Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Created June 19, 2014 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barneycarroll/34e60e18705688df1b0f to your computer and use it in GitHub Desktop.
Save barneycarroll/34e60e18705688df1b0f to your computer and use it in GitHub Desktop.
SASS mixin for creating absolutely positioned, fractional width items. It fulfils the common flexbox use-cases but uses a simpler syntax.
// gridItems is a mixin for creating absolutely positioned,
// fractional width items. It fulfils the common flexbox use-cases
// but uses a simpler syntax.
//
// The only requirement is that the parent be relatively positioned.
// Multiple invocation methods are possible, all of which are
// exemplified at the bottom.
// Occupy full dimensions of parent container.
// The gridItems mixin adds each passed selector to this rule.
%grid-item {
position : absolute;
left : 0;
top : 0;
height : 100%;
width : 100%;
}
// $opts is heavily overloaded: see bottom for details or read on.
@mixin gridItems( $opts ){
// For horizontal grids (the default), $opts should be a map of
// ( @selector, @fractionUnit ) pairs.
$items : $opts;
// Again, horizontal is the default. These properties will be used
// When applying fractional positioning.
$dimension : 'width';
$offset : 'left';
// If the grid is non-horizontal (ie vertical), pass a map where
// @items conforms to the format detailed above as follows:
// ( vertical : true, items : @items... )
@if map-get( $opts, items ){
$items : map-get( $opts, items );
}
// Remap properties when vertical property is passed
@if map-get( $opts, vertical ){
$dimension : 'height';
$offset : 'top';
}
// Default item enumeration is ( @selector, @fraction ),
// but you can also pass ( @fraction ), in which case @selector
// is assumed to be '> :nth-child( [indexInMap] )'
$no-selectors : false;
// We need to increment fractions.
// In future, may implement an overload method in which empty $items
// results in equal-sized fractions for any number of items.
$fractions : 0;
// For items of index n > 1, we need to apply the cumulative offset
// of previous items
$previous : 0;
// In cases where selectors aren't passed, we need to remap our internal
// variables. Takes several iterations because of hard limitations in SASS.
@each $selector, $fraction in $items {
// Set a flag. Note that we need either all selectors or no selectors at all.
@if $no-selectors = null {
$no-selectors : $fraction = null;
}
// Temporarily remap. A second iteration applies the necessary selector.
@if $no-selectors {
$fraction : $selector;
// Because we can't retrieve iteration index from @each on maps,
// Use a unique id to create an unambiguous key for each item.
// This is a temporary measure, as explained below.
$selector : unique_id();
}
}
// Create a list of keys from the $map. Necessary (in this implementation)
// to retrieve an index from unique keys when iterating (we still need a map).
//
// Should really create a higher-level fork for the $no-selectors API
// rather than literring the code with expensive conditions.
@if $no-selectors {
$selectorList : map-keys( $items );
}
@each $selector, $fraction in $items {
@if no-selectors {
$index : index( $selectorList, $selector ) + 1;
$selector : #{ '> nth-child( ' + $index + ' )';
}
$fractions : $fractions + $fraction;
}
@each $selector, $fraction in $items {
$percentage : ( $fraction / $fractions ) * 100;
#{ $selector } {
@extend %grid-item;
#{ $dimension } : #{ $percentage + '%' };
#{ $offset } : #{ $previous + '%' };
}
$previous : $previous + $percentage;
}
}
// |------|----|
// |xxxxxx|xxxx|
// |xxxxxx|xxxx|
// |xxxxxx|xxxx|
// |xxxxxx|xxxx|
// |xxxxxx|xxxx|
// |------|----|
// .container {
// @include gridItems( (
// ( '.chartEngineBox', 3 ),
// ( '.sidePanelBox', 2 )
// ) );
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment