Skip to content

Instantly share code, notes, and snippets.

@mcguffin
Last active August 29, 2015 14:17
Show Gist options
  • Save mcguffin/e44a1be1a6a54cc391cd to your computer and use it in GitHub Desktop.
Save mcguffin/e44a1be1a6a54cc391cd to your computer and use it in GitHub Desktop.
Generate SASS code for fixed aspect ratio layout grid.
<?php
/* Copyright 2015 Jörn Lund https://github.com/mcguffin/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Generate Ratio Grid
* -------------------
* Output bootstrap sass code which can be used to generate a responsive layout grid where
* all grid cells will have equal heights, based on the grid width. This will be achieved
* by maintaining a specific aspect ratio for every row-height / column-width combination.
*
* For example in a row with class .r-xs-4 every grid cell (.col-xs-*) will always have a
* height of 4 grid columns widths.
*
* On compiling make sure to set the number precision to a higher value. 8 turned out to
* be a good value.
*
* Depending on $class_prefix and included sizes the output css have a size up to ~40kB
*
* The markup:
* <div class="row r-xs-6 r-lg-3">
* <div class="col-xs-6 col-lg-4">
* <div><!-- cell wrapper, sets the cell height -->
* <div class="my-grid-cell-content">
* <!--
* cell content wrapper.
* position:absolute (respecting the grid gutter)
* overflow:hidden
* -->
* </div>
* </div>
* </div>
* </div>
*
* @param $gridsize int The gridsize. Should match the $grid-columns SASS Variable
* which you defined in bootstrap (default: 12)
* @param $class_prefix string Class name prefix. Better use something short. Default 'r'
* @param $screen_sizes array Array of bootstrap sizes to generate. Defaults to all
* possible sizes: array( 'xs' , 'sm' , 'md' , 'lg' )
* @return string The Sass code
*/
function generate_ratio_grid( $grid_columns = 12, $screen_sizes = array( 'xs' , 'sm' , 'md' , 'lg' ) , $class_prefix = 'r' ) {
header("Content-Type: text/plain");
// generate rules
$map_sizes = array( 'xs' => '' , 'sm' => '$screen-sm-min' , 'md' => '$screen-md-min' , 'lg' => '$screen-lg-min' );
// We want one css selector for every possible cell ratio...
$ratio2selector = array();
// ... and we want each selector to only appear once in a media query
$ratio2mq = array();
// map ratio
$map_ratio = array();
for ( $i = 1; $i<=$grid_columns; $i++ ) {
for ( $j = 1; $j<=$grid_columns; $j++ ) {
$ratio = number_format( 100*$i/$j , 8 , '.' , '' );
$map_ratio[ $ratio ] = "percentage(( {$i} / {$j} ))";
if ( ! isset( $ratio2selector[$ratio] ) )
$ratio2selector[$ratio] = array();
foreach( $screen_sizes as $container_i => $screen_size ) {
$mq = $map_sizes[$screen_size];
if ( ! isset( $ratio2selector[$ratio][$mq] ) )
$ratio2selector[$ratio][$mq] = array();
$ratio2selector[$ratio][$mq][] = ".{$class_prefix}-{$screen_size}-{$i} .col-{$screen_size}-{$j} > *";
}
}
}
// optimize rules
foreach ( $ratio2selector as $ratio => $media_selectors ) {
foreach ( $media_selectors as $mq => $selectors ) {
if ( ! isset( $ratio2mq[$mq] ) )
$ratio2mq[$mq] = array();
if ( ! isset( $ratio2mq[$mq][$ratio] ) )
$ratio2mq[$mq][$ratio] = array();
$ratio2mq[$mq][$ratio] = array_merge( $selectors , $ratio2mq[$mq][$ratio] );
}
}
// output sass
$nl = "\n";
$tab = "\t";
$space = " ";
$screen_sizes_string = implode( ', ', $screen_sizes );
$output = "/**
* SCSS generated by generate_ratio_grid()
* https://gist.github.com/mcguffin/e44a1be1a6a54cc391cd
*
* Parameters:
* grid_columns: $grid_columns
* screen_sizes: $screen_sizes_string
* class_prefix: $class_prefix
*/
[class^='{$class_prefix}-'],[class*=' {$class_prefix}-'] {
clear:both;
[class^='col-'],[class*=' col-'] {
padding:0;
& > * { // first div
width:100%;
display:block;
& > * { // grid cell content
position:absolute;
left:\$grid-gutter-width / 2;
top:\$grid-gutter-width / 2;
bottom:\$grid-gutter-width / 2;
right:\$grid-gutter-width / 2;
margin:0;
overflow:hidden;
}
}
}
}
";
foreach ( $ratio2mq as $mq => $ratios ) {
$t = ! empty( $mq ) ? $tab : '';
$output .= ! empty( $mq ) ? "@media{$space}(min-width: $mq){$space}{{$nl}" : '';
foreach ( $ratios as $ratio => $selector ) {
$print_ratio = $map_ratio[$ratio];
$output .= "{$t}". implode(', ', $selector ) . "{$space}{{$nl}";
$output .= "{$t}{$tab}padding:0 0 {$print_ratio};{$nl}";
$output .= "{$t}}{$nl}";
}
$output .= ! empty( $mq ) ? "}" : "";
$output .= "{$nl}{$nl}";
}
return $output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment