diff --git a/README.md b/README.md index 8038481..3bc0656 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ All math is handled by Enigma. All you have to do is to put in few basic numbers ## How to use it -Include the sass files from `dist/` folder and you are ready to go. +Include the sass files from `dist/` folder and add `_enigma.scss` into your main sass file and you are ready to go. Enigma offers few functions and one mixin to make setting up typography and vertycal rhythm easy. All you have to do is to give Enigma some basic settings for you project. (well you don't have to do it as Enigma have some defaults but if you really care about nice typography, then you will do it). diff --git a/dist/_enigma.scss b/dist/_enigma.scss new file mode 100644 index 0000000..c2c00c7 --- /dev/null +++ b/dist/_enigma.scss @@ -0,0 +1,11 @@ +/// Enigma files +// default settings +@import './partials/defaults'; + +// Control blocks +@import './partials/functions'; +@import './partials/mixins'; + +// Debug tools for vertical rhythm +@import './partials/tools'; + diff --git a/dist/partials/_defaults.scss b/dist/partials/_defaults.scss new file mode 100644 index 0000000..384c871 --- /dev/null +++ b/dist/partials/_defaults.scss @@ -0,0 +1,27 @@ +/// TODO - rename to settings +/* +root - font size at root element, it = 1rem +base - font size of body text (paragraph) +unit - unit to calculate all sizes in +alfa - primary scale +beta - secondary scale, optional +start - start/smalles index of scale - used to improve performance +stop - larges index of scale - used to improve performance +line-shift - align lines to be exactly below text, not in the middle +line-color - color of debug lines +All dimension must be in pixels +*/ +$enigma-defaults: ( + 'root': 16px, + 'base': 16px, + 'unit': 1rem, + 'alfa': 1.5, + 'beta': null, + 'start': -3, + 'stop': 5, + 'line-shift': -7px, + 'line-color': #15ADE6 +); + +// Custom settings map (empty for merge) +$enigma: () !default; \ No newline at end of file diff --git a/dist/partials/_functions.scss b/dist/partials/_functions.scss new file mode 100644 index 0000000..e1eaabe --- /dev/null +++ b/dist/partials/_functions.scss @@ -0,0 +1,206 @@ +/// ------------------------ +/// HELPER FUNCTIONS +/// ------------------------ + +/// Removes unit from number +@function stripUnit ( $number ) { + $unit: $number * 0 + 1; + @return ($number / $unit); +} + +/// TODO not used, delete +@function enigmaRound ( $number, $root ) { + @return (round( $number * $root ) / $root ); +} + +/// Returns basic font size +/// @param $unit - Bool - return number with unit set in options or without unit +@function enigmaBase( $unit: false) { + $enigma-opt: enigmaSettings(); + + @if $unit { + @return ( map_get($enigma-opt, 'base') / map_get($enigma-opt, 'root') ) * map_get($enigma-opt, 'unit') ; + } @else { + @return map_get($enigma-opt, 'base') / map_get($enigma-opt, 'root'); + } +} + +/// Merge default and user settings +@function enigmaSettings () { + @if length($enigma) > 0 { + @return map_merge( $enigma-defaults, $enigma); + } @else { + @return $enigma-defaults; + } +} + +/// Power function +@function enigmaPower( $exponent, $scale ) { + $result: $scale; + + @if $exponent > 0 { + @for $i from 1 to $exponent { + $result: $result * $scale; + } + } @else { + @for $i from 1 to $exponent { + $result: $result / $scale; + } + } + + @return $result; +} + +/// Quick sort +/// @author Sam Richards +/// @param {List} $list - list to sort +/// @return {List} +@function quick-sort($list) { + $less: (); + $equal: (); + $large: (); + + @if length($list) > 1 { + $seed: nth($list, ceil(length($list) / 2)); + + @each $item in $list { + @if ($item == $seed) { + $equal: append($equal, $item); + } @else if ($item < $seed) { + $less: append($less, $item); + } @else if ($item > $seed) { + $large: append($large, $item); + } + } + + @return join(join(quick-sort($less), $equal), quick-sort($large)); + } + + @return $list; +} + +/// Generate list from two scales +@function generateScale( $lvl, $scales) { + $result: 1; + + // Generate list of scale values + @if $lvl != 0 { + $start: $lvl / abs($lvl); + + @each $scale in $scales { + @for $i from $start through $lvl { + $result: join($result, enigmaPower($i, $scale) ); + } + } + } + + // Sort the list + $result: quick-sort($result); + + @return $result; +} + + + +/// ------------------------ +/// VERTICAL RHYTHM FUNCTIONS +/// ------------------------ + +/// Spacing function to keep vertical rhytm consistent +/// can be used for margin, padding etc. +/// @return multiplication of line height +/// $lvl doesn't have to be integer +@function enigmaLeading ( $lvl: 1 ) { + $enigma-opt: enigmaSettings(); + $enigma-base: enigmaBase(); + + // Return specified number of lines + @return map_get($enigma-opt, 'alfa') * $enigma-base * map_get($enigma-opt, 'unit') * $lvl; +} + +/// Function to calculate size based on scale +/// @param $lvl - Number - position on scale to use as font size +/// @param $scale - String - optional, which scale should be used +/// +/// If only one argument provided function return font-size based on both +/// scales (merged scale, if more scales defined). +/// In case of two arguments function return font size on position of +/// specified scale +@function enigmaSize ( $lvl: 0, $scale: null ) { + $enigma-opt: enigmaSettings(); + $enigma-base: enigmaBase(true); + $scales: null; + $index: 0; + + // No scale selected, take value from combination of both scales + @if $scale == null { + + // Create list from alfa and beta scales + @if map_get($enigma-opt, 'beta') == null { + + // return normal power value if no beta is defined + @return enigmaPower( $lvl, map_get($enigma-opt, 'alfa') ) * $enigma-base; + + } @else { + $scales: generateScale( $lvl, map_get($enigma-opt, 'alfa') map_get($enigma-opt, 'beta') ); + } + + // Modify $lvl to reflext that list contains 1 as well + @if $lvl > 0 { + $index: $lvl + 1; + } @else { + $index: $lvl - 1; + } + + // Get the correct index + @return nth( $scales, $index ) * $enigma-base; + + // Return value for only one scale + } @else { + @if map_get($enigma-opt, $scale) == null { + @error 'Scale #{$scale} is not defined.'; + } + @return enigmaPower( $lvl, map_get($enigma-opt, $scale) ) * $enigma-base; + } +} + +/// Function to calculate correct line height to keep +/// vertical rhythm consistent +/// $lh-args: $lvl, real, at N +/// $lvl {Number} - for what font-size will the line-height be calculated +/// real - keyword - $lvl is exact line-height, no calculation is done +/// of N - line-height will align itself to proper vertical rhytm after N lines +/// eg. 3 of 4 - 4 lines are equal to 3 standart lines - useful for smaller texts +@function enigmaLine ( $lh-args, $scale: null ) { + // Parse line-height arguments + $lvl: nth( $lh-args, 1); + $real: index($lh-args, 'real'); + $at: index($lh-args, 'at'); + + // Other variables + $enigma-opt: enigmaSettings(); + $n: 1; + $text-size: enigmaSize($lvl, $scale); + + // Return value + $lh: enigmaLeading(); + + // Line height calculation + // if the line-hegiht value is real value + @if ( $real ) { + @return $lvl; + } + + // Find out how many lines will be necessary for this font size + $n: ceil($text-size / $lh); + $n: stripUnit($n); + + $lh: $lh / $text-size; + + // N at M calculation + @if $at { + $lh: $lh * nth( $lh-args, $at + 1); + } + + @return $lh * $n; +} \ No newline at end of file diff --git a/dist/partials/_mixins.scss b/dist/partials/_mixins.scss new file mode 100644 index 0000000..9916237 --- /dev/null +++ b/dist/partials/_mixins.scss @@ -0,0 +1,80 @@ +/// Set basic text properties based on base font size and scale +/// FIXME - popis +/// Mixin bere parametry ve tvaru (2 / 1.2 3 1) kde parametry jsou následující +/// 2 - velikost textu dle stupnice (nepovinný parametr, default je jedna) +/// 1.2 - vlastní řádkování (nepovinný parametr default je dle stupnice) +/// 3 - margin top (nepov paramater, pokud není zadán, margin je 0) +/// 1 - margin bottom - jedná se o násobek leadingu (defaultní výšky řádku) (nepovinný parametr, pokud není zadán, margin je 0) +/// Pokud je třeba zadat pouze margin bottom a top nechceme měnit, je možné použít klíčové slovo base, které zachová hodnotu margin top nezměněnou + +/// [ FZ ] [ scale ] on [ LH | FZ at Q ] with [ MT MB ] +@mixin enigma ( $keywords: () ) { + // Prepare parametr variables + $lvl: 0; + $lh-args: 0; + $scale: null; + $on: index( $keywords, 'on' ); + $at: index( $keywords, 'at' ); + $margins: index( $keywords, 'with'); + + // Process keywords variables + // Get position on modular scale + @if length( $keywords ) != 0 { + $lvl: nth( $keywords, 1 ); + @if type-of( $lvl ) != number { + @error 'First argument must be a integer number, not a #{ type-of($lvl) }'; + } + } + + // Get modular scale used to calculate sizes + @if ( length($keywords) > 1 and ( nth($keywords, 2) == 'alfa' or nth($keywords, 2) == 'beta' ) ) { + $scale: nth($keywords, 2); + } + + font-size: enigmaSize( $lvl, $scale ); + + + // Create line-height arguments + @if $on { + + $lh-args: nth( $keywords, $on + 1 ); + + @if $at { + @for $i from $at through ( ( $margins or length($keywords) + 1 ) - 1 ) { + $lh-args: join( $lh-args, nth( $keywords, $i)); + } + + } @else { + $lh-args: append( $lh-args, 'real'); + } + + // no line-height argument - calculate line height based on font size + } @else { + $lh-args: $lvl; + } + + line-height: enigmaLine( $lh-args, $scale ); + + + // Add margins to text element + // Custom margins if defined + @if $margins { + + // Set margin-top if keyword 'base' is not used + @if ( nth( $keywords, $margins + 1 ) ) != 'base' { + $mt: nth( $keywords, $margins + 1 ); + margin-top: enigmaLeading( $mt ); + } + + // Set margin-bottom if second margin parametr was used + @if ( length($keywords) >= $margins + 2 ) and ( type-of(nth( $keywords, $margins + 2 ) ) == 'number' ) { + $mb: nth( $keywords, $margins + 2 ); + margin-bottom: enigmaLeading( $mb ); + } + + // Add default margins if with declaration omitted + } @else { + margin-top: enigmaLeading( 1 ); + margin-bottom: enigmaLeading( 1 ); + } +} diff --git a/dist/partials/_tools.scss b/dist/partials/_tools.scss new file mode 100644 index 0000000..5eb312c --- /dev/null +++ b/dist/partials/_tools.scss @@ -0,0 +1,18 @@ +// Create grid lines for debug purpose +// [1] - enigmaLeading caused some issues, so the size is defined same way +// as gradient +@mixin enig-grid () { + $enigma-opt: enigmaSettings(); + + $line-stop: map_get($enigma-opt, 'base') * map_get($enigma-opt, 'alfa') + map_get($enigma-opt, 'line-shift'); + + background: linear-gradient( + transparent $line-stop - 1px, + map_get($enigma-opt, 'line-color') $line-stop - 1px, + map_get($enigma-opt, 'line-color') $line-stop, + transparent $line-stop + ) !important; + background-position: 0 0 !important; + background-size: 100% ( map_get($enigma-opt, 'base') * map_get($enigma-opt, 'alfa')) !important; // [1] + background-repeat: repeat-y !important; +} \ No newline at end of file