forked from raybrownco/rem
-
Notifications
You must be signed in to change notification settings - Fork 7
/
_rem.scss
133 lines (118 loc) · 5.06 KB
/
_rem.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// @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 <length> or <percentage> value to any other.
@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 may accidentally be the same.
@if $from-unit == $to-unit { @return $length; }
@if unit($from-context) != 'px' { @warn "Parameter $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."; }
// Fixed ratios
// https://developer.mozilla.org/en/CSS/length
// http://dev.w3.org/csswg/css3-values/#absolute-lengths
$px-per-in: 96px / 1in;
$px-per-mm: 96px / 25.4mm;
$px-per-cm: 96px / 2.54cm;
$px-per-pt: 4px / 3pt;
$px-per-pc: 16px / 1pc;
// Variables to store actual convesion ratios
$px-per-from-unit: 1;
$px-per-to-unit: 1;
@if $from-unit != 'px' {
@if $from-unit == 'em' { $px-per-from-unit: $from-context / 1em }
@else if $from-unit == 'rem' { $px-per-from-unit: $base-font-size / 1rem }
@else if $from-unit == '%' { $px-per-from-unit: $from-context / 100% }
@else if $from-unit == 'ex' { $px-per-from-unit: $from-context / 2ex }
@else if $from-unit == 'in' { $px-per-from-unit: $px-per-in }
@else if $from-unit == 'mm' { $px-per-from-unit: $px-per-mm }
@else if $from-unit == 'cm' { $px-per-from-unit: $px-per-cm }
@else if $from-unit == 'pt' { $px-per-from-unit: $px-per-pt }
@else if $from-unit == 'pc' { $px-per-from-unit: $px-per-pc }
@else if $to-unit == 'ch' or $to-unit == 'vw' or $to-unit == 'vh' or $to-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;
}
}
@if $to-unit != 'px' {
@if $to-unit == 'em' { $px-per-to-unit: $to-context / 1em }
@else if $to-unit == 'rem' { $px-per-to-unit: $base-font-size / 1rem }
@else if $to-unit == '%' { $px-per-to-unit: $to-context / 100% }
@else if $to-unit == 'ex' { $px-per-to-unit: $to-context / 2ex }
@else if $to-unit == 'in' { $px-per-to-unit: $px-per-in }
@else if $to-unit == 'mm' { $px-per-to-unit: $px-per-mm }
@else if $to-unit == 'cm' { $px-per-to-unit: $px-per-cm }
@else if $to-unit == 'pt' { $px-per-to-unit: $px-per-pt }
@else if $to-unit == 'pc' { $px-per-to-unit: $px-per-px }
@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 $length * $px-per-from-unit / $px-per-to-unit;
}
// For the given property, use rem units with px as a fallback value for older
// browsers.
//
// $property - The CSS property name.
// $values - The value (or space-separated list of values) for the property.
// $rem-with-px-fallback - Boolean, default: true; whether to use pixel fallback values.
// $important – Boolean, default: false; whether to add an !important flag to the declaration.
//
@mixin rem($property, $values, $use-px-fallback: $rem-with-px-fallback, $important: false) {
// Create a couple of empty lists as output buffers.
$px-values: ();
$rem-values: ();
// Ensure $values is a list.
@if type-of($values) != 'list' {
$values: join((), $values);
}
// Loop through the $values list
@each $value in $values {
// Pass through string values like `auto` or `inherit`.
@if type-of($value) == string or $value == 0 {
$px-values: join($px-values, $value);
$rem-values: join($rem-values, $value);
}
// 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.
@else 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);
}
}
// Add an !important flag if necessary.
@if $important {
$px-values: #{ $px-values + " !important" };
$rem-values: #{ $rem-values + " !important" };
}
// 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;
}