// SASSY MODULAR-SCALE // https://github.com/scottkellum/modular-scale // Defaults $ratio: golden_ratio() !default; $base-size: 16px !default; $round-pixels: true !default; // Modular Scale function @function modular-scale($multiple, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { // return the $base-size if $multiple is zero @if $multiple == 0 { @if type-of($base-size) == "list" { $base-size: sort_list($base-size); @return nth($base-size, 1); } // return just the simple $base-size value if it's not a list @return $base-size; } // if multiple base-sizes are passed in as a list // and multiple ratios are passed in as a list // calculate values in using each base-size / ratio combination @if type-of($base-size) == "list" and type-of($ratio) == "list" { @if unit(ms-multibase-multiratio($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { @return round(ms-multibase-multiratio($multiple, $base-size, $ratio)); } @return ms-multibase-multiratio($multiple, $base-size, $ratio); } // if multiple base-sizes are passed in as a list // calculate values in using each base-size @if type-of($base-size) == "list" and type-of($ratio) == "number" { @if unit(ms-multibase($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { @return round(ms-multibase($multiple, $base-size, $ratio)); } @return ms-multibase($multiple, $base-size, $ratio); } // if multiple ratios are passed in as a list // calculate values in using each ratio @if type-of($base-size) == "number" and type-of($ratio) == "list" { @if unit(ms-multiratio($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { @return round(ms-multiratio($multiple, $base-size, $ratio)); } @return ms-multiratio($multiple, $base-size, $ratio); } // If there are no lists just run the simple function @if unit(power($ratio, $multiple) * $base-size) == "px" and $round-pixels == true { @return round(power($ratio, $multiple) * $base-size); } @return power($ratio, $multiple) * $base-size; } // calculate values in using each base-size / ratio combination @function ms-multibase-multiratio($multiple, $base-size: $base-size, $ratio: $ratio) { // start with an empty list to place all values in $scale-values: (); // make sure base sizes are in ascending order $base-size: sort_list($base-size); // take each base-size in turn $k: 1; @while $k <= length($base-size) { // add each $base-size to the list except the first @if $k > 1 { $scale-values: append($scale-values, nth($base-size, $k)); } // take each ratio in turn $j: 1; @while $j <= length($ratio) { // reset $modular-scale for each set $modular-scale: nth($base-size, $k); // do the scale for each base-size using this ratio @if $multiple > 0 { // up $multiple times // and add the result to $scale-values @for $i from 1 through $multiple { $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); } // and down until the value is lower than the lowest $base-size // and add the result to $scale-values $i: -1; $modular-scale: nth($base-size, $k); @while $modular-scale >= nth($base-size, 1) { $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); $i: $i - 1; } } @if $multiple < 0 { // do the scale down for each set to below 1px $i: 0; $modular-scale: nth($base-size, $k); @while $i >= $multiple { $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); $i: $i - 1; } } $j: $j + 1; } $k: $k + 1; } // return trimmed and sorted final list @return trim-sort($multiple, $scale-values, $base-size); } // calculate values in using each base-size @function ms-multibase($multiple, $base-size: $base-size, $ratio: $ratio) { // start with an empty list to place all values in $scale-values: (); // make sure base sizes are in ascending order $base-size: sort_list($base-size); // take each base-size in turn $k: 1; @while $k <= length($base-size) { // add each $base-size to the list except the first @if $k > 1 { $scale-values: append($scale-values, nth($base-size, $k)); } // reset $modular-scale for each set $modular-scale: nth($base-size, $k); // do the scale for each base-size using this ratio @if $multiple > 0 { // up $multiple times // and add the result to $scale-values @for $i from 1 through $multiple { $modular-scale: power($ratio, $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); } // and down until the value is lower than the lowest $base-size // and add the result to $scale-values $i: -1; $modular-scale: nth($base-size, $k); @while $modular-scale >= nth($base-size, 1) { $modular-scale: power($ratio, $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); $i: $i - 1; } } @if $multiple < 0 { // do the scale down for each set to below 1px $i: 0; $modular-scale: nth($base-size, $k); @while $i >= $multiple { $modular-scale: power($ratio, $i) * nth($base-size, $k); $scale-values: append($scale-values, $modular-scale); $i: $i - 1; } } $k: $k + 1; } // return trimmed and sorted final list @return trim-sort($multiple, $scale-values, $base-size); } // calculate values in using each ratio @function ms-multiratio($multiple, $base-size: $base-size, $ratio: $ratio) { // start with an empty list to place all values in $scale-values: (); // If $multiple is a positive integer (up the scale) @if $multiple > 0 { // take each ratio in turn $j: 1; @while $j <= length($ratio) { // reset $modular-scale for each set $modular-scale: $base-size; // do the scale using this ratio thru the multiple, and add the result to $scale-values @for $i from 1 through $multiple { $modular-scale: power(nth($ratio, $j), $i) * $base-size; $scale-values: append($scale-values, $modular-scale); } $j: $j + 1; } // sort acsending $scale-values: sort_list($scale-values); // return the final value using the laced list @return nth($scale-values, $multiple); } // If $multiple is a negative integer (down the scale) @if $multiple < 0 { // take each ratio in turn $j: 1; @while $j <= length($ratio) { // reset $modular-scale for each set $modular-scale: $base-size; // do the scale using this ratio thru the multiple, and add the result to $scale-values @for $i from 1 through $multiple * -1 { $modular-scale: power(nth($ratio, $j), -$i) * $base-size; $scale-values: append($scale-values, $modular-scale); } $j: $j + 1; } // sort decending $scale-values: reverse_list(sort_list($scale-values)); // return the final value using the laced list @return nth($scale-values, $multiple * -1); } } // trim and sort the final list @function trim-sort($multiple, $scale-values: $scale-values, $base-size: $base-size) { @if $multiple > 0 { // trim list so we can count from the lowest $base-size $scale-values: trim_list($scale-values, nth($base-size, 1), true); // sort acsending $scale-values: sort_list($scale-values); // return the final value using the laced list @return nth($scale-values, $multiple); } @else { // trim list so we can count from the lowest $base-size $scale-values: trim_list($scale-values, nth($base-size, 1), false); // sort acsending $scale-values: reverse_list(sort_list($scale-values)); // return the final value using the laced list @return nth($scale-values, -$multiple); } } ///////////////////////////////////////////////////////////////////////// // alias for golden_ratio() @function golden() { @return golden_ratio(); } // Shortcut @function ms($multiple, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { // Return the value from the Modular Scale function @return modular-scale($multiple, $base-size, $ratio, $round-pixels); } // Write Modular Scale List @function modular-scale-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { $ms-list: unquote("MS-LIST:"); @for $i from $start through $finish { $ms-list: append($ms-list, ms($i, $base-size, $ratio, $round-pixels)); } @return $ms-list; } @function ms-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { @return modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); } @mixin modular-scale-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { @debug modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); } @mixin ms-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { @debug modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); } @mixin modular-scale-list-output($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { MODULAR-SCALE-LIST { ms-list: modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); } } @mixin ms-list-output($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { @include modular-scale-list-output($start, $finish, $base-size, $ratio, $round-pixels); } // Other libraries can easily query if this function is avalible $modular-scale-loaded: true;