// Foundation for Apps ALPHA // by ZURB // foundation.zurb.com // Licensed under MIT Open Source $include-css: () !default; $modules: () !default; $rem-base: 16px !default; /// Checks if a module is in use. @function using($name) { // Import from global scope $include-css: $include-css !global; $module-key: map-get($include-css, $name); @if $module-key == true or $module-key == null { @return true; } @else { @return false; } } /// Checks if a module's CSS has already been exported. @function imported($name) { // Import from global scope $modules: $modules !global; // Check if the module is already on the imported list @if type-of(index($modules, $name)) == 'number' { @return true; } @else { @return false; } } /// Outputs the chunk of content passed if component $name hasn't yet been output. /// This prevents code duplication by keeping track of which components have already been output. /// /// @param {string} $name - Name of component to output /// /// @output The content passed, if the component has not yet been exported. @mixin exports($name) { // Check if the module has already been imported @if not(imported($name)) { // Check if the module should be used @if using($name) { $modules: append($modules, $name) !global; @content; } } } /// Map Serialize /// Converts a Sass map to a URL-encoded string, like this: `key1=value1&key2=value2`. We use this function to encode the media queries in the `$breakpoints` variable, so it can be transferred to our JavaScript for use there. /// /// @param {map} $map - Map to convert. /// /// @return A string with a map converted to a string. @function map-serialize($map) { $str: ''; @each $key, $value in $map { $str: $str + $key + '=' + $value + '&'; } $str: str-slice($str, 1, -2); @return $str; } /// Map Next /// Find the next key in a map. /// /// @param {map} $map - Map to traverse. /// @param {mixed} $key - Key to use as a starting point. /// /// @return The value for the key after `$key` if `$key` was found. If `$key` was not found, or `$key` was the last value in the map, returns null. @function map-next($map, $key) { // Store the values of the map as a list, so we can access them with nth $values: map-values($map); // Ghetto for loop $i: 1; $found: false; @each $val in map-keys($map) { @if $found == false { @if ($key == $val) { $found: true; } $i: $i + 1; } } // If the key doesn't exist, or it's the last key in the map, return null @if $i > length($map) { @return null; } // Otherwise return the value @else { @return nth($values, $i); } } /// Is It Light? /// Checks the lightness of $color, and if it passes the $threshold of lightness, it returns the `$yes` color. Otherwise, it returns the `$no` color. Use this function to dynamically output a foreground color based on a given background color. /// /// @param {color} $color - Color to check the lightness of. /// @param {color} $yes - Color to return if $color is light. /// @param {color} $no - Color to return if $color is dark. /// @param {percentage} $threshold - Threshold of lightness to check against. /// /// @return The $yes color or $no color. @function isitlight($color, $yes: #000, $no: #fff, $threshold: 60%) { @if (lightness($color) > $threshold) { @return $yes; } @else { @return $no; } } /// Smart Scale /// Scales a color to be lighter if it's light, or darker if it's dark. Use this function to "fade" a color appropriate to its lightness. /// /// @param {color} $color - Color to scale. /// @param {percentage} $scale - Amount to scale up or down. /// @param {percentage} $threshold - Threshold of lightness to check against. /// /// @return A scaled color. @function smartscale($color, $scale: 5%, $threshold: 60%) { @if lightness($color) > $threshold { $scale: -$scale; } @return scale-color($color, $lightness: $scale); } /// Has Value /// Returns true if a value is not 0, null, or none. Use this function to check for values like `border: 0` or `box-shadow: none`. /// /// @param $val - Value to check. /// /// @return True if `$val` is not 0, null, or none. @function hasvalue($val) { @if $val == null or $val == none { @return false; } @if type-of($val) == 'number' and strip-unit($val) == 0 { @return false; } @return true; } /// Get Side /// Determine a top/right/bottom/right value on a padding, margin, etc. property, no matter how many values were passed in. Use this function if you need to know the specific side of a value, but don't know if the value is using shorthand. /// /// @param {list|number} $val - Value to analyze. Should be a shorthand sizing property, e.g. "1em 2em 1em" /// @param {keyword} $side - Side to return. Should be top, right, bottom, or left. /// /// @return A single value based on `$val` and `$side`. @function get-side($val, $side) { $length: length($val); @if $length == 1 { @return $val; } @if $length == 2 { @return map-get(( top: nth($val, 1), bottom: nth($val, 1), left: nth($val, 2), right: nth($val, 2), ), $side); } @if $length == 3 { @return map-get(( top: nth($val, 1), left: nth($val, 2), right: nth($val, 2), bottom: nth($val, 3), ), $side); } @if $length == 4 { @return map-get(( top: nth($val, 1), right: nth($val, 2), bottom: nth($val, 3), left: nth($val, 4), ), $side); } } /// Get Border Value /// Given border $val, find a specific element of the border, which is $elem. The possible values for $elem are width, style, and color. /// /// @param {list} $val - Border value to find a value in. /// @param {keyword} $elem - Border component to extract. /// /// @param If the value exists, returns the value. If the value is not in the border definition, the function will return a 0px width, solid style, or black border. @function get-border-value($val, $elem) { // Find the width, style, or color and return it @each $v in $val { $type: type-of($v); @if $elem == width and $type == 'number' { @return $v; } @if $elem == style and $type == 'string' { @return $v; } @if $elem == color and $type == 'color' { @return $v; } } // Defaults $defaults: ( width: 0, style: solid, color: black, ); @return map-get($defaults, $elem); } /// Get Shadow Value /// Given shadow value $val, find a specific element of the shadow, which is $elem. The possible values for $elem are x, y, size, spread, color, and inset. /// /// @param {list} $val - Shadow value to find a value in. /// @param {keyword} $elem - Shadow component to extract. /// /// @return If the value exists, returns the value. If the value is not set, returns false. If `$elem` is "inset", returns true, otherwise false. @function get-shadow-value($val, $elem) { // Return "none" if there's no shadow @if $val == none { @return none; } // Inset and color are always at the beginning and end @if $elem == inset { @return nth($val, 1) == inset; } @if $elem == color { @if type-of(nth($val, -1)) == color { @return nth($val, -1); } @else { @return black; } } // The rest of the values are located perilously in the middle $values: (); @each $v in $val { @if type-of($v) == 'number' { $values: append($values, $v); } } @if $elem == x { @if length($values) >= 1 { @return nth($values, 1); } @else { @return 0; } } @else if $elem == y { @if length($values) >= 2 { @return nth($values, 2); } @else { @return 0; } } @else if $elem == size { @if length($values) >= 3 { @return nth($values, 3); } @else { @return 0; } } @else if $elem == spread { @if length($values) >= 4 { @return nth($values, 4); } @else { @return 0; } } @else { @return false; } } /// Strip Unit /// Removes the unit (e.g. px, em, rem) from a value, returning the number only. /// /// @param {number} $num - Number to strip unit from. /// /// @return The same number, sans unit. @function strip-unit($num) { @return $num / ($num * 0 + 1); } /// Turn to Degrees /// Converts a turn unit to the equivalent unit in degrees. 1turn is equal to 360 degrees. Not all browsers support turn, so this function allows us to use turns while outputting a value that all browsers understand. /// /// @param {number} $value - Turn value to convert. /// /// @return The same value, but in degrees. @function turn-to-deg($value) { @return strip-unit($value) * 360deg; } /// Convert to Rem /// Converts a pixel value to matching rem value. *Any* value passed, regardless of unit, is assumed to be a pixel value. By default, the base pixel value used to calculate the rem value is taken from the `$rem-base` variable. /// /// @param {number} $value - Pixel value to convert. /// /// @return A number in rems, calculated based on the given value and the base pixel value. @function convert-to-rem($value, $base-value: $rem-base) { $value: strip-unit($value) / strip-unit($base-value) * 1rem; @if ($value == 0rem) { $value: 0; } // Turn 0rem into 0 @return $value; } /// Rem Calculator /// Converts one or more pixel values into matching rem values. This function works a lot like `convert-to-rem`, except it can convert more than one value at once, which is useful when setting multiple values on a `margin` or `padding` property. /// /// @param {number|list} $values - One or more values to convert. Be sure to separate them with spaces and not commas. If you need to convert a comma-separated list, wrap the list in parentheses. /// /// @return A list of converted values. @function rem-calc($values, $base-value: null) { @if $base-value == null { $base-value: $rem-base; } $max: length($values); @if $max == 1 { @return convert-to-rem(nth($values, 1), $base-value); } $remValues: (); @for $i from 1 through $max { $remValues: append($remValues, convert-to-rem(nth($values, $i), $base-value)); } @return $remValues; }