diff options
Diffstat (limited to 'src/_gradients.scss')
-rw-r--r-- | src/_gradients.scss | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/src/_gradients.scss b/src/_gradients.scss new file mode 100644 index 0000000..7c52d63 --- /dev/null +++ b/src/_gradients.scss | |||
@@ -0,0 +1,600 @@ | |||
1 | //// | ||
2 | /// Smoother background gradients. | ||
3 | /// | ||
4 | /// The default background gradients produced by any browser have a quite harsh transition between | ||
5 | /// colors. This is especially apparent if you, for example, use a strong fade-out gradient to make | ||
6 | /// text in front of a background more readable. | ||
7 | /// | ||
8 | /// The function in this file generates smoother gradients by using easing functions of the user's | ||
9 | /// choice. | ||
10 | /// It's essentially a more flexible alternative to the PostCSS plugin "PostCSS Easing Gradients": | ||
11 | /// https://github.com/larsenwork/postcss-easing-gradients | ||
12 | /// | ||
13 | /// @group Background gradients | ||
14 | /// | ||
15 | /// @access public | ||
16 | //// | ||
17 | |||
18 | /// | ||
19 | /// Number of intermediate color stops generated to achieve easing. | ||
20 | /// A higher value results in better quality, but also much more generated code. | ||
21 | /// | ||
22 | /// @type number | ||
23 | /// | ||
24 | $iro-easing-gradient-steps: 10 !default; | ||
25 | |||
26 | /// | ||
27 | /// Generate a new easing background gradient. | ||
28 | /// This function is intended to be as similar as possible to the newly proposed syntax for | ||
29 | /// linear-gradient and radial-gradient which includes easing hints. | ||
30 | /// | ||
31 | /// @param {string} $type - Either 'linear' or 'radial', which means the gradient will be either a linear-gradient or a radial-gradient. | ||
32 | /// @param {string} $dir - The direction of the gradient. Depending on $type, this value must be a valid direction for linear-gradient or radial-gradient. | ||
33 | /// @param {color | list} $stop - A color stop as used for linear-gradient or radial-gradient. | ||
34 | /// @param {arglist} $stops - More color stops as used for linear-gradient or radial-gradient. Between two color stops, you may also define an easing hint such as `ease-in-out`, `cubic-bezier 0.42 0 0.58 1`, `steps 3 jump-end`, and so on. | ||
35 | /// | ||
36 | /// @return {string} A linear-gradient or radial-gradient with an alternative transitioning behavior. | ||
37 | /// | ||
38 | /// @throw If $type is invalid | ||
39 | /// | ||
40 | /// @link https://github.com/w3c/csswg-drafts/issues/1332 The new CSSWG proposal | ||
41 | /// | ||
42 | /// @example scss - A smoother linear gradient | ||
43 | /// .background { | ||
44 | /// background-image: iro-easing-gradient( | ||
45 | /// linear, | ||
46 | /// to top, | ||
47 | /// #000, | ||
48 | /// in-out-sine, | ||
49 | /// transparent | ||
50 | /// ); | ||
51 | /// } | ||
52 | /// | ||
53 | /// // Generates: | ||
54 | /// | ||
55 | /// .background { | ||
56 | /// background-image: linear-gradient( | ||
57 | /// to top, | ||
58 | /// black 0%, | ||
59 | /// rgba(0, 0, 0, 0.975528) 10%, | ||
60 | /// rgba(0, 0, 0, 0.904508) 20%, | ||
61 | /// rgba(0, 0, 0, 0.793893) 30%, | ||
62 | /// rgba(0, 0, 0, 0.654508) 40%, | ||
63 | /// rgba(0, 0, 0, 0.5) 50%, | ||
64 | /// rgba(0, 0, 0, 0.345492) 60%, | ||
65 | /// rgba(0, 0, 0, 0.206107) 70%, | ||
66 | /// rgba(0, 0, 0, 0.0954915) 80%, | ||
67 | /// rgba(0, 0, 0, 0.0244717) 90%, | ||
68 | /// rgba(0, 0, 0, 3.78257e-11) 100% | ||
69 | /// ); | ||
70 | /// } | ||
71 | /// | ||
72 | /// @example scss - A smoother radial gradient | ||
73 | /// .background { | ||
74 | /// background-image: iro-easing-gradient( | ||
75 | /// radial, | ||
76 | /// 50em 16em at 0 0, | ||
77 | /// #000, | ||
78 | /// in-out-sine, | ||
79 | /// transparent | ||
80 | /// ); | ||
81 | /// } | ||
82 | /// | ||
83 | /// // Generates: | ||
84 | /// | ||
85 | /// .background { | ||
86 | /// background-image: radial-gradient( | ||
87 | /// 50em 16em at 0 0, | ||
88 | /// black 0%, | ||
89 | /// rgba(0, 0, 0, 0.975528) 10%, | ||
90 | /// rgba(0, 0, 0, 0.904508) 20%, | ||
91 | /// rgba(0, 0, 0, 0.793893) 30%, | ||
92 | /// rgba(0, 0, 0, 0.654508) 40%, | ||
93 | /// rgba(0, 0, 0, 0.5) 50%, | ||
94 | /// rgba(0, 0, 0, 0.345492) 60%, | ||
95 | /// rgba(0, 0, 0, 0.206107) 70%, | ||
96 | /// rgba(0, 0, 0, 0.0954915) 80%, | ||
97 | /// rgba(0, 0, 0, 0.0244717) 90%, | ||
98 | /// rgba(0, 0, 0, 3.78257e-11) 100% | ||
99 | /// ); | ||
100 | /// } | ||
101 | /// | ||
102 | /// @example scss - A smoother linear gradient with complex color positions | ||
103 | /// .background { | ||
104 | /// background-image: iro-easing-gradient( | ||
105 | /// linear, | ||
106 | /// to top, | ||
107 | /// #000 20%, | ||
108 | /// in-out-sine, | ||
109 | /// transparent calc(20% + 25em) | ||
110 | /// ); | ||
111 | /// } | ||
112 | /// | ||
113 | /// // Generates: | ||
114 | /// | ||
115 | /// .background { | ||
116 | /// background-image: linear-gradient( | ||
117 | /// to top, | ||
118 | /// black 20%, | ||
119 | /// rgba(0, 0, 0, 0.975528) calc(20% + (20% + 25em - 20%) * 0.1), | ||
120 | /// rgba(0, 0, 0, 0.904508) calc(20% + (20% + 25em - 20%) * 0.2), | ||
121 | /// rgba(0, 0, 0, 0.793893) calc(20% + (20% + 25em - 20%) * 0.3), | ||
122 | /// rgba(0, 0, 0, 0.654508) calc(20% + (20% + 25em - 20%) * 0.4), | ||
123 | /// rgba(0, 0, 0, 0.5) calc(20% + (20% + 25em - 20%) * 0.5), | ||
124 | /// rgba(0, 0, 0, 0.345492) calc(20% + (20% + 25em - 20%) * 0.6), | ||
125 | /// rgba(0, 0, 0, 0.206107) calc(20% + (20% + 25em - 20%) * 0.7), | ||
126 | /// rgba(0, 0, 0, 0.0954915) calc(20% + (20% + 25em - 20%) * 0.8), | ||
127 | /// rgba(0, 0, 0, 0.0244717) calc(20% + (20% + 25em - 20%) * 0.9), | ||
128 | /// transparent calc(20% + 25em)) | ||
129 | /// ); | ||
130 | /// } | ||
131 | /// | ||
132 | @function iro-easing-gradient($type, $dir, $stop, $stops...) { | ||
133 | $pos-template: null; | ||
134 | $stops: iro-list-prepend($stops, $stop); | ||
135 | |||
136 | $last-positioned-stop: 1; | ||
137 | $generated-stops: (); | ||
138 | |||
139 | // | ||
140 | // Generate gradient | ||
141 | // | ||
142 | |||
143 | @for $i from 1 through length($stops) { | ||
144 | $stop: nth($stops, $i); | ||
145 | |||
146 | @if $i == 1 { | ||
147 | @if not iro-easing-gradient-is-color-stop($stop) { | ||
148 | @error 'The first color stop argument must be a color stop.'; | ||
149 | } | ||
150 | |||
151 | @if type-of($stop) == color { | ||
152 | // | ||
153 | // The first color stop is unpositioned. The default position for the first | ||
154 | // color stop is 0, which is explicitly added for easier calculations. | ||
155 | // | ||
156 | |||
157 | $stop: $stop 0; | ||
158 | $stops: set-nth($stops, $i, $stop); | ||
159 | } | ||
160 | |||
161 | $generated-stops: append($generated-stops, iro-str-implode($stop, ' ')); | ||
162 | } @else if iro-easing-gradient-is-positioned-color-stop($stop) or ($i == length($stops)) { | ||
163 | @if not iro-easing-gradient-is-color-stop($stop) { | ||
164 | @error 'The last color stop argument must be a color stop.'; | ||
165 | } | ||
166 | |||
167 | // | ||
168 | // Either the current stops list item is a positioned color stop, or the end of | ||
169 | // the stops list has been reached. | ||
170 | // | ||
171 | |||
172 | @if (type-of($stop) == color) and ($i == length($stops)) { | ||
173 | // | ||
174 | // The current stop is an unpositioned color stop, which means this is the end | ||
175 | // of the stops list. The default position for the last color stop is 100%, which | ||
176 | // is explicitly added for easier calculations. | ||
177 | // | ||
178 | |||
179 | $stop: $stop 100%; | ||
180 | $stops: set-nth($stops, $i, $stop); | ||
181 | } | ||
182 | |||
183 | // | ||
184 | // Now the current color stop is guaranteed to be a positioned color stop. | ||
185 | // | ||
186 | |||
187 | @if $i > $last-positioned-stop + 1 { | ||
188 | // | ||
189 | // There is at least one stops list item (unpositioned color stop or easing function) | ||
190 | // between the last positioned color stop and the current stops list item. Interpolate | ||
191 | // the positions of all stops list items that are color stops. | ||
192 | // | ||
193 | |||
194 | $interpolated-stops: iro-easing-gradient-interpolate-stop-positions( | ||
195 | nth($stops, $last-positioned-stop), | ||
196 | iro-list-slice($stops, $last-positioned-stop + 1, $i - 1), | ||
197 | $stop | ||
198 | ); | ||
199 | |||
200 | $new-stops: join( | ||
201 | iro-list-slice($stops, 1, $last-positioned-stop), | ||
202 | $interpolated-stops | ||
203 | ); | ||
204 | $new-stops: join( | ||
205 | $new-stops, | ||
206 | iro-list-slice($stops, $i) | ||
207 | ); | ||
208 | $stops: $new-stops; | ||
209 | } | ||
210 | |||
211 | // | ||
212 | // Now all color stops between this one and the last positioned one have | ||
213 | // interpolated positions. | ||
214 | // Next task is to perform an easing transition between all color stops that | ||
215 | // have an easing function specified. The rest can be left alone since the | ||
216 | // browser will automatically apply a linear transition between them. | ||
217 | // | ||
218 | |||
219 | $j: $last-positioned-stop + 1; | ||
220 | @while $j <= $i { | ||
221 | $easing: null; | ||
222 | $prev-stop: nth($stops, $j - 1); | ||
223 | $next-stop: nth($stops, $j); | ||
224 | |||
225 | @if not iro-easing-gradient-is-color-stop($next-stop) { | ||
226 | $j: $j + 1; | ||
227 | |||
228 | $easing: $next-stop; | ||
229 | $next-stop: nth($stops, $j); | ||
230 | |||
231 | @if not iro-easing-gradient-is-color-stop($next-stop) { | ||
232 | @error 'There can be at most one interpolation hint between to color stops.'; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | @if $easing != null { | ||
237 | @if type-of($easing) == number { | ||
238 | @error 'Midpoint shifts are not supported.'; | ||
239 | } | ||
240 | |||
241 | $easing-func: null; | ||
242 | $easing-args: (); | ||
243 | |||
244 | @if type-of($easing) == list { | ||
245 | $easing-args: iro-list-slice($easing, 2); | ||
246 | $easing: nth($easing, 1); | ||
247 | } | ||
248 | |||
249 | $generated-stops: join( | ||
250 | $generated-stops, | ||
251 | iro-easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args) | ||
252 | ); | ||
253 | } @else { | ||
254 | $generated-stops: append($generated-stops, iro-str-implode($next-stop, ' ')); | ||
255 | } | ||
256 | |||
257 | $j: $j + 1; | ||
258 | } | ||
259 | |||
260 | $last-positioned-stop: $i; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | @if $type == 'linear' { | ||
265 | @return linear-gradient($dir, unquote(iro-str-implode($generated-stops, ', '))); | ||
266 | } @else if $type == 'radial' { | ||
267 | @return radial-gradient($dir, unquote(iro-str-implode($generated-stops, ', '))); | ||
268 | } @else { | ||
269 | @error 'Invalid gradient type: #{inspect($type)}.'; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /// | ||
274 | /// Alias for iro-easing-gradient('linear',...) | ||
275 | /// | ||
276 | /// @see {function} iro-easing-gradient | ||
277 | /// | ||
278 | @function iro-easing-linear-gradient($dir, $stop, $stops...) { | ||
279 | @return iro-easing-gradient('linear', $dir, $stop, $stops...); | ||
280 | } | ||
281 | |||
282 | /// | ||
283 | /// Alias for iro-easing-gradient('radial',...) | ||
284 | /// | ||
285 | /// @see {function} iro-easing-gradient | ||
286 | /// | ||
287 | @function iro-easing-radial-gradient($dir, $stop, $stops...) { | ||
288 | @return iro-easing-gradient('radial', $dir, $stop, $stops...); | ||
289 | } | ||
290 | |||
291 | /// | ||
292 | /// Generate a smooth transition from one color stop to another using the provided easing function. | ||
293 | /// | ||
294 | /// @access private | ||
295 | /// | ||
296 | @function iro-easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args: ()) { | ||
297 | @if $easing == 'steps' { | ||
298 | $steps: null; | ||
299 | $jump: null; | ||
300 | |||
301 | @if length($easing-args) > 1 { | ||
302 | $steps: nth($easing-args, 1); | ||
303 | $jump: nth($easing-args, 2); | ||
304 | } @else { | ||
305 | $steps: nth($easing-args, 1); | ||
306 | $jump: jump-end; | ||
307 | } | ||
308 | |||
309 | @return iro-easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump); | ||
310 | } @else { | ||
311 | $easing-func: null; | ||
312 | @if function-exists('iro-' + $easing) { | ||
313 | $easing-func: get-function('iro-' + $easing); | ||
314 | } @else { | ||
315 | $easing-func: get-function($easing); | ||
316 | } | ||
317 | |||
318 | @return iro-easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /// | ||
323 | /// Generate a smooth transition from one color stop to another using the provided cubic-bezier function. | ||
324 | /// | ||
325 | /// @access private | ||
326 | /// | ||
327 | @function iro-easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args: ()) { | ||
328 | $prev-stop-color: nth($prev-stop, 1); | ||
329 | $prev-stop-pos: nth($prev-stop, 2); | ||
330 | $next-stop-color: nth($next-stop, 1); | ||
331 | $next-stop-pos: nth($next-stop, 2); | ||
332 | |||
333 | $stops: (); | ||
334 | |||
335 | @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { | ||
336 | // | ||
337 | // The transition color stop positions can be statically calculated. | ||
338 | // | ||
339 | |||
340 | $distance: $next-stop-pos - $prev-stop-pos; | ||
341 | |||
342 | @for $i from 1 through $iro-easing-gradient-steps { | ||
343 | $perc: $i / $iro-easing-gradient-steps; | ||
344 | |||
345 | $color: null; | ||
346 | $pos: $prev-stop-pos + $perc * $distance; | ||
347 | @if $perc == 1 { | ||
348 | $color: $next-stop-color; | ||
349 | } @else { | ||
350 | $color: mix($next-stop-color, $prev-stop-color, call($easing-func, append($easing-args, $perc)...) * 100%); | ||
351 | } | ||
352 | |||
353 | $stops: append($stops, $color + ' ' + $pos); | ||
354 | } | ||
355 | } @else { | ||
356 | // | ||
357 | // The transition color stop positions have to be dynamically calculated with the calc() function. | ||
358 | // | ||
359 | |||
360 | @if type-of($prev-stop-pos) != number { | ||
361 | // must be calc() | ||
362 | @if (type-of($prev-stop-pos) != string) or (str-index($prev-stop-pos, 'calc(') != 1) { | ||
363 | @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; | ||
364 | } | ||
365 | |||
366 | $prev-stop-pos: str-slice($prev-stop-pos, 6, str-length($prev-stop-pos) - 1); | ||
367 | } | ||
368 | |||
369 | @if type-of($next-stop-pos) != number { | ||
370 | // must be calc() | ||
371 | @if (type-of($next-stop-pos) != string) or (str-index($next-stop-pos, 'calc(') != 1) { | ||
372 | @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; | ||
373 | } | ||
374 | |||
375 | $next-stop-pos: str-slice($next-stop-pos, 6, str-length($next-stop-pos) - 1); | ||
376 | } | ||
377 | |||
378 | @for $i from 1 through $iro-easing-gradient-steps { | ||
379 | $perc: $i / $iro-easing-gradient-steps; | ||
380 | |||
381 | $color: null; | ||
382 | $pos: null; | ||
383 | @if $perc == 1 { | ||
384 | $color: $next-stop-color; | ||
385 | $pos: calc(#{$next-stop-pos}); | ||
386 | } @else { | ||
387 | $color: mix($next-stop-color, $prev-stop-color, call($easing-func, append($easing-args, $perc)...) * 100%); | ||
388 | $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc}); | ||
389 | } | ||
390 | |||
391 | $stops: append($stops, $color + ' ' + $pos); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | @return $stops; | ||
396 | } | ||
397 | |||
398 | /// | ||
399 | /// Generate a step transition from one color stop to another. | ||
400 | /// | ||
401 | /// @access private | ||
402 | /// | ||
403 | @function iro-easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump: jump-end) { | ||
404 | $prev-stop-color: nth($prev-stop, 1); | ||
405 | $prev-stop-pos: nth($prev-stop, 2); | ||
406 | $next-stop-color: nth($next-stop, 1); | ||
407 | $next-stop-pos: nth($next-stop, 2); | ||
408 | |||
409 | $stops: (); | ||
410 | |||
411 | @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { | ||
412 | // | ||
413 | // The transition color stop positions can be statically calculated. | ||
414 | // | ||
415 | |||
416 | $distance: $next-stop-pos - $prev-stop-pos; | ||
417 | |||
418 | @for $i from 1 through $steps { | ||
419 | $x1: ($i - 1) / $steps; | ||
420 | $x2: $i / $steps; | ||
421 | $y: null; | ||
422 | |||
423 | @if $jump == jump-start { | ||
424 | $y: $i / $steps; | ||
425 | } @else if $jump == jump-end { | ||
426 | $y: ($i - 1) / $steps; | ||
427 | } @else if $jump == jump-both { | ||
428 | $y: $i / ($steps + 1); | ||
429 | } @else if $jump == jump-none { | ||
430 | $y: ($i - 1) / ($steps - 1); | ||
431 | } @else { | ||
432 | @error 'Invalid $jump: #{inspect($jump)}'; | ||
433 | } | ||
434 | |||
435 | $color: null; | ||
436 | $pos1: if($x1 == 0, $prev-stop-pos, $prev-stop-pos + $x1 * $distance); | ||
437 | $pos2: if($x2 == 1, $next-stop-pos, $prev-stop-pos + $x2 * $distance); | ||
438 | |||
439 | @if $y == 0 { | ||
440 | $color: $prev-stop-color; | ||
441 | } @else if $y == 1 { | ||
442 | $color: $next-stop-color; | ||
443 | } @else { | ||
444 | $color: mix($next-stop-color, $prev-stop-color, $y * 100%); | ||
445 | } | ||
446 | |||
447 | $stops: append($stops, $color + ' ' + $pos1); | ||
448 | $stops: append($stops, $color + ' ' + $pos2); | ||
449 | } | ||
450 | } @else { | ||
451 | // | ||
452 | // The transition color stop positions have to be dynamically calculated with the calc() function. | ||
453 | // | ||
454 | |||
455 | @if type-of($prev-stop-pos) != number { | ||
456 | // must be calc() | ||
457 | @if (type-of($prev-stop-pos) != string) or (str-index($prev-stop-pos, 'calc(') != 1) { | ||
458 | @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; | ||
459 | } | ||
460 | |||
461 | $prev-stop-pos: str-slice($prev-stop-pos, 6, str-length($prev-stop-pos) - 1); | ||
462 | } | ||
463 | |||
464 | @if type-of($next-stop-pos) != number { | ||
465 | // must be calc() | ||
466 | @if (type-of($next-stop-pos) != string) or (str-index($next-stop-pos, 'calc(') != 1) { | ||
467 | @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; | ||
468 | } | ||
469 | |||
470 | $next-stop-pos: str-slice($next-stop-pos, 6, str-length($next-stop-pos) - 1); | ||
471 | } | ||
472 | |||
473 | @for $i from 1 through $steps { | ||
474 | $x1: ($i - 1) / $steps; | ||
475 | $x2: $i / $steps; | ||
476 | $y: null; | ||
477 | |||
478 | @if $jump == jump-start { | ||
479 | $y: $i / $steps; | ||
480 | } @else if $jump == jump-end { | ||
481 | $y: ($i - 1) / $steps; | ||
482 | } @else if $jump == jump-both { | ||
483 | $y: $i / ($steps + 1); | ||
484 | } @else if $jump == jump-none { | ||
485 | $y: ($i - 1) / ($steps - 1); | ||
486 | } @else { | ||
487 | @error 'Invalid $jump: #{inspect($jump)}'; | ||
488 | } | ||
489 | |||
490 | $color: null; | ||
491 | $pos1: if($x1 == 0, $prev-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$x1})); | ||
492 | $pos2: if($x2 == 1, $next-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$x2})); | ||
493 | |||
494 | @if $y == 0 { | ||
495 | $color: $prev-stop-color; | ||
496 | } @else if $y == 1 { | ||
497 | $color: $next-stop-color; | ||
498 | } @else { | ||
499 | $color: mix($next-stop-color, $prev-stop-color, $y * 100%); | ||
500 | } | ||
501 | |||
502 | $stops: append($stops, $color + ' ' + $pos1); | ||
503 | $stops: append($stops, $color + ' ' + $pos2); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | @return $stops; | ||
508 | } | ||
509 | |||
510 | /// | ||
511 | /// Interpolate the positions of multiple color stops between two color stops whose positions are set. | ||
512 | /// | ||
513 | /// @access private | ||
514 | /// | ||
515 | @function iro-easing-gradient-interpolate-stop-positions($prev-stop, $stops, $next-stop) { | ||
516 | $prev-stop-pos: nth($prev-stop, 2); | ||
517 | $next-stop-pos: nth($next-stop, 2); | ||
518 | |||
519 | $stops-num: 0; | ||
520 | @for $i from 1 through length($stops) { | ||
521 | $stop: nth($stops, $i); | ||
522 | @if iro-easing-gradient-is-color-stop($stop) { | ||
523 | $stops-num: $stops-num + 1; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | $i: 1; | ||
528 | $cur-stop-num: 1; | ||
529 | |||
530 | @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { | ||
531 | // | ||
532 | // The color stop positions can be statically calculated. | ||
533 | // | ||
534 | |||
535 | $distance: $next-stop-pos - $prev-stop-pos; | ||
536 | |||
537 | @for $i from 1 through length($stops) { | ||
538 | $stop: nth($stops, $i); | ||
539 | @if iro-easing-gradient-is-color-stop($stop) { | ||
540 | $pos: $prev-stop-pos + $distance / ($stops-num + 1) * $cur-stop-num; | ||
541 | $stops: set-nth($stops, $i, $stop $pos); | ||
542 | |||
543 | $cur-stop-num: $cur-stop-num + 1; | ||
544 | } | ||
545 | } | ||
546 | } @else { | ||
547 | // | ||
548 | // The color stop positions have to be dynamically calculated with the calc() function. | ||
549 | // | ||
550 | |||
551 | @if type-of($prev-stop-pos) != number { | ||
552 | // must be calc() | ||
553 | @if (type-of($prev-stop-pos) != string) or (str-index($prev-stop-pos, 'calc(') != 1) { | ||
554 | @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; | ||
555 | } | ||
556 | |||
557 | $prev-stop-pos: str-slice($prev-stop-pos, 6, str-length($prev-stop-pos) - 1); | ||
558 | } | ||
559 | |||
560 | @if type-of($next-stop-pos) != number { | ||
561 | // must be calc() | ||
562 | @if (type-of($next-stop-pos) != string) or (str-index($next-stop-pos, 'calc(') != 1) { | ||
563 | @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; | ||
564 | } | ||
565 | |||
566 | $next-stop-pos: str-slice($next-stop-pos, 6, str-length($next-stop-pos) - 1); | ||
567 | } | ||
568 | |||
569 | @for $i from 1 through length($stops) { | ||
570 | $stop: nth($stops, $i); | ||
571 | @if iro-easing-gradient-is-color-stop($stop) { | ||
572 | $perc: $cur-stop-num / ($stops-num + 1); | ||
573 | $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc}); | ||
574 | $stops: set-nth($stops, $i, $stop $pos); | ||
575 | |||
576 | $cur-stop-num: $cur-stop-num + 1; | ||
577 | } | ||
578 | } | ||
579 | } | ||
580 | |||
581 | @return $stops; | ||
582 | } | ||
583 | |||
584 | /// | ||
585 | /// Check if the input is a valid color stop. | ||
586 | /// | ||
587 | /// @access private | ||
588 | /// | ||
589 | @function iro-easing-gradient-is-color-stop($input) { | ||
590 | @return (type-of($input) == color) or iro-easing-gradient-is-positioned-color-stop($input); | ||
591 | } | ||
592 | |||
593 | /// | ||
594 | /// Check if the input is a valid positioned color stop. | ||
595 | /// | ||
596 | /// @access private | ||
597 | /// | ||
598 | @function iro-easing-gradient-is-positioned-color-stop($input) { | ||
599 | @return (type-of($input) == list) and (type-of(nth($input, 1)) == color); | ||
600 | } | ||