1// SASSY MODULAR-SCALE 2// https://github.com/scottkellum/modular-scale 3 4// Defaults 5$ratio: golden_ratio() !default; 6$base-size: 16px !default; 7$round-pixels: true !default; 8 9// Modular Scale function 10@function modular-scale($multiple, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 11 12 // return the $base-size if $multiple is zero 13 @if $multiple == 0 { 14 @if type-of($base-size) == "list" { 15 $base-size: sort_list($base-size); 16 @return nth($base-size, 1); 17 } 18 19 // return just the simple $base-size value if it's not a list 20 @return $base-size; 21 } 22 23 // if multiple base-sizes are passed in as a list 24 // and multiple ratios are passed in as a list 25 // calculate values in using each base-size / ratio combination 26 @if type-of($base-size) == "list" and type-of($ratio) == "list" { 27 @if unit(ms-multibase-multiratio($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { 28 @return round(ms-multibase-multiratio($multiple, $base-size, $ratio)); 29 } 30 @return ms-multibase-multiratio($multiple, $base-size, $ratio); 31 } 32 33 // if multiple base-sizes are passed in as a list 34 // calculate values in using each base-size 35 @if type-of($base-size) == "list" and type-of($ratio) == "number" { 36 @if unit(ms-multibase($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { 37 @return round(ms-multibase($multiple, $base-size, $ratio)); 38 } 39 @return ms-multibase($multiple, $base-size, $ratio); 40 } 41 42 // if multiple ratios are passed in as a list 43 // calculate values in using each ratio 44 @if type-of($base-size) == "number" and type-of($ratio) == "list" { 45 @if unit(ms-multiratio($multiple, $base-size, $ratio)) == "px" and $round-pixels == true { 46 @return round(ms-multiratio($multiple, $base-size, $ratio)); 47 } 48 @return ms-multiratio($multiple, $base-size, $ratio); 49 } 50 51 // If there are no lists just run the simple function 52 @if unit(power($ratio, $multiple) * $base-size) == "px" and $round-pixels == true { 53 @return round(power($ratio, $multiple) * $base-size); 54 } 55 @return power($ratio, $multiple) * $base-size; 56} 57 58// calculate values in using each base-size / ratio combination 59@function ms-multibase-multiratio($multiple, $base-size: $base-size, $ratio: $ratio) { 60 61 // start with an empty list to place all values in 62 $scale-values: (); 63 64 // make sure base sizes are in ascending order 65 $base-size: sort_list($base-size); 66 67 // take each base-size in turn 68 $k: 1; 69 @while $k <= length($base-size) { 70 71 // add each $base-size to the list except the first 72 @if $k > 1 { 73 $scale-values: append($scale-values, nth($base-size, $k)); 74 } 75 76 // take each ratio in turn 77 $j: 1; 78 @while $j <= length($ratio) { 79 80 // reset $modular-scale for each set 81 $modular-scale: nth($base-size, $k); 82 83 // do the scale for each base-size using this ratio 84 @if $multiple > 0 { 85 86 // up $multiple times 87 // and add the result to $scale-values 88 @for $i from 1 through $multiple { 89 $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); 90 $scale-values: append($scale-values, $modular-scale); 91 } 92 93 // and down until the value is lower than the lowest $base-size 94 // and add the result to $scale-values 95 $i: -1; 96 $modular-scale: nth($base-size, $k); 97 @while $modular-scale >= nth($base-size, 1) { 98 $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); 99 $scale-values: append($scale-values, $modular-scale); 100 $i: $i - 1; 101 } 102 } 103 @if $multiple < 0 { 104 105 // do the scale down for each set to below 1px 106 $i: 0; 107 $modular-scale: nth($base-size, $k); 108 @while $i >= $multiple { 109 $modular-scale: power(nth($ratio, $j), $i) * nth($base-size, $k); 110 $scale-values: append($scale-values, $modular-scale); 111 $i: $i - 1; 112 } 113 } 114 $j: $j + 1; 115 } 116 $k: $k + 1; 117 } 118 119 // return trimmed and sorted final list 120 @return trim-sort($multiple, $scale-values, $base-size); 121} 122 123// calculate values in using each base-size 124@function ms-multibase($multiple, $base-size: $base-size, $ratio: $ratio) { 125 126 // start with an empty list to place all values in 127 $scale-values: (); 128 129 // make sure base sizes are in ascending order 130 $base-size: sort_list($base-size); 131 132 // take each base-size in turn 133 $k: 1; 134 @while $k <= length($base-size) { 135 136 // add each $base-size to the list except the first 137 @if $k > 1 { 138 $scale-values: append($scale-values, nth($base-size, $k)); 139 } 140 141 // reset $modular-scale for each set 142 $modular-scale: nth($base-size, $k); 143 144 // do the scale for each base-size using this ratio 145 @if $multiple > 0 { 146 147 // up $multiple times 148 // and add the result to $scale-values 149 @for $i from 1 through $multiple { 150 $modular-scale: power($ratio, $i) * nth($base-size, $k); 151 $scale-values: append($scale-values, $modular-scale); 152 } 153 154 // and down until the value is lower than the lowest $base-size 155 // and add the result to $scale-values 156 $i: -1; 157 $modular-scale: nth($base-size, $k); 158 @while $modular-scale >= nth($base-size, 1) { 159 $modular-scale: power($ratio, $i) * nth($base-size, $k); 160 $scale-values: append($scale-values, $modular-scale); 161 $i: $i - 1; 162 } 163 } 164 @if $multiple < 0 { 165 166 // do the scale down for each set to below 1px 167 $i: 0; 168 $modular-scale: nth($base-size, $k); 169 @while $i >= $multiple { 170 $modular-scale: power($ratio, $i) * nth($base-size, $k); 171 $scale-values: append($scale-values, $modular-scale); 172 $i: $i - 1; 173 } 174 } 175 $k: $k + 1; 176 } 177 178 // return trimmed and sorted final list 179 @return trim-sort($multiple, $scale-values, $base-size); 180} 181 182// calculate values in using each ratio 183@function ms-multiratio($multiple, $base-size: $base-size, $ratio: $ratio) { 184 185 // start with an empty list to place all values in 186 $scale-values: (); 187 188 // If $multiple is a positive integer (up the scale) 189 @if $multiple > 0 { 190 191 // take each ratio in turn 192 $j: 1; 193 @while $j <= length($ratio) { 194 195 // reset $modular-scale for each set 196 $modular-scale: $base-size; 197 198 // do the scale using this ratio thru the multiple, and add the result to $scale-values 199 @for $i from 1 through $multiple { 200 $modular-scale: power(nth($ratio, $j), $i) * $base-size; 201 $scale-values: append($scale-values, $modular-scale); 202 } 203 $j: $j + 1; 204 } 205 206 // sort acsending 207 $scale-values: sort_list($scale-values); 208 209 // return the final value using the laced list 210 @return nth($scale-values, $multiple); 211 } 212 213 // If $multiple is a negative integer (down the scale) 214 @if $multiple < 0 { 215 216 // take each ratio in turn 217 $j: 1; 218 @while $j <= length($ratio) { 219 220 // reset $modular-scale for each set 221 $modular-scale: $base-size; 222 223 // do the scale using this ratio thru the multiple, and add the result to $scale-values 224 @for $i from 1 through $multiple * -1 { 225 $modular-scale: power(nth($ratio, $j), -$i) * $base-size; 226 $scale-values: append($scale-values, $modular-scale); 227 } 228 $j: $j + 1; 229 } 230 231 // sort decending 232 $scale-values: reverse_list(sort_list($scale-values)); 233 234 // return the final value using the laced list 235 @return nth($scale-values, $multiple * -1); 236 } 237} 238 239// trim and sort the final list 240@function trim-sort($multiple, $scale-values: $scale-values, $base-size: $base-size) { 241 @if $multiple > 0 { 242 243 // trim list so we can count from the lowest $base-size 244 $scale-values: trim_list($scale-values, nth($base-size, 1), true); 245 246 // sort acsending 247 $scale-values: sort_list($scale-values); 248 249 // return the final value using the laced list 250 @return nth($scale-values, $multiple); 251 } 252 @else { 253 254 // trim list so we can count from the lowest $base-size 255 $scale-values: trim_list($scale-values, nth($base-size, 1), false); 256 257 // sort acsending 258 $scale-values: reverse_list(sort_list($scale-values)); 259 260 // return the final value using the laced list 261 @return nth($scale-values, -$multiple); 262 } 263} 264 265///////////////////////////////////////////////////////////////////////// 266 267// alias for golden_ratio() 268@function golden() { 269 @return golden_ratio(); 270} 271 272// Shortcut 273@function ms($multiple, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 274 // Return the value from the Modular Scale function 275 @return modular-scale($multiple, $base-size, $ratio, $round-pixels); 276} 277 278// Write Modular Scale List 279@function modular-scale-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 280 $ms-list: unquote("MS-LIST:"); 281 @for $i from $start through $finish { 282 $ms-list: append($ms-list, ms($i, $base-size, $ratio, $round-pixels)); 283 } 284 @return $ms-list; 285} 286 287@function ms-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 288 @return modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); 289} 290 291@mixin modular-scale-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 292 @debug modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); 293} 294 295@mixin ms-list($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 296 @debug modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); 297} 298 299@mixin modular-scale-list-output($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 300 MODULAR-SCALE-LIST { 301 ms-list: modular-scale-list($start, $finish, $base-size, $ratio, $round-pixels); 302 } 303 } 304 305@mixin ms-list-output($start: 0, $finish: 20, $base-size: $base-size, $ratio: $ratio, $round-pixels: $round-pixels) { 306 @include modular-scale-list-output($start, $finish, $base-size, $ratio, $round-pixels); 307} 308 309// Other libraries can easily query if this function is avalible 310$modular-scale-loaded: true;