super-gigi
v2.1.0
Published
A customizable Sass Grid Generator based on CSS3 Flex-box
Downloads
112
Readme
Super GiGi is a customizable Sass Grid Generator based on CSS3 Flex-box.
It has been developed with modern web applications in mind and its first purpose is to make it easier to manage responsive layouts. It is developed in Sass, but a compiled CSS version is available.
Nowadays I suggest to use CSS Grids But if you wanna go to use Flex, I really suggest to use some tool like that 😎
V2 Breaking Change
The only thing to do is to refer to this file: [path to super-gigi]/lib/main
instead of [path to super-gigi]/dist/\_main.scss
It's the only breaking change 🙂
V2 What's new
It works on Dart Sass, fully Sass modules support and easier to mantain 😁
Playground
Installation
You can choose different ways to install Super GiGi:
- Download the latest release.
- Clone the repo:
https://github.com/Objectway/super-gigi.git
. - Install with npm:
npm install super-gigi -D
.
After the download you can use the CSS compiled version by importing [path to super-gigi]/lib/compiled/supergigi.css
.
To use the Sass version (which uses all of the options and mixins below) you have to import
in your sass file [path to super-gigi]/lib/_main.scss
.
Options
If you are using the Sass version you can personalize Super GiGi by
simply changing the value of its variables before importing main.scss
.
$grid-columns: 10;
@import "[path to super-gigi]/lib/main";
Or with Sass modules
@use "[path to super-gigi]/lib/main" with (
$grid-column: 10
);
$rem-base
If you want to use rem on your site, set the font-size of your html
tag to rem-base
.
$design-base
default: $rem-base
- type: unit
This is the default value for all the
units functions, it is useful when you have a pixel based design mockup and you want to convert all of the measurements in rem / em. By default this has the same value of $rem-base
, but in some cases you may want change it.
$row-width
default: rem-calc(1920)
- type: unit
This is the max-width
of our row objects. The default value is 1920 pixels
converted in rems via rem-calc()
function.
$column-gutter
default: rem-calc(30)
- type: unit
This is the space between our columns, also known as gutter. The default value is 30 pixels converted in rems via rem-calc()
function.
If you prefer, there is a EXPERIMENTAL
option that you can use to have a responsive gutter using a map similar to the breakpoints
one.
$column-gutter: (
"xxsmall": 0.5em,
"medium": 1em,
"xlarge": 1.5em
);
Doing that, all the grid mixins will generate responsive gutter:
.foo {
@include grid-column;
}
and tadà:
.foo {
box-sizing: border-box;
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 0em) {
.foo {
padding-left: 0.25em;
padding-right: 0.25em;
}
}
@media only screen and (min-width: 45em) {
.foo {
padding-left: 0.5em;
padding-right: 0.5em;
}
}
@media only screen and (min-width: 80em) {
.foo {
padding-left: 0.75em;
padding-right: 0.75em;
}
}
$grid-columns
default: 12
- type: number
The number of columns used in our layout.
$use-classes
default: false
- type: boolean
Set this variable to true if you want to generate static classes, like:
.row
, .column
or .large-12
.
$use-placeholders
default: false
- type: boolean
Set this variable to true if you want to generate placeholders to us like:
.column {
@extend %column;
@extend %large-12;
}
$row-name
default: row
- type: string
This option will change the name of the row object classes or placeholder.
$column-name
default: column
- type: string
This option will change the name of the column object classes or placeholder.
$use-bem
default: false
- type: boolean
This option will change the format of the class names generated when $use-class
is true
.
$bem-separator
default: '--'
- type: string
This option will change the separator between the block and the element whe using BEM naming.
$grid-start
default: left
- type: string
- possibile values: left
or right
This is the value to change if you want to develop a rtl application.
$use-dry
default: false
- type: boolean
If true, all the grid will be passed by dry-it()
mixin.
$debug
default: false
- type: boolean
With big applications and semantic BEM selectors, it is difficult to understand
what kind of properties a DOM element has. If you set this
variable to true
, Super GiGi will add a "content" property that will be
useful when we inspect the elements.
Example:
.fooColumn {
font-size: 30px;
}
@media only screen and (min-width: 45em) {
.fooColumn {
left: 8.33333%;
right: 8.33333%;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
order: 0;
content: "COLUMN: width : (xxsmall: 6, large: 6) | push : 1 | pull : 1 | order : 0 | global : true";
}
}
$sg-collapse
default: false
- type: boolean
By default, Super GiGi columns have a $column-gutter
made with padding. If you want to remove that gutter to all your columns, set this option to true
$sg-use-margin EXPERIMENTAL
default: false
- type: boolean
It is possible to use margins as additional column-gutter between columns. This is not mutual esclusive to the padding -to do that, see the $collapse
option inside the grid-column
mixin or the $sg-collapse
option-, but it will add another column-gutter to your column. This is the general option for all your columns. You can set this option to a single column by the $margin
option of the grid-column
mixin.
$sg-include-box-sizing
default: true
- type: boolean
By default, Super GiGi columns and rows have a box-sizing: border-box
applied to them. If you have already globally defined box-sizing: border-box
within your project and want to remove the redundancy, set this option to false
.
$eq-grid
default: false
- type: boolean
Super GiGi supports EQJS. Turn this option to
true
to use element queries css instead of classical mediaqueries. See the media-query()
mixin for other infos.
$breakpoints
default: ( xxsmall: 0, xsmall: 480, small: 640, medium: 720, large: 1024, xlarge: 1280, xxlarge: 1440 )
- type:
map
Ok, this might look a little complicated :) but we wanted to have an easily accessible setting in one place. This is a Sass map, and is used to define all of our mediaqueries.
The keys are used to define the name of our breakpoints and will be passed to our classes generator or to our mixins.
As an example, the following...
$breakpoints: (
sml: 0em,
mdm: 40em,
lrg: 60em
);
... will generate this css:
@media (min-width: 40em) {
.mdm-3 {
width: 25%;
}
}
@media (min-width: 40em) {
.lrg-3 {
width: 25%;
}
}
If you decide to change class names like in the example above, then just in the same way you have to change how you refer to breakpoints in all of your mixins:
.foo {
@include grid-row(false);
&__bar {
@include grid-column(
$width: (sml:6, lrg: 6),
$collapse: false,
$push: (mdm:6, lrg: 12),
$pull: 1,
$order: 0
);
}
&foo {
@include media-query(lrg) {
background: red
}
}
Note
As values you can pass unitless values (like in the default setting), those will be converted in em. If you want you can pass the unit too like:
$breakpoints: (
small: 300px,
large: 900px
);
@import "main";
.example {
@include media-query(small, only) {
content: "yeah";
}
}
// Will generate
// @media only screen and (min-width: 300px) and (max-width: 899px) {
// .example {
// content: 'yeah'
// }
// }
$breakpoints: (
small: 20rem,
large: 40rem
);
@import "main";
.example {
@include media-query(small, only) {
content: "yeah";
}
}
// Will generate
// @media only screen and (min-width: 20rem) and (max-width: 39.9375rem) {
// .example {
// content: 'yeah'
// }
// }
$breakpoints: (
small: 300,
large: 900
);
@import "main";
.example {
@include media-query(small, only) {
content: "yeah";
}
}
// Will generate
// @media only screen and (min-width: 18.75em) and (max-width: 56.1875em) {
// .example {
// content: 'yeah'
// }
// }
$use-flex
default: true
- type: boolean
Super GiGi is developed with CSS3 Flexbox, but there are fallback options with float
and display: table
.
Set this option to false
, to don't use the flex properties.
$use-table EXPERIMENTAL
default: true
- type: boolean
Super GiGi is developed with CSS3 Flexbox, but there is a fallback in table. Set this option to true
, to use the float properties.
$use-float EXPERIMENTAL
default: true
- type: boolean
Super GiGi is developed with CSS3 Flexbox, but there is a fallback in float. Set this option to true
, to use the float properties.
$query-direction EXPERIMENTAL
default: (min-width, max-width)
- type: list
Super GiGi is developed mobile first, but in some cases you would like to
develop in graceful decadency. To do this you can set
$query-direction: (max-width, min-width)
. The media-queries will be reverted
and all the queries will go from the largest query to the smallest one.
Mixins
If you're using the Sass version of Super-GiGi you'll can use the following Mixins. Here you can found extended documentation for Grid and Visibility mixins too.
media-query()
arguments: $query
, $only
, $eq-grid
- $query
- optional
- default:
xxsmall
- type:
string
- $until
- optional
- default:
false
- type:
boolean
orstring
- $eq-grid
- optional
- default:
false
- type:
boolean
As you can guess, this is the mixin that generates our media or element query.
The $query
argument must be one of the key
values defined
in the $breakpoints
variable.
Super GiGi is developed mobile first, so if you write
@include mediaquery(small){...}
you will target all the queries from small
.
If you want to trigger only a range you can pass $until
parameter to your mixin implementation.
$until
accepts only
or a $breakpoints
key value.
Example:
.sausage {
@include media-query(small, only) {
content: "small only;";
}
}
.eggplant {
@include media-query(small, large) {
content: "small to large;";
}
}
will generate:
@media only screen and (min-width: 40em) and (max-width: 44.9375em) {
.sausage {
content: "small only;";
}
}
@media only screen and (min-width: 40em) and (max-width: 79.9375em) {
.eggplant {
content: "small to large;";
}
}
You can choose between the classical media query or the JavaScript powered element query. You don't have to specify this setting everytime, Super GiGi provides a global $eq-grid variable, but it might be handy to mix media end element queries.
grid-space()
arguments: $property
, $attr
- $property
- optional
- default:
width
- type:
string
- $attr
- optional
- default:
auto
- type:
list
- $margin
- optional
- default:
false
- type:
boolean
When you are writing css in a grid, it's difficult to manage
the measures sometime. grid-space()
comes to help us in this ungrateful task!
You must declare the property you want to set (for example:
margin-left
) by changing the $property
argument.
You then have to pass how many column of the grid you want that property to take.
For example assuming that we have 12
$grid-columns
:
.foo {
@include grid-space(margin-left, 5);
}
will return
.foo {
margin-left: 41.6667%;
}
You can also express the number of column you want to use for your calculation,
passing to $attr
a sass list composed like
that: $column
of
$columns
. For example:
.foo {
@include grid-space(margin-left, 1 of 2);
}
will return
.foo {
margin-left: 50%;
}
For infos about $margin
option, see the margin
section.
grid-container
an alias for grid-row(false)
(see above)
Simiply a row not nested, usefull for the first row of your page, or for row not nested in a column
grid-row()
arguments: $nested
, $vertical
- $nested
- optional
- default:
true
- type:
boolean
- $vertical
DEPRECATED
- optional
- default:
false
- type:
boolean
This mixin will generate the row element of the grid. It's real simple,
you may specify if the row is nested in another row (to reset the padding).
The option $vertical
will only add the CSS3 flex-direction: column
property to the element, so it's deprecated. It would be removed soon.
grid-column()
arguments: $width
, $offset
, $push
, $pull
, $order
, $collapse
, $global
- $width
- optional
- default:
null
- $offset
- optional
- default:
null
- $push
- optional
- default:
null
- $pull
- optional
- default:
null
- $order
- optional
- default:
null
- $collapse
- optional
- default:
null
- type:
boolean
- $global
- optional
- default:
true
- type:
boolean
- $margin
EXPERIMENTAL
- optional
- default:
$sg-use-margin
- type:
boolean
- $eq-grid
- optional
- default:
false
- type:
boolean
This is the most important mixin of our grid. And probabily it is the mixin that you will use more. Let's take a look at how it works:
.foo {
@include grid-column(
$width: (
xxsmall: 6,
large: 6
),
$push: (
xxsmall: 6,
large: 12
),
$pull: 1,
$order: 0,
$collapse: false,
$global: true,
$eq-grid: false
);
}
will generate:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
position: relative;
right: auto;
position: relative;
left: auto;
right: 8.33333%;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
order: 0;
}
@media only screen and (min-width: 0em) {
.foo {
width: 50%;
left: 50%;
}
}
@media only screen and (min-width: 64em) {
.foo {
width: 50%;
left: 100%;
}
}
note: you see repeated properties, because we set pull and push for the same element.
1 - Passing an integer
.foo {
@include grid-column($width: 1);
}
will return:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
width: 8.33333%;
}
The first four properties are the common behaviour of the column object, the
relevant part is width: 8.33333%
. This is calculated via
grid-space() mixin
2 - Passing a semantic list
.foo {
@include grid-column($width: 1 of 3);
}
will return:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
width: 33.33333%;
}
As before, the first four properties are the common rules of our column, the
relevant part is width: 33.33333%
. This is calculated via
grid-space() mixin
3 - Passing a queries map
.foo {
@include grid-column(
$width: (
small: 6,
medium: 4,
large: 3
)
);
}
will generate:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 40em) {
.foo {
width: 50%;
}
}
@media only screen and (min-width: 45em) {
.foo {
width: 33.33333%;
}
}
@media only screen and (min-width: 64em) {
.foo {
width: 25%;
}
}
As before, the first four properties are the common rules of our column, the relevant part are these in the media query. How you can see we have the widths of the column set in a responsive way.
4 - Width
As said before $width
, $offset
, $push
and $pull
have similar behaviors, but $width
is obviously a bit different.
We've seen that you can pass to $width
essentialy a number. When you do that,
Super GiGi
will add to your css: flex: 0 0 auto
. This is essential to our flex grid to work.
But you can set $width
to auto
, that will set the width
css property to auto
and the flex
property to 1 1 0%
.
With this option you can have columns that will take all of the available space on
a given row.
If you have one column, it will take 100% of the space, if you have two then they both will take 50% each, and so on.
Another important option is to set $width
to 0
. This will not set width
to 0% (a column must have a minimun width). But the width will be auto
.
In this way you can have a column with the width decided from the content.
.foo {
@include grid-column($order: 3);
}
.bar {
@include grid-column(
$order: (
small: 6,
medium: 4,
large: 3
)
);
}
will compile in:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
width: auto;
order: 3;
}
.bar {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
width: auto;
}
@media only screen and (min-width: 40em) {
.bar {
order: 6;
}
}
@media only screen and (min-width: 45em) {
.bar {
order: 4;
}
}
@media only screen and (min-width: 64em) {
.bar {
order: 3;
}
}
show-from()
arguments: $query
- $query
- required
- default:
null
- type:
string
This is the first of Super GiGi's visibility mixins. It simple takes a$query
argument and sets the element todisplay: none;
until the passed$query
, where the element will take the property:display: inherit
. Example
.foo {
@include show-from(small);
}
and magically:
.foo {
display: none;
}
@media only screen and (min-width: 40em) {
.foo {
display: inherit;
}
}
hide-from()
arguments: $query
- $query
- required
- default:
null
- type:
string
Likeshow-from()
. It simple takes a$query
argument and sets the element todisplay: inherit;
until the passed$query
, where the element will take the property:display: none
. Example:
.foo {
@include hide-from(small);
}
will generate:
.foo {
display: inherit;
}
@media only screen and (min-width: 40em) {
.foo {
display: none;
}
}
show-for()
arguments: $query
- $query
- required
- default:
null
- type:
string
In this case the element is hidden by display: none;
and will have
the property: display: inherit
only for the selected media query range.
Example:
.foo {
@include show-for(small);
}
will generate:
.foo {
display: none;
}
@media only screen and (min-width: 40em) and (max-width: 44.9375em) {
.foo {
display: inherit;
}
}
hide-for()
arguments: $query
- $query
- required
- default:
null
- type:
string
The last of our visibility mixins. This will hide the element with
display: none;
only for the selected media query range. Example:
.foo {
@include hide-for(small);
}
will generate:
.foo {
display: inherit;
}
@media only screen and (min-width: 40em) and (max-width: 44.9375em) {
.foo {
display: none;
}
}
responsive-gutter() EXPERIMENTAL
By default SuperGiGi has a fixed $column-gutter
that is the
same for each breakpoint in the $breakpoints
variable. If you
want to have a different gutter based on breakpoints, you can set a map as seen
on $column-gutter
.
If you need to manage the responsive gutter, you can use this mixin
$column-gutter: (
"xxsmall": 0.5em,
"medium": 1em,
"xlarge": 1.5em
);
.bar {
@include responsive-gutter {
margin-top: $column-gutter;
}
}
And the CSS will be:
@media only screen and (min-width: 0em) {
.bar {
margin-top: 0.5em;
}
}
@media only screen and (min-width: 45em) {
.bar {
margin-top: 1em;
}
}
@media only screen and (min-width: 80em) {
.bar {
margin-top: 1.5em;
}
}
If you are already in a mediaquery, the mixin will take only the current breakpoint, as shown below
.foobar {
@include media-query("medium") {
color: red;
@include responsive-gutter {
left: $column-gutter;
}
}
}
will become:
@media only screen and (min-width: 45em) {
.foobar {
color: red;
left: 1em;
}
}
Obviously it will work with math operations too:
.foobar {
@include media-query("xxsmall") {
@include responsive-gutter {
top: $column-gutter;
left: ($column-gutter / 2);
bottom: ($column-gutter * 2);
right: ($column-gutter + 2);
}
}
}
@media only screen and (min-width: 0em) {
.foobar {
top: 0.5em;
left: 0.25em;
bottom: 1em;
right: 2.5em;
}
}
dry-it()
arguments: $id
- $id
- required
- type:
string
NOTE: This mixin will change the order of your generated css.
One of the bad thing that we have in developing a grid without a default classes schema is that the resulting css code will be semantic, but not dry. You can (and you should) use gzip to serve your css, but there will still be redundant css code.
Example:
.foo {
@include grid-column(
(
small: 12,
large: 6
)
);
}
.bar {
@include grid-column(
(
small: 12,
large: 6
)
);
}
will generate this css:
.foo {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 40em) {
.foo {
width: 100%;
}
}
@media only screen and (min-width: 64em) {
.foo {
width: 50%;
}
}
.bar {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 40em) {
.bar {
width: 100%;
}
}
@media only screen and (min-width: 64em) {
.bar {
width: 50%;
}
}
We just generated the same code for two identical classes.
Sass helps with placeholders, but still we will need to extend too many selector to
have a dry behavior. What if we can generate placeholders on fly?
That is exactly what dry-it()
does. To use it you just need to set $use-dry
to true
.
The result will be like this:
.foo {
@include grid-column(
(
small: 12,
large: 6
)
);
}
.bar {
@include grid-column(
(
small: 12,
large: 6
)
);
}
will generate this css:
*.foo,
*.bar {
box-sizing: border-box;
padding-left: calc(1.875rem / 2);
padding-right: calc(1.875rem / 2);
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 40em) {
*.foo,
*.bar {
width: 100%;
}
}
@media only screen and (min-width: 64em) {
*.foo,
*.bar {
width: 50%;
}
}
IMPORTANT To use this option it is preferable to order your media query smaller to larger. I know, that is a very boring thing to do manually, but fortunally: PostCSS mqpacker comes to help us. An example on how to use it in gulp:
var mqpacker = require('css-mqpacker');
var postcss = require('gulp-postcss');
var sass = require('gulp-sass');
module.exports = function() {
return gulp.src('/styles/*.+(sass|scss)')
.pipe(sass())
.pipe(
postcss([
mqpacker({
sort: true
})
])
)
.pipe(gulp.dest('/styles/'));
You can find a complete gulp file in gulp/tasks/sass.js
.
Functions
We love Foundation and we've been using it a lot. These functions are based on our preferred Foundation functions that we want to continue to use in our projects.
remove-unit()
arguments: $value
- $value
- required
- type:
list
removes the unit from a value Example
$foo: remove-unit(10px); //will return 10
rem-calc()
arguments: $values
, $base-value
- $values
- required
- type:
list
- $base-value
- optional
- default:
$rem-base
- type:
measure
Transforms an array of pixel values (with or without px
) in rem unit, based on
the optional $base-value
passed to the function.
Examples
.foo {
margin: rem-calc(16 8 16 8);
padding: rem-calc(8px);
}
will return:
.foo {
margin: 1rem 0.5rem 1rem 0.5rem;
padding: 0.5rem;
}
em-calc()
arguments: $values
, $base-value
- $values
- required
- type:
list
- $base-value
- optional
- default:
$rem-base
- type:
measure
Transforms an array of pixel values (with or without px
) in em unit, based on
the optional $base-value
passed to the function.
Examples
.foo {
margin: em-calc(16 8 16 8);
padding: em-calc(8, 8);
}
will return:
.foo {
margin: 1em 0.5em 1em 0.5em;
padding: 0.5em;
}
px-calc()
arguments: $values
, $base-value
- $values
- required
- type:
list
- $base-value
- optional
- default:
$rem-base
- type:
measure
Transforms an array of ems or rems values (with or without em/rem
) in pixel
unit, based on the optional $base-value
passed to the function.
Example
.foo {
margin: px-calc(1em 0.5em 1em 0.5em);
padding: px-calc(1rem);
}
will return:
.foo {
margin: 16px 8px 16px 8px;
padding: 16px;
}
Extras
Run it
Would you like to collaborate? Here are some useful npm tasks:
$ npm run dev
-> Compiles sources, serves the dev folder and starts watchers
$ npm run compile
-> Compiles the sources for development
$ npm run build
-> Compiles for distribution
we have added unit tests recently. You can run it with Mocha.
BROWSER SUPPORT
Super GiGi is built in flex. So the browser support is
the same of the flexbox property. You can use the $use-float
or $use-table
setting variable to provide a fallback for the old browsers. It works fine for base case, you could use Modernizr for advanced one.
If you use the sass version, we suggest you to take a look to AutoPrefixer, to generate the vendor prefixes.
If you have to support old browsers you can try Flexie
DISTRIBUTED UNDER THE MIT LICENSE
The MIT License (MIT)
Copyright © 2015 Objectway S.P.A
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.