// vendor.scss v1.0 | @ajlkn | MIT licensed */ // Vars. /// Vendor prefixes. /// @var {list} $vendor-prefixes: ( '-moz-', '-webkit-', '-ms-', '' ); /// Properties that should be vendorized. /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org /// @var {list} $vendor-properties: ( // Animation. 'animation', 'animation-delay', 'animation-direction', 'animation-duration', 'animation-fill-mode', 'animation-iteration-count', 'animation-name', 'animation-play-state', 'animation-timing-function', // Appearance. 'appearance', // Backdrop filter. 'backdrop-filter', // Background image options. 'background-clip', 'background-origin', 'background-size', // Box sizing. 'box-sizing', // Clip path. 'clip-path', // Filter effects. 'filter', // Flexbox. 'align-content', 'align-items', 'align-self', 'flex', 'flex-basis', 'flex-direction', 'flex-flow', 'flex-grow', 'flex-shrink', 'flex-wrap', 'justify-content', 'order', // Font feature. 'font-feature-settings', 'font-language-override', 'font-variant-ligatures', // Font kerning. 'font-kerning', // Fragmented borders and backgrounds. 'box-decoration-break', // Grid layout. 'grid-column', 'grid-column-align', 'grid-column-end', 'grid-column-start', 'grid-row', 'grid-row-align', 'grid-row-end', 'grid-row-start', 'grid-template-columns', 'grid-template-rows', // Hyphens. 'hyphens', 'word-break', // Masks. 'mask', 'mask-border', 'mask-border-outset', 'mask-border-repeat', 'mask-border-slice', 'mask-border-source', 'mask-border-width', 'mask-clip', 'mask-composite', 'mask-image', 'mask-origin', 'mask-position', 'mask-repeat', 'mask-size', // Multicolumn. 'break-after', 'break-before', 'break-inside', 'column-count', 'column-fill', 'column-gap', 'column-rule', 'column-rule-color', 'column-rule-style', 'column-rule-width', 'column-span', 'column-width', 'columns', // Object fit. 'object-fit', 'object-position', // Regions. 'flow-from', 'flow-into', 'region-fragment', // Scroll snap points. 'scroll-snap-coordinate', 'scroll-snap-destination', 'scroll-snap-points-x', 'scroll-snap-points-y', 'scroll-snap-type', // Shapes. 'shape-image-threshold', 'shape-margin', 'shape-outside', // Tab size. 'tab-size', // Text align last. 'text-align-last', // Text decoration. 'text-decoration-color', 'text-decoration-line', 'text-decoration-skip', 'text-decoration-style', // Text emphasis. 'text-emphasis', 'text-emphasis-color', 'text-emphasis-position', 'text-emphasis-style', // Text size adjust. 'text-size-adjust', // Text spacing. 'text-spacing', // Transform. 'transform', 'transform-origin', // Transform 3D. 'backface-visibility', 'perspective', 'perspective-origin', 'transform-style', // Transition. 'transition', 'transition-delay', 'transition-duration', 'transition-property', 'transition-timing-function', // Unicode bidi. 'unicode-bidi', // User select. 'user-select', // Writing mode. 'writing-mode', ); /// Values that should be vendorized. /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org /// @var {list} $vendor-values: ( // Cross fade. 'cross-fade', // Element function. 'element', // Filter function. 'filter', // Flexbox. 'flex', 'inline-flex', // Grab cursors. 'grab', 'grabbing', // Gradients. 'linear-gradient', 'repeating-linear-gradient', 'radial-gradient', 'repeating-radial-gradient', // Grid layout. 'grid', 'inline-grid', // Image set. 'image-set', // Intrinsic width. 'max-content', 'min-content', 'fit-content', 'fill', 'fill-available', 'stretch', // Sticky position. 'sticky', // Transform. 'transform', // Zoom cursors. 'zoom-in', 'zoom-out', ); // Functions. /// Removes a specific item from a list. /// @author Hugo Giraudel /// @param {list} $list List. /// @param {integer} $index Index. /// @return {list} Updated list. @function remove-nth($list, $index) { $result: null; @if type-of($index) != number { @warn "$index: #{quote($index)} is not a number for `remove-nth`."; } @else if $index == 0 { @warn "List index 0 must be a non-zero integer for `remove-nth`."; } @else if abs($index) > length($list) { @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; } @else { $result: (); $index: if($index < 0, length($list) + $index + 1, $index); @for $i from 1 through length($list) { @if $i != $index { $result: append($result, nth($list, $i)); } } } @return $result; } /// Replaces a substring within another string. /// @author Hugo Giraudel /// @param {string} $string String. /// @param {string} $search Substring. /// @param {string} $replace Replacement. /// @return {string} Updated string. @function str-replace($string, $search, $replace: '') { $index: str-index($string, $search); @if $index { @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); } @return $string; } /// Replaces a substring within each string in a list. /// @param {list} $strings List of strings. /// @param {string} $search Substring. /// @param {string} $replace Replacement. /// @return {list} Updated list of strings. @function str-replace-all($strings, $search, $replace: '') { @each $string in $strings { $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace)); } @return $strings; } // Mixins. /// Wraps @content in vendorized keyframe blocks. /// @param {string} $name Name. @mixin keyframes($name) { @-moz-keyframes #{$name} { @content; } @-webkit-keyframes #{$name} { @content; } @-ms-keyframes #{$name} { @content; } @keyframes #{$name} { @content; } } /// Vendorizes a declaration's property and/or value(s). /// @param {string} $property Property. /// @param {mixed} $value String/list of value(s). @mixin vendor($property, $value) { // Determine if property should expand. $expandProperty: index($vendor-properties, $property); // Determine if value should expand (and if so, add '-prefix-' placeholder). $expandValue: false; @each $x in $value { @each $y in $vendor-values { @if $y == str-slice($x, 1, str-length($y)) { $value: set-nth($value, index($value, $x), '-prefix-' + $x); $expandValue: true; } } } // Expand property? @if $expandProperty { @each $vendor in $vendor-prefixes { #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; } } // Expand just the value? @elseif $expandValue { @each $vendor in $vendor-prefixes { #{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; } } // Neither? Treat them as a normal declaration. @else { #{$property}: #{$value}; } }