Last active
June 27, 2019 19:05
-
-
Save dinocarl/c903a5ad01e95ace41fa6e7d55a0775e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://codepen.io/anon/pen/LgJPmv | |
// https://codepen.io/anon/pen/qJMaER | |
// https://codepen.io/anon/pen/vQNxaN | |
// https://codepen.io/anon/pen/mQrbQV | |
// https://codepen.io/anon/pen/wLPxOV | |
// Functions | |
// convenience type-checking functions | |
@function is_null( $val ) { @return type-of( $val ) == 'null'; } | |
@function is_map( $val ) { @return type-of( $val ) == map; } | |
// inverses | |
@function isnt_null( $val ) { @return not is_null( $val ); } | |
@function isnt_map( $val ) { @return not is_map( $val ); } | |
// allows for getting at nested attributes in a Sass map | |
// ensures a null return for any unrecognized paths | |
// $colors: (header:(one: #333, two: #444), footer: #666); | |
// path(('header', 'two'), $colors); => #444 | |
@function path( $keys, $map ) { | |
@each $key in $keys { | |
@if isnt_map( $map ) { | |
$map: ( _mt_: null ); | |
} | |
$map: map-get( $map, $key ); | |
} | |
@return $map; | |
} | |
// accepts a function name and a list. | |
// outputs a new list where each member has had the function run against it | |
@function map( $fn, $list ) { | |
$accumulated: (); | |
@for $i from 1 through length( $list ) { | |
$accumulated: append( $accumulated, call( $fn, nth( $list, $i ) ), comma ); | |
} | |
@return $accumulated; | |
} | |
@function single-column-calc( $num-cols, $gutter ) { | |
@return ( 100 - ( $gutter * ( $num-cols - 1 ) ) ) / $num-cols; | |
} | |
@function column-width-calc( $span, $num-cols, $gutter ) { | |
$single-column: single-column-calc( $num-cols, $gutter ); | |
@return $single-column + ( ( $single-column + $gutter ) * ( $span - 1 ) ); | |
} | |
@function offset-width-calcc( $span, $num-cols, $gutter ) { | |
$single-column: single-column-calc( $num-cols, $gutter ); | |
@return ( $single-column + $gutter ) * $span; | |
} | |
@function single-col-px($gutter-width, $total-width, $total-span) { | |
@return ( $total-width - ( ( $total-span - 1 ) * $gutter-width ) ) / $total-span; | |
}; | |
@function span-width-calc( $span, $gutter-width, $total-width, $total-span ) { | |
$single-col: single-col-px( $gutter-width, $total-width, $total-span ); | |
$col-margin-ratio: $single-col / $gutter-width; | |
@return ( $span * ( $gutter-width * $col-margin-ratio ) ) + ( ( $span - 1 ) * $gutter-width ); | |
} | |
@function offset-width-calc( $span, $gutter-width, $total-width, $total-span ) { | |
$single-col: single-col-px( $gutter-width, $total-width, $total-span ); | |
$col-margin-ratio: $single-col / $gutter-width; | |
@return ( $span * ( $gutter-width * $col-margin-ratio ) ) + ( $span * $gutter-width ); | |
} | |
@function create-col-selector( $props ) { | |
@return unquote( '.col-#{path(('size'), $props)}-#{path(('span'), $props)}' ); | |
} | |
@function create-offset-selector( $props ) { | |
@return unquote( '.col-#{path(('size'), $props)}-offset-#{path(('span'), $props)}' ); | |
} | |
@function create-order-selector( $props ) { | |
@return unquote( '.ord-#{path(('size'), $props)}-#{path(('span'), $props)}' ); | |
} | |
// Data | |
$column-data: ( | |
cols: 12, | |
widths: ( | |
xs: ( | |
max: 480, | |
gutter: 8 | |
), | |
sm: ( | |
max: 768, | |
gutter: 12 | |
), | |
md: ( | |
max: 992, | |
gutter: 12 | |
), | |
lg: ( | |
max: 1200, | |
gutter: 14 | |
), | |
), | |
); | |
// Mixins | |
@mixin col-media-query( $width, $idx ) { | |
@if $idx > 1 { | |
@media only screen and (min-width: #{$width + 1}px) { | |
@content; | |
} | |
} | |
@else { | |
@content; | |
} | |
} | |
@mixin generate-columns( $props ) { | |
$widths: path( ('widths'), $props ); | |
$num-cols: path( ('cols'), $props ); | |
$custom-cols: $num-cols - 1; | |
$width-types: map-keys( $widths ); | |
// Create mobile-first variations | |
// of the larger sized columns. | |
// Include the xs last variation b/c | |
// it will always be 100% width | |
$classnames: create-col-selector( ( | |
size: 'xs', | |
span: $num-cols | |
) ); | |
@for $i from 2 through length( $width-types ) { | |
$item: nth( $width-types, $i ); | |
@for $s from 1 through $num-cols { | |
$classnames: append( $classnames, create-col-selector( ( | |
size: $item, | |
span: $s | |
) ), comma ); | |
} | |
} | |
#{$classnames} { | |
width: 100%; | |
} | |
// Generate permutations | |
$curr-items: (); | |
@for $i from 1 through length( $width-types ) { | |
$item: nth( $width-types, $i ); | |
$curr-item-data: ( | |
size: $item | |
); | |
$curr-width: path( ( $item, 'max' ), $widths ); | |
$curr-gutter: path( ( $item, 'gutter' ), $widths ); | |
$curr-gutter-size: ( $curr-gutter / $curr-width ) * 100%; | |
$curr-items: append( $curr-items, $curr-item-data ); | |
// Encase the permutations inside an optional media query | |
$order-data: (); | |
@include col-media-query( $curr-width, $i ) { | |
@for $p from 1 through length( $curr-items ) { | |
$curr-size: path( ('size'), nth( $curr-items, $p ) ); | |
// Create an Offset 0 | |
#{create-offset-selector(( | |
size: $curr-size, | |
span: 0 | |
))} { | |
margin-left: 0; | |
} | |
@for $span from 1 through $custom-cols { | |
$curr-permutation-data: ( | |
size: $curr-size, | |
span: $span | |
); | |
$curr-px-width: span-width-calc( $span, $curr-gutter, $curr-width, $num-cols ); | |
$curr-permutation-name: create-col-selector( $curr-permutation-data ); | |
$curr-permutation-offset: create-offset-selector( $curr-permutation-data ); | |
$curr-permutation-order: create-order-selector( ( | |
size: $item, | |
span: $span | |
) ); | |
$order-data: map-merge( $order-data, (#{$curr-permutation-order}: $span) ); | |
// Output the class | |
#{$curr-permutation-name} { | |
// width: column-width-calc( $span, $num-cols, $curr-gutter-size ); | |
width: percentage( $curr-px-width / $curr-width ); | |
} | |
// Output the offset | |
#{$curr-permutation-offset} { | |
margin-left: percentage( offset-width-calc( $span, $curr-gutter, $curr-width, $num-cols ) / $curr-width ); | |
} | |
// Output the nests | |
@for $nest from 1 through $span { | |
$nest-selector: create-col-selector( ( | |
size: 'xs', | |
span: $nest | |
) ); | |
#{$curr-permutation-name} #{$nest-selector} { | |
width: percentage( span-width-calc( $nest, $curr-gutter, $curr-px-width, $span ) / $curr-px-width ); | |
} | |
} | |
} | |
} | |
@each $selector, $order in $order-data { | |
#{ $selector } { order: $order; } | |
} | |
} | |
} | |
} | |
// output CSS | |
body { | |
margin: 0; | |
padding: 0; | |
font-family: monospace; | |
line-height: 1.2 | |
} | |
.bgo { | |
background-color: orange; | |
} | |
.bgs { | |
background-color: silver; | |
} | |
.row { | |
display: flex; | |
flex-flow: row wrap; | |
justify-content: space-between; | |
& > * { | |
box-sizing: border-box; | |
margin-top: .5em; | |
} | |
} | |
@include generate-columns($column-data); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment