748286b5 |
1 | // vendor.scss v1.0 | @ajlkn | MIT licensed */ |
2 | |
3 | // Vars. |
4 | |
5 | /// Vendor prefixes. |
6 | /// @var {list} |
7 | $vendor-prefixes: ( |
8 | '-moz-', |
9 | '-webkit-', |
10 | '-ms-', |
11 | '' |
12 | ); |
13 | |
14 | /// Properties that should be vendorized. |
15 | /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org |
16 | /// @var {list} |
17 | $vendor-properties: ( |
18 | |
19 | // Animation. |
20 | 'animation', |
21 | 'animation-delay', |
22 | 'animation-direction', |
23 | 'animation-duration', |
24 | 'animation-fill-mode', |
25 | 'animation-iteration-count', |
26 | 'animation-name', |
27 | 'animation-play-state', |
28 | 'animation-timing-function', |
29 | |
30 | // Appearance. |
31 | 'appearance', |
32 | |
33 | // Backdrop filter. |
34 | 'backdrop-filter', |
35 | |
36 | // Background image options. |
37 | 'background-clip', |
38 | 'background-origin', |
39 | 'background-size', |
40 | |
41 | // Box sizing. |
42 | 'box-sizing', |
43 | |
44 | // Clip path. |
45 | 'clip-path', |
46 | |
47 | // Filter effects. |
48 | 'filter', |
49 | |
50 | // Flexbox. |
51 | 'align-content', |
52 | 'align-items', |
53 | 'align-self', |
54 | 'flex', |
55 | 'flex-basis', |
56 | 'flex-direction', |
57 | 'flex-flow', |
58 | 'flex-grow', |
59 | 'flex-shrink', |
60 | 'flex-wrap', |
61 | 'justify-content', |
62 | 'order', |
63 | |
64 | // Font feature. |
65 | 'font-feature-settings', |
66 | 'font-language-override', |
67 | 'font-variant-ligatures', |
68 | |
69 | // Font kerning. |
70 | 'font-kerning', |
71 | |
72 | // Fragmented borders and backgrounds. |
73 | 'box-decoration-break', |
74 | |
75 | // Grid layout. |
76 | 'grid-column', |
77 | 'grid-column-align', |
78 | 'grid-column-end', |
79 | 'grid-column-start', |
80 | 'grid-row', |
81 | 'grid-row-align', |
82 | 'grid-row-end', |
83 | 'grid-row-start', |
84 | 'grid-template-columns', |
85 | 'grid-template-rows', |
86 | |
87 | // Hyphens. |
88 | 'hyphens', |
89 | 'word-break', |
90 | |
91 | // Masks. |
92 | 'mask', |
93 | 'mask-border', |
94 | 'mask-border-outset', |
95 | 'mask-border-repeat', |
96 | 'mask-border-slice', |
97 | 'mask-border-source', |
98 | 'mask-border-width', |
99 | 'mask-clip', |
100 | 'mask-composite', |
101 | 'mask-image', |
102 | 'mask-origin', |
103 | 'mask-position', |
104 | 'mask-repeat', |
105 | 'mask-size', |
106 | |
107 | // Multicolumn. |
108 | 'break-after', |
109 | 'break-before', |
110 | 'break-inside', |
111 | 'column-count', |
112 | 'column-fill', |
113 | 'column-gap', |
114 | 'column-rule', |
115 | 'column-rule-color', |
116 | 'column-rule-style', |
117 | 'column-rule-width', |
118 | 'column-span', |
119 | 'column-width', |
120 | 'columns', |
121 | |
122 | // Object fit. |
123 | 'object-fit', |
124 | 'object-position', |
125 | |
126 | // Regions. |
127 | 'flow-from', |
128 | 'flow-into', |
129 | 'region-fragment', |
130 | |
131 | // Scroll snap points. |
132 | 'scroll-snap-coordinate', |
133 | 'scroll-snap-destination', |
134 | 'scroll-snap-points-x', |
135 | 'scroll-snap-points-y', |
136 | 'scroll-snap-type', |
137 | |
138 | // Shapes. |
139 | 'shape-image-threshold', |
140 | 'shape-margin', |
141 | 'shape-outside', |
142 | |
143 | // Tab size. |
144 | 'tab-size', |
145 | |
146 | // Text align last. |
147 | 'text-align-last', |
148 | |
149 | // Text decoration. |
150 | 'text-decoration-color', |
151 | 'text-decoration-line', |
152 | 'text-decoration-skip', |
153 | 'text-decoration-style', |
154 | |
155 | // Text emphasis. |
156 | 'text-emphasis', |
157 | 'text-emphasis-color', |
158 | 'text-emphasis-position', |
159 | 'text-emphasis-style', |
160 | |
161 | // Text size adjust. |
162 | 'text-size-adjust', |
163 | |
164 | // Text spacing. |
165 | 'text-spacing', |
166 | |
167 | // Transform. |
168 | 'transform', |
169 | 'transform-origin', |
170 | |
171 | // Transform 3D. |
172 | 'backface-visibility', |
173 | 'perspective', |
174 | 'perspective-origin', |
175 | 'transform-style', |
176 | |
177 | // Transition. |
178 | 'transition', |
179 | 'transition-delay', |
180 | 'transition-duration', |
181 | 'transition-property', |
182 | 'transition-timing-function', |
183 | |
184 | // Unicode bidi. |
185 | 'unicode-bidi', |
186 | |
187 | // User select. |
188 | 'user-select', |
189 | |
190 | // Writing mode. |
191 | 'writing-mode', |
192 | |
193 | ); |
194 | |
195 | /// Values that should be vendorized. |
196 | /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org |
197 | /// @var {list} |
198 | $vendor-values: ( |
199 | |
200 | // Cross fade. |
201 | 'cross-fade', |
202 | |
203 | // Element function. |
204 | 'element', |
205 | |
206 | // Filter function. |
207 | 'filter', |
208 | |
209 | // Flexbox. |
210 | 'flex', |
211 | 'inline-flex', |
212 | |
213 | // Grab cursors. |
214 | 'grab', |
215 | 'grabbing', |
216 | |
217 | // Gradients. |
218 | 'linear-gradient', |
219 | 'repeating-linear-gradient', |
220 | 'radial-gradient', |
221 | 'repeating-radial-gradient', |
222 | |
223 | // Grid layout. |
224 | 'grid', |
225 | 'inline-grid', |
226 | |
227 | // Image set. |
228 | 'image-set', |
229 | |
230 | // Intrinsic width. |
231 | 'max-content', |
232 | 'min-content', |
233 | 'fit-content', |
234 | 'fill', |
235 | 'fill-available', |
236 | 'stretch', |
237 | |
238 | // Sticky position. |
239 | 'sticky', |
240 | |
241 | // Transform. |
242 | 'transform', |
243 | |
244 | // Zoom cursors. |
245 | 'zoom-in', |
246 | 'zoom-out', |
247 | |
248 | ); |
249 | |
250 | // Functions. |
251 | |
252 | /// Removes a specific item from a list. |
253 | /// @author Hugo Giraudel |
254 | /// @param {list} $list List. |
255 | /// @param {integer} $index Index. |
256 | /// @return {list} Updated list. |
257 | @function remove-nth($list, $index) { |
258 | |
259 | $result: null; |
260 | |
261 | @if type-of($index) != number { |
262 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; |
263 | } |
264 | @else if $index == 0 { |
265 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; |
266 | } |
267 | @else if abs($index) > length($list) { |
268 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; |
269 | } |
270 | @else { |
271 | |
272 | $result: (); |
273 | $index: if($index < 0, length($list) + $index + 1, $index); |
274 | |
275 | @for $i from 1 through length($list) { |
276 | |
277 | @if $i != $index { |
278 | $result: append($result, nth($list, $i)); |
279 | } |
280 | |
281 | } |
282 | |
283 | } |
284 | |
285 | @return $result; |
286 | |
287 | } |
288 | |
289 | /// Replaces a substring within another string. |
290 | /// @author Hugo Giraudel |
291 | /// @param {string} $string String. |
292 | /// @param {string} $search Substring. |
293 | /// @param {string} $replace Replacement. |
294 | /// @return {string} Updated string. |
295 | @function str-replace($string, $search, $replace: '') { |
296 | |
297 | $index: str-index($string, $search); |
298 | |
299 | @if $index { |
300 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); |
301 | } |
302 | |
303 | @return $string; |
304 | |
305 | } |
306 | |
307 | /// Replaces a substring within each string in a list. |
308 | /// @param {list} $strings List of strings. |
309 | /// @param {string} $search Substring. |
310 | /// @param {string} $replace Replacement. |
311 | /// @return {list} Updated list of strings. |
312 | @function str-replace-all($strings, $search, $replace: '') { |
313 | |
314 | @each $string in $strings { |
315 | $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace)); |
316 | } |
317 | |
318 | @return $strings; |
319 | |
320 | } |
321 | |
322 | // Mixins. |
323 | |
324 | /// Wraps @content in vendorized keyframe blocks. |
325 | /// @param {string} $name Name. |
326 | @mixin keyframes($name) { |
327 | |
328 | @-moz-keyframes #{$name} { @content; } |
329 | @-webkit-keyframes #{$name} { @content; } |
330 | @-ms-keyframes #{$name} { @content; } |
331 | @keyframes #{$name} { @content; } |
332 | |
333 | } |
334 | |
335 | /// Vendorizes a declaration's property and/or value(s). |
336 | /// @param {string} $property Property. |
337 | /// @param {mixed} $value String/list of value(s). |
338 | @mixin vendor($property, $value) { |
339 | |
340 | // Determine if property should expand. |
341 | $expandProperty: index($vendor-properties, $property); |
342 | |
343 | // Determine if value should expand (and if so, add '-prefix-' placeholder). |
344 | $expandValue: false; |
345 | |
346 | @each $x in $value { |
347 | @each $y in $vendor-values { |
348 | @if $y == str-slice($x, 1, str-length($y)) { |
349 | |
350 | $value: set-nth($value, index($value, $x), '-prefix-' + $x); |
351 | $expandValue: true; |
352 | |
353 | } |
354 | } |
355 | } |
356 | |
357 | // Expand property? |
358 | @if $expandProperty { |
359 | @each $vendor in $vendor-prefixes { |
360 | #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; |
361 | } |
362 | } |
363 | |
364 | // Expand just the value? |
365 | @elseif $expandValue { |
366 | @each $vendor in $vendor-prefixes { |
367 | #{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; |
368 | } |
369 | } |
370 | |
371 | // Neither? Treat them as a normal declaration. |
372 | @else { |
373 | #{$property}: #{$value}; |
374 | } |
375 | |
376 | } |