// @private Default font-size for all browsers $browser-default-font-size: 16px; // Base font size in pixels, if not already defined. // Should be the same as the font-size of the html element. $base-font-size: 16px !default; // Whether to output fallback values in px when outputting rems. $rem-with-px-fallback: true !default; // Convert any CSS or value to any another. // // @param $length // A css or value // // @param $to-unit // String matching a css unit keyword, e.g. 'em', '%', etc. // // @param $from-context // When converting from relative units, the absolute length (in px) to // which $length refers (e.g. for $lengths in em units, would normally be the // font-size of the current element). // // @param $to-context // For converting to relative units, the absolute length in px to which the // output value will refer. Defaults to the same as $from-context, since it is // rarely needed. @function convert-length( $length, $to-unit, $from-context: $base-font-size, $to-context: $from-context ) { $from-unit: unit($length); // Optimize for cases where `from` and `to` units are accidentally the same. @if $from-unit == $to-unit { @return $length; } // Context values must be in px so we can determine a conversion ratio for // relative units. @if unit($from-context) != 'px' { @warn "Paremeter $from-context must resolve to a value in pixel units."; } @if unit($to-context) != 'px' { @warn "Parameter $to-context must resolve to a value in pixel units."; } // Convert input length to pixels $px-length: $length; @if $from-unit != 'px' { // Convert relative units using the from-context parameter. @if $from-unit == 'em' { $px-length: $length * $from-context / 1em } @else if $from-unit == 'rem' { $px-length: $length * $base-font-size / 1rem } @else if $from-unit == '%' { $px-length: $length * $from-context / 100% } @else if $from-unit == 'ex' { $px-length: $length * $from-context / 2ex } // Convert absolute units using Sass' conversion table. @else if $from-unit == 'in' or $from-unit == 'mm' or $from-unit == 'cm' or $from-unit == 'pt' or $from-unit == 'pc' { $px-length: 0px + $length } // Certain units can't be converted. @else if $from-unit == 'ch' or $from-unit == 'vw' or $from-unit == 'vh' or $from-unit == 'vmin' { @warn "#{$from-unit} units can't be reliably converted; Returning original value."; @return $length; } @else { @warn "#{$from-unit} is an unknown length unit. Returning original value."; @return $length; } } // Convert length in pixels to the output unit $output-length: $px-length; @if $to-unit != 'px' { // Relative units @if $to-unit == 'em' { $output-length: $px-length * 1em / $to-context } @else if $to-unit == 'rem' { $output-length: $px-length * 1rem / $base-font-size } @else if $to-unit == '%' { $output-length: $px-length * 100% / $to-context } @else if $to-unit == 'ex' { $output-length: $px-length * 2ex / $to-context } // Absolute units @else if $to-unit == 'in' { $output-length: 0in + $px-length } @else if $to-unit == 'mm' { $output-length: 0mm + $px-length } @else if $to-unit == 'cm' { $output-length: 0cm + $px-length } @else if $to-unit == 'pt' { $output-length: 0pt + $px-length } @else if $to-unit == 'pc' { $output-length: 0pc + $px-length } // Non-convertible units @else if $to-unit == 'ch' or $to-unit == 'vw' or $to-unit == 'vh' or $to-unit == 'vmin' { @warn "#{$to-unit} units can't be reliably converted; Returning original value."; @return $length; } @else { @warn "#{$to-unit} is an unknown length unit. Returning original value."; @return $length; } } @return $output-length; } // Output a given style rule containing rem values along with an (optional) // fallback rule for older browsers (with rem values converted to px). // // @param $property // The css property name. // // @param $values // The value (or space-separated list of values) for the property. // // @param $use-px-fallback // [ true | false ] // @mixin rem($property, $values, $use-px-fallback: $rem-with-px-fallback) { // Create a couple of empty lists as output buffers. $px-values: (); $rem-values: (); // Loop through the $values list @each $value in $values { // For each property value, if it's in rem or px, derive both rem and // px values for it and add those to the end of the appropriate buffer. // Ensure all pixel values are rounded to the nearest pixel. @if type-of($value) == number and not unitless($value) and (unit($value) == px or unit($value) == rem) { @if unit($value) == px { $px-values: join($px-values, round($value)); $rem-values: join($rem-values, convert-length($value, rem)); } @else { $px-values: join($px-values, round(convert-length($value, px))); $rem-values: join($rem-values, $value); } } @else { $px-values: join($px-values, $value); $rem-values: join($rem-values, $value); } } // Use pixel fallback for browsers that don't understand rem units. @if $use-px-fallback { #{$property}: $px-values; } // Use rem values for everyone else (overrides pixel values). #{$property}: $rem-values; } @mixin if-rem($property, $values, $use-px-fallback: $rem-with-px-fallback) { $has-rem: false; @each $value in $values { $has-rem: if(unit($value) == 'rem', true, $has-rem); } @if $has-rem { @include rem($property, $values, $use-px-fallback); } @else { #{$property}: $values; } }