//// /// Project mixins /// /// @group utilities //// /// Shorthand border creation mixin. /// Allows for single line, variable border width, /// /// @parameter {string} $border-width - Accepts 1-4 unit values dictating border-widths. /// @parameter {string} $border-style [solid] - Set border style. /// @parameter {string} $border-color [$color-border-base] - Set border color. /// /// @example scss /// .well { /// @include border(2px 1px 5px, dashed, #666); /// } /// @example css /// .well { /// border-style: dashed; /// border-color: #666; /// border-width: 2px 1px 5px; /// } /// /// @todo Allow multiple border style and color declarations. @mixin border($border-width, $border-style: solid, $border-color: $color-border-base) { // If more than 4 widths submitted, display error @if (length($border-width) > 4) { @error 'Border-width accepts a maximum of 4 width parameters; #{length($border-width)} found.'; } // New border width list $new-width: (); // Populate it @for $i from 1 through length($border-width) { // If border is unitless, append unit @if unitless(nth($border-width, $i)) { $new-width: append($new-width, nth($border-width, $i) * 1px); } @else { $new-width: append($new-width, nth($border-width, $i)); } } border-style: $border-style; border-color: $border-color; border-width: $new-width; } /// Shorthand centering of elements. /// If width and height are undefined, centering will be done via `translate`. /// If width and height are defined, centering will be done via `margin`. /// If width is defined and height is undefined, centering will be done via `margin-left` and `translateY`. /// If width is undefined and height is defined, centering will be done via `translateX` and `margin-top`. /// /// Centering via flexbox is included as a separate mixin. /// @see {mixin} center-children /// /// @parameter {string} $width [null] - Width of the element to be centered (can be 'null'). /// @parameter {string} $height [null] - Height of the element to be centered (can be 'null'). /// /// @example scss /// .action { /// @include center(400px null); /// } /// @example css /// .action { /// position: absolute; /// top: 50%; /// left: 50%; /// width: 400px; /// margin-left: -200px; /// transform: translateY(-50%); /// } @mixin center($width: null, $height: null) { position: absolute; top: 50%; left: 50%; @if not $width and not $height { transform: translate(-50%, -50%); } @else if $width and $height { width: $width; height: $height; margin: -($width / 2) #{0 0} -($height / 2); } @else if not $height { width: $width; margin-left: -($width / 2); transform: translateY(-50%); } @else { height: $height; margin-top: -($height / 2); transform: translateX(-50%); } } /// Shorthand centering of elements via flex. /// Should be applied to a container whose child elements you want centered (horizontally and vertically). /// /// @example scss /// .callout { /// @include center-children; /// } /// @example css /// .callout { /// display: flex; /// justify-content: center; /// align-items: center; /// } @mixin center-children { display: flex; justify-content: center; align-items: center; } /// Quick clearfix mixin for clearing container content. /// Proper use-case is when a container's children are floated. If the /// container itself is floated and needs to be cleared, this will not /// function the same as a `clear: left/right/both;`. /// /// @example scss /// .container { /// @include clearfix; /// } /// @example css /// .container::after { /// content: ''; /// display: table; /// clear: both; /// } @mixin clearfix { &::after { content: ''; display: table; clear: both; } } /// Quick text replacement mixin for hiding text outside of an element. /// Primarily used to hide text when a background-image replaces it. /// /// @example scss /// .hero { /// @include hide-text; /// } /// @example css /// .hero { /// text-indent: 101%; /// overflow: hidden; /// white-space: nowrap; /// } @mixin hide-text { text-indent: 101%; overflow: hidden; white-space: nowrap; } /// Shorthand element positioning mixin. /// /// @parameter {string} $pos-type [relative] - Accepts all valid position strings (static, relative, absolute, fixed). /// @parameter {string} $pos-vals [0 0 0 0] - Position values in typical order (top, right, bottom, left). If a value is not required, inset a unitless 0. /// /// @example scss /// .call-to-action { /// @include position(absolute, 15px 50px 0 0); /// } /// @example css /// .call-to-action { /// position: absolute; /// top: 15px; /// right: 50px; /// } /// /// @todo Allow for unitless usage (i.e., `left: 0; right: 0;`) due to it being valid content. @mixin position($pos-type: relative, $pos-vals: 0 0 0 0) { // If no position type designated, default to 'relative' @if type-of($pos-type) == list{ $pos-vals: $pos-type; $pos-type: relative; } // Separate values into top, right, bottom, left $top: nth($pos-vals, 1); $right: nth($pos-vals, 2); $bottom: nth($pos-vals, 3); $left: nth($pos-vals, 4); // Return position position: $pos-type; // Return values // If value is a number and has a unit type, print value // otherwise ignore @if (type-of($top) == number and not unitless($top)){ top: $top; } @if (type-of($right) == number and not unitless($right)){ right: $right; } @if (type-of($bottom) == number and not unitless($bottom)){ bottom: $bottom; } @if (type-of($left) == number and not unitless($left)){ left: $left; } } /// Shorthand element sizing. /// Accepts auto or unit values. If only one value is provided, it will use that value for both width and height. /// Otherwise the first value is width and the second value is height. /// /// @parameter {string} - Accepts 1 or 2 values. /// /// @example scss /// .bucket { /// @include size(auto 150px); /// } /// @example css /// .bucket { /// width: auto; /// height: 150px; /// } @mixin size($size) { // If only one value is present @if length($size) == 1 { @if $size == auto{ width: auto; height: auto; } @else if unitless($size) { width: $size * 1px; height: $size * 1px; } @else if not(unitless($size)) { width: $size; height: $size; } } // If both values are present @if length($size) == 2 { $width: nth($size, 1); $height: nth($size, 2); @if $width == auto { width: $width; } @else if unitless($width){ width: $width * 1px; } @else if not(unitless($width)) { width: $width; } @if $height == auto{ height: $height; } @else if unitless($height) { height: $height * 1px; } @else if not(unitless($height)) { height: $height; } } // If more than 2 values, display error @if length($size) > 2 { @error 'Too many values detected. Size mixin only accepts 1-2 values.'; } } /// Shorthand for single-line text truncation based on width. /// /// @parameter {string} $truncate-width [100%] - Width the element will be truncated at. /// /// @example scss /// .short-title { /// @include truncate(250px); /// } /// @example css /// .short-title { /// display: inline-block; /// max-width: 250px; /// overflow: hidden; /// text-overflow: ellipsis; /// white-space: nowrap; /// word-wrap: normal; /// } @mixin truncate($truncate-width: 100%) { display: inline-block; max-width: $truncate-width; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; word-wrap: normal; }