/// Makes an element's :before pseudoelement a FontAwesome icon. /// @param {string} $content Optional content value to use. /// @param {string} $where Optional pseudoelement to target (before or after). @mixin icon($content: false, $where: before) { text-decoration: none; &:#{$where} { @if $content { content: $content; } -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; font-family: FontAwesome; font-style: normal; font-weight: normal; text-transform: none !important; } } /// Applies padding to an element, taking the current element-margin value into account. /// @param {mixed} $tb Top/bottom padding. /// @param {mixed} $lr Left/right padding. /// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left) /// @param {bool} $important If true, adds !important. @mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) { @if $important { $important: '!important'; } $x: 0.1em; @if unit(_size(element-margin)) == 'rem' { $x: 0.1rem; } padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important}; } /// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp). /// @param {string} $svg SVG data URL. /// @return {string} Encoded SVG data URL. @function svg-url($svg) { $svg: str-replace($svg, '"', '\''); $svg: str-replace($svg, '%', '%25'); $svg: str-replace($svg, '<', '%3C'); $svg: str-replace($svg, '>', '%3E'); $svg: str-replace($svg, '&', '%26'); $svg: str-replace($svg, '#', '%23'); $svg: str-replace($svg, '{', '%7B'); $svg: str-replace($svg, '}', '%7D'); $svg: str-replace($svg, ';', '%3B'); @return url("data:image/svg+xml;charset=utf8,#{$svg}"); } /// Initializes base flexgrid classes. /// @param {string} $vertical-align Vertical alignment of cells. /// @param {string} $horizontal-align Horizontal alignment of cells. @mixin flexgrid-base($vertical-align: null, $horizontal-align: null) { // Grid. @include vendor('display', 'flex'); @include vendor('flex-wrap', 'wrap'); // Vertical alignment. @if ($vertical-align == top) { @include vendor('align-items', 'flex-start'); } @else if ($vertical-align == bottom) { @include vendor('align-items', 'flex-end'); } @else if ($vertical-align == center) { @include vendor('align-items', 'center'); } @else { @include vendor('align-items', 'stretch'); } // Horizontal alignment. @if ($horizontal-align != null) { text-align: $horizontal-align; } // Cells. > * { @include vendor('flex-shrink', '1'); @include vendor('flex-grow', '0'); } } /// Sets up flexgrid columns. /// @param {integer} $columns Columns. @mixin flexgrid-columns($columns) { > * { $cell-width: 100% / $columns; width: #{$cell-width}; } } /// Sets up flexgrid gutters. /// @param {integer} $columns Columns. /// @param {number} $gutters Gutters. @mixin flexgrid-gutters($columns, $gutters) { // Apply padding. > * { $cell-width: 100% / $columns; padding: ($gutters * 0.5); width: $cell-width; } } /// Sets up flexgrid gutters (flush). /// @param {integer} $columns Columns. /// @param {number} $gutters Gutters. @mixin flexgrid-gutters-flush($columns, $gutters) { // Apply padding. > * { $cell-width: 100% / $columns; $cell-width-pad: $gutters / $columns; padding: ($gutters * 0.5); width: calc(#{$cell-width} + #{$cell-width-pad}); } // Clear top/bottom gutters. > :nth-child(-n + #{$columns}) { padding-top: 0; } > :nth-last-child(-n + #{$columns}) { padding-bottom: 0; } // Clear left/right gutters. > :nth-child(#{$columns}n + 1) { padding-left: 0; } > :nth-child(#{$columns}n) { padding-right: 0; } // Adjust widths of leftmost and rightmost cells. > :nth-child(#{$columns}n + 1), > :nth-child(#{$columns}n) { $cell-width: 100% / $columns; $cell-width-pad: ($gutters / $columns) - ($gutters / 2); width: calc(#{$cell-width} + #{$cell-width-pad}); } } /// Reset flexgrid gutters (flush only). /// Used to override a previous set of flexgrid gutter classes. /// @param {integer} $columns Columns. /// @param {number} $gutters Gutters. /// @param {integer} $prev-columns Previous columns. @mixin flexgrid-gutters-flush-reset($columns, $gutters, $prev-columns) { // Apply padding. > * { $cell-width: 100% / $prev-columns; $cell-width-pad: $gutters / $prev-columns; padding: ($gutters * 0.5); width: calc(#{$cell-width} + #{$cell-width-pad}); } // Clear top/bottom gutters. > :nth-child(-n + #{$prev-columns}) { padding-top: ($gutters * 0.5); } > :nth-last-child(-n + #{$prev-columns}) { padding-bottom: ($gutters * 0.5); } // Clear left/right gutters. > :nth-child(#{$prev-columns}n + 1) { padding-left: ($gutters * 0.5); } > :nth-child(#{$prev-columns}n) { padding-right: ($gutters * 0.5); } // Adjust widths of leftmost and rightmost cells. > :nth-child(#{$prev-columns}n + 1), > :nth-child(#{$prev-columns}n) { $cell-width: 100% / $columns; $cell-width-pad: $gutters / $columns; padding: ($gutters * 0.5); width: calc(#{$cell-width} + #{$cell-width-pad}); } } /// Adds debug styles to current flexgrid element. @mixin flexgrid-debug() { box-shadow: 0 0 0 1px red; > * { box-shadow: inset 0 0 0 1px blue; position: relative; > * { position: relative; box-shadow: inset 0 0 0 1px green; } } } /// Initializes the current element as a flexgrid. /// @param {integer} $columns Columns (optional). /// @param {number} $gutters Gutters (optional). /// @param {bool} $flush If true, clears padding around the very edge of the grid. @mixin flexgrid($settings: ()) { // Settings. // Debug. $debug: false; @if (map-has-key($settings, 'debug')) { $debug: map-get($settings, 'debug'); } // Vertical align. $vertical-align: null; @if (map-has-key($settings, 'vertical-align')) { $vertical-align: map-get($settings, 'vertical-align'); } // Horizontal align. $horizontal-align: null; @if (map-has-key($settings, 'horizontal-align')) { $horizontal-align: map-get($settings, 'horizontal-align'); } // Columns. $columns: null; @if (map-has-key($settings, 'columns')) { $columns: map-get($settings, 'columns'); } // Gutters. $gutters: 0; @if (map-has-key($settings, 'gutters')) { $gutters: map-get($settings, 'gutters'); } // Flush. $flush: true; @if (map-has-key($settings, 'flush')) { $flush: map-get($settings, 'flush'); } // Initialize base grid. @include flexgrid-base($vertical-align, $horizontal-align); // Debug? @if ($debug) { @include flexgrid-debug; } // Columns specified? @if ($columns != null) { // Initialize columns. @include flexgrid-columns($columns); // Gutters specified? @if ($gutters > 0) { // Flush gutters? @if ($flush) { // Initialize gutters (flush). @include flexgrid-gutters-flush($columns, $gutters); } // Otherwise ... @else { // Initialize gutters. @include flexgrid-gutters($columns, $gutters); } } } } /// Resizes a previously-initialized grid. /// @param {integer} $columns Columns. /// @param {number} $gutters Gutters (optional). /// @param {list} $reset A list of previously-initialized grid columns (only if $flush is true). /// @param {bool} $flush If true, clears padding around the very edge of the grid. @mixin flexgrid-resize($settings: ()) { // Settings. // Columns. $columns: 1; @if (map-has-key($settings, 'columns')) { $columns: map-get($settings, 'columns'); } // Gutters. $gutters: 0; @if (map-has-key($settings, 'gutters')) { $gutters: map-get($settings, 'gutters'); } // Previous columns. $prev-columns: false; @if (map-has-key($settings, 'prev-columns')) { $prev-columns: map-get($settings, 'prev-columns'); } // Flush. $flush: true; @if (map-has-key($settings, 'flush')) { $flush: map-get($settings, 'flush'); } // Resize columns. @include flexgrid-columns($columns); // Gutters specified? @if ($gutters > 0) { // Flush gutters? @if ($flush) { // Previous columns specified? @if ($prev-columns) { // Convert to list if it isn't one already. @if (type-of($prev-columns) != list) { $prev-columns: ($prev-columns); } // Step through list of previous columns and reset them. @each $x in $prev-columns { @include flexgrid-gutters-flush-reset($columns, $gutters, $x); } } // Resize gutters (flush). @include flexgrid-gutters-flush($columns, $gutters); } // Otherwise ... @else { // Resize gutters. @include flexgrid-gutters($columns, $gutters); } } }