Skip to content

Instantly share code, notes, and snippets.

@TravisMullen
Created April 6, 2017 20:39
Show Gist options
  • Save TravisMullen/1281e7f0b4c16456b126a4b67103912c to your computer and use it in GitHub Desktop.
Save TravisMullen/1281e7f0b4c16456b126a4b67103912c to your computer and use it in GitHub Desktop.
A few small style Preprocessors in SCSS
// Angular Base Apps
// by Base Apps
// https://github.com/base-apps/angular-base-apps
// Licensed under MIT Open Source
// updated by Travis Mullen
//
$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;
}
/// styles
// =============================================================================
// color classes :: base
// =============================================================================
$white: '#fff' !default;
$black: '#000' !default;
$primary-color: #2173a6 !default;
$secondary-color: #f1f1f1 !default;
$alert-color: #1E2B34 !default;
$alert-dark: darken($alert-color, 25 !default);
$info-color: #999 !default;
$success-color: #43AC6A !default;
$success-dark: darken($success-color, 25) !default;
$warning-color: #F08A24 !default;
$warning-dark: darken($warning-color, 25) !default;
$gray: '#bbb' !default;
$gray-dark: '#393d42' !default;
$gray-light: '#eee' !default;
// do not code hex values here,
// pull color vars from `setting.scss`
$base-color-classes: (
"white": $white,
"black": $black,
"primary-color": $primary-color,
"secondary-color": $secondary-color,
"success-color": $success-color,
"alert-color": $alert-color,
"info-color": $info-color,
"warning-color": $warning-color,
"gray": $gray,
"gray-dark": $gray-dark,
"gray-light": $gray-light
);
/* basic foreground colors :: `.color-name` */
@each $color, $value in $base-color-classes {
.#{$color} {
color: $value !important;
}
}
/* basic background colors :: `.bg-color-name` */
@each $color, $value in $base-color-classes {
.#{$color}-bg {
background-color: $value !important;
}
}
// =============================================================================
// type
// =============================================================================
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
dl,
li,
label,
span,
a,
sup,
sub,
small,
th,
td,
address {
// help smooth out `font-smoothing: antialiased`
text-shadow: rem-calc(1) rem-calc(1) rem-calc(1) rgba(0, 0, 0, 0.004);
/* &.alt-font {
font-family: $alt-font-family;
}
&.body-font {
font-family: $body-font-family;
} */
}
/* @mixin base-panel($gray-dark: , $body-background: $gray-dark) {
border: rem-calc(2) solid $gray-dark;
background-color: $body-background;
}
*/
@mixin hovershadow( $hover-color: '#000' ) {
filter: drop-shadow(rem-calc(1) rem-calc(2) rem-calc(2) rgba($hover-color, 0.3));
&:hover {
filter: drop-shadow(rem-calc(1) rem-calc(2) rem-calc(2) rgba($hover-color, 0.4));
}
}
@mixin svgicon( $global-padding: $rem-base ) {
/* .svg-icon { */
&.prefix {
margin-right: $global-padding;
}
&.postfix {
margin-left: $global-padding;
}
display: inline-flex;
align-self: center;
position: relative;
height: 1em;
width: 1em;
svg,
img {
height:1em;
width:1em;
}
&.svg-baseline {
svg,
img {
bottom: -(1em/8);
position: absolute;
}
}
/* } */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment