What is reflex? #

Reflex gives you the ability to easily take advantage of flexbox for laying out a grid while having a reliable inline-block fallback for older browsers.

At the time of writing, global flexbox support is at 94.1% (excluding browsers with outdated or partial support) so I propose that it's time to start taking advantage of flexbox and accept that the inline-block fallback won't support everything.

Where flexbox isn't supported, your basic grid structure will remain intact and most of the layout classes still work. Try this page out in a non-flexbox browser to see for yourself!

Why use reflex? #

  • It's lightweight - 12KB in it's minified form and 1.8KB gzipped
  • Where flexbox is supported, grid cells are all the same height by default
  • Reflex grid cells never push each other out of the way (as with floated grids)
  • Supports semantic elements e.g. you can use ul as a grid
  • Supports nested grids
  • Good cross browser support
  • Built in both Sass/SCSS and LESS
  • Built using BEM syntax
  • Easily customizable and extendable

Intended use #

  • Creating complex nested grids which take advantage of flexbox layout properties
  • Generating a reliable grid with dynamic content e.g. a list of products
  • An addition or replacement to your current css framework
  • A set of vendor-prefixed Sass or LESS mixins ready to be incorporated into an existing framework
  • A set of vendor-prefixed helper classes to get your flexbox solution off the ground faster

Use as CSS #

You can use the compiled css directly by downloading either the minified or non-minified version.

Clone via github#

You could clone this repo via github which would allow you to modify the variables such as the number of columns or the breakpoints.

Use with npm #

npm install reflex-grid

Visit the reflex npm page for stats.

Reflex grid introduction #

<div class="grid">
    <div class="grid__col-6">
        <content>
    </div>
    <div class="grid__col-6">
        <content>
    </div>
</div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc et sagittis dui. Maecenas rhoncus justo aliquam urna finibus tincidunt et ut mauris.
Vivamus nulla leo, dignissim nec tempor vel, consequat ac dolor. Nunc dignissim in ante sed dapibus. Aenean sit amet aliquet dolor, at auctor erat.

With reference to BEM syntax, this is the anamtomy of a reflex grid:

.grid

example: grid

This is the top level element and is similar to a row in bootstrap. It sets the following properties:

  • display: flex
  • flex-wrap: wrap

.grid__element

example: grid__col-xs-6

This is a child element of .grid and is similar to a col-x in bootstrap. It sets the following properties:

  • display: flex
  • flex-direction: column

.grid--modifier

example: grid--align-end

Modifier classes can be applied to both the grid and grid__element. Further examples include:

  • grid--no-wrap
  • grid--align-end
  • grid--justify-center

Browser support #

Reflex falls back to an inline-block grid for browsers that do not support flexbox. Reflex uses some css hacks to help the inline-block grid work on older browsers. It's important to note that some of the features of flexbox do not have an equivalent in the inline-block fallback so not everything will work in the fallback, but your grid will remain intact.

If you want to use the grid with breakpoints in ie8 and below you will need to use respond.js which enables media query support in those browsers via JavaScript and html5Shiv if you wish to use html5 elements such as section

It is possible for this framework to support ie6. You can make a tiny change to enable support but it greatly increases the filesize of the css. Look in _mixins.scss (Sass) or mixins.less (LESS) for the commented line.

Semantic markup #

You don't have to use div for your grid and ideally you should use the most semantically appropriate markup for your use case with no visible difference.

Divs #

<div class="grid">
    <div class="grid__col-6">
        <content>
    </div>
</div>

Unordered list #

<ul class="grid">
    <li class="grid__col-6">
        <content>
    </li>
</ul>

Html5 elements #

<section class="grid">
    <article class="grid__col-6">
        <content>
    </article>
</section>

Numbered columns #

By default reflex is a 12 column grid but this can be easily changed. Regardless of how many columns you need, you will likely require extra control over the breakpoints at which your grid columns revert to 100% width. To do this you will need to use these modifier classes which determine grid columns at various viewport sizes. A grid built using numbered columns in this way will remain fully intact in the inline-block fallback.

The reflex grid breakpoints can be easily re-defined but are set to these values by default:

Class prefix grid__col- grid__col-xs- grid__col-sm- grid__col-md- grid__col-lg- grid__col-xlg-
Collapses at does not collapse < 480px < 768px < 992px < 1200px < 1600px

Auto columns #

You can add any number of auto sizing grid__col-auto columns to a grid and therefore avoid using numbered columns. You can also use the regular breakpoints to determine when your columns revert to 100% width. A grid built using auto columns will not remain fully intact in the inline-block fallback and will not work properly in ie10 due to it's limited flexbox support but if this is a concern, you could use JavaScript for that.

grid__col-auto
grid__col-auto
grid__col-sm-auto
grid__col-sm-auto
grid__col-md-auto

Flexbox direction and axis #

To understand how this grid works, you'll need to first understand how flexbox works, especially in relation to the cross axis and main axis. There's a pretty good introduction to flexbox here but here's a quick demo of the main points: flex direction, main axis, and cross axis.

row

↔ main axis

↕ cross axis

column

↕ main axis

↔ cross axis

By default any grid element is set to flex-direction: row and the main axis therefore follows the horizontal direction.

By default any grid__col-x element is set to flex-direction: column and the main axis therefore follows the vertical direction.

This will become important when you are using the modifier classes which typically act upon either the main or cross axis

Grid modifiers #

Grid wrapping #

By default, the flex-wrap property of a display: flex element is set to nowrap but because this is a grid framework we generally need our grid to wrap so we explcitly set flex-wrap: wrap on our grid element

grid__col-x elements do not wrap by default, but you can make them do so by using the modifier grid--wrap.

In the inline-block fallback your grid columns will always wrap when they add up to 100% width (12 column by default).

.grid--no-wrap #

When applied to grid sets flex-wrap: nowrap and gives you this:

these

columns

do not collapse

.grid--wrap-reverse #

When applied to grid sets flex-wrap: wrap-reverse and gives you a grid that wraps in reverse:

I am first in the markup

I am second in the markup

I am third in the markup

Cross axis modifiers #

These modifiers can be added to your grid element but also to the grid__col-x elements inside the grid.

Equal height columns by default #

In browsers that support flexbox we have equal height columns by default because the default value of align-items is stretch

First appear years night there the in them rule.

Over after behold was living together tree is very sixth let bring fish. Forth behold they're fly deep.

Be can't winged good for also saying first.

.grid--align-start #

When applied to grid or grid__col-x sets align-items: flex-start and gives you this:

First appear years night there the in them rule.

Over after behold was living together tree is very sixth let bring fish. Forth behold they're fly deep.

Be can't winged good for also saying first.

.grid--align-end #

When applied to grid or grid__col-x sets align-items: flex-end

First appear years night there the in them rule.

Over after behold was living together tree is very sixth let bring fish. Forth behold they're fly deep.

Be can't winged good for also saying first.

.grid--align-center #

When applied to grid or grid__col-x sets align-items: center

First appear years night there the in them rule.

Over after behold was living together tree is very sixth let bring fish. Forth behold they're fly deep.

Be can't winged good for also saying first.

.grid--align-baseline #

When applied to grid or grid__col-x sets align-items: baseline.

By default, different text elements in adjacent columns will be aligned by their size and margin:

Heading 2

Heading 3

Paragraph

With grid--align-baseline applied to the grid element the text lines up:

Heading 2

Heading 3

Paragraph

Cross axis override modifiers #

You can override the cross axis alignment of a single grid__col-x element by using these modifers.

.grid--align-self-stretch #

When applied to grid__col-x sets align-self: stretch

First appear years night there the in them rule that bring fly gathered there is place good.

stretch

First appear years night there the in them rule that bring fly gathered there is place good Created rule image night firmament.

.grid--align-self-start #

When applied to grid__col-x sets align-self: flex-start

First appear years night there the in them rule that bring fly gathered there is place good.

start

First appear years night there the in them rule that bring fly gathered there is place good Created rule image night firmament.

.grid--align-self-end #

When applied to grid__col-x sets align-self: flex-end

First appear years night there the in them rule that bring fly gathered there is place good.

end

First appear years night there the in them rule that bring fly gathered there is place good Created rule image night firmament.

.grid--align-self-center #

When applied to grid__col-x sets align-self: center

First appear years night there the in them rule that bring fly gathered there is place good.

center

First appear years night there the in them rule that bring fly gathered there is place good Created rule image night firmament.

Cross axis positioning #

These modifers set the value of align-content which determine the position of your grid elements when there is extra space available in the cross-axis (usually because you've set a height on the grid that is larger than the contents). These modifiers can be added to your grid element but also to the grid__col-x elements inside the grid.

This modifier has no effect when there is only one line of grid__col-x elements in the grid so cannot be used when grid--no-wrap is present on the grid or when you only have a single row of columns

Stretch by default #

In browsers that support flexbox we have equal height columns that stretch to fill the available space by default because the default value of align-content is stretch

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.grid--align-content-start #

When applied to grid or grid__col-x sets align-content: flex-start

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.grid--align-content-end #

When applied to grid or grid__col-x sets align-content: flex-end

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.grid--align-content-center #

When applied to grid or grid__col-x sets align-content: center

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.grid--align-content-space-between #

When applied to grid or grid__col-x sets align-content: space-between

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.grid--align-content-space-around #

When applied to grid or grid__col-x sets align-content: space-around

First appear

Great blessed

Years night

Firmament you

To lights

Place good

Main axis alignment #

These modifers set the value of justify-content which determine the position of your grid elements when there is extra space available in the main-axis (usually because your columns do not make up the full width of a grid). These modifiers can be added to your grid element but also to the grid__col-x elements inside the grid.

Left aligned by default #

Grid elements are aligned to the left by default because the default value of justify-content is flex-start

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

.grid--justify-end #

When applied to grid or grid__col-x sets justify-content: flex-end

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

.grid--justify-center #

When applied to grid or grid__col-x sets justify-content: center

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

.grid--justify-space-between #

When applied to grid or grid__col-x sets justify-content: space-between

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

First appear years night there the in them rule.

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

.grid--justify-space-around #

When applied to grid or grid__col-x sets justify-content: space-around

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

First appear years night there the in them rule.

First appear years night there the in them rule.

Be can't winged good for also saying first. Shall, fourth Greater cattle.

Flex direction #

These modifers set the value of flex-direction. These modifiers can be added to your grid element but also to the grid__col-x elements inside the grid.

Rows by default #

grid elements are in rows by default because the default value of flex-direction is row. grid__col-x elements are columns by default but can be set to behave as rows by using grid--direction-row

I am first in the markup

I am second in the markup

I am third in the markup

I am fourth in the markup

I am fifth in the markup

.grid--direction-row-reverse #

When applied to grid or grid__col-x sets flex-direction: row-reverse

I am first in the markup

I am second in the markup

I am third in the markup

I am fourth in the markup

I am fifth in the markup

.grid--direction-column #

When applied to grid or grid__col-x sets flex-direction: column

I am first in the markup

I am second in the markup

I am third in the markup

.grid--direction-column-reverse #

When applied to grid or grid__col-x sets flex-direction: column-reverse

I am first in the markup

I am second in the markup

I am third in the markup

Ordering grid elements #

These helper classes allow you to easily set order to your grid elements. This is useful because it allows you to have your markup in the correct semantic order for accessiblity purposes but in a different order visually.

By default there are 12 ordering helpers to match the default 12 columns. Changing the number of columns by editing the variable will also produce a matching number of order helper classes

.grid--order-<n> #

When applied to grid__col-x sets order: n

I am first in the markup but ordered second

I am second in the markup but ordered third

I am third in the markup but ordered first

Responsive ordering #

There are responsive ordering classes that correspond to both the number of columns and the breakpoints so you can choose to change the order of grid__col-x elements only above certain viewport sizes.

For example: .grid--order-2-md

.grid--order-<n>-<breakpoint> #

When applied to grid__col-x sets order: n when viewport size is above the selected breakpoint.

I am first in the markup but ordered second when viewport size is above 992px

I am second in the markup but ordered third when viewport size is above 992px

I am third in the markup but ordered first when viewport size is above 992px

Advanced grid layout #

.grid__cell #

There are some nuances with flexbox that may make your life difficult if you're not expecting them. There is a wealth of information available on this subject in the flexbox working draft.

This is part of flexbox, and is entirely expected. However, flexbox layout is not always appropriate so it's possible to add a grid__cell child element to your grid__col-x columns which defines an area of your column as display: block allowing you to lay out the contents of your grid elements like you would normally.

Flexbox differences

  • Margins on adjacent elements do not collapse
  • Margins set to auto absorb extra space and can be used for alignment
  • float, clear and vertical-align have no effect on a flex item

Column content by default

<div class="grid">
    <div class="grid__col-6">
        <content>
    </div>
    <div class="grid__col-6">
        <content>
    </div>
</div>

float: right

float: left

The top and bottom margins on these paragraphs do not collapse together as you would expect

The top and bottom margins on these paragraphs do not collapse together as you would expect

Column content using .grid__cell

<div class="grid">
    <div class="grid__col-6">
        <div class="grid__cell">
            <content>
        </div>
    </div>
    <div class="grid__col-6">
        <div class="grid__cell">
            <content>
        </div>
    </div>
</div>

float: right

float: left

The top and bottom margins on these paragraphs collapse together as you would expect

The top and bottom margins on these paragraphs collapse together as you would expect

.grid__cell-img #

If you're using a grid__cell as above, you can simply use your regular responsive image solution such as the solution used in bootstrap.

If you're not using a grid__cell, flex images need to be handled differently to make them responsive and you should use grid__cell-img.

<div class="grid">
    <div class="grid__col-sm-4">
        <img class="grid__cell-img" src="">
    </div>
</div>

It's possible to set up a footer section in a grid__col-x element that is always aligned to the bottom by using grid__cell-footer. This footer element is set up as a flex box so all the usual grid modifers work on it.

  • Consectetur adipiscing elit, sed do eiusmod.

  • Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc et sagittis dui. Maecenas rhoncus justo aliquam urna finibus tincidunt et ut mauris.

.grid--bleed #

By default, grid__col-x elements have padding to space the grid out. It's possible to override this in all grid__col-x child elements in a grid by applying the modifer grid--bleed to your grid element.

  • Consectetur adipiscing elit, sed do eiusmod.

  • Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc et sagittis dui. Maecenas rhoncus justo aliquam urna finibus tincidunt et ut mauris.

.grid__col--bleed #

You can override the padding on individual grid__col-x elements by using grid__col--bleed.

  • Default

  • grid__col--bleed applied

.grid__col--bleed-x #

You can override the left and right padding on individual grid__col-x elements by using grid__col--bleed-x.

  • Default

  • grid__col--bleed-x applied

.grid__col--bleed-y #

You can override the top and bottom padding on individual grid__col-x elements by using grid__col--bleed-y.

  • Default

  • grid__col--bleed-y applied

.grid__col--bg #

You can add a background image to grid__col-x elements by using grid__col--bg.

  • You can add a background image to grid__col-x elements by using grid__col--bg.

.grid__cell--padding-x #

You can apply padding to individual grid__cell elements by using grid__cell--padding-x.

  • padding-sm

  • padding-md

  • padding-lg

Visibility helpers #

You can use some generic visibility helpers that can be applied to any element, not just grid elements. resize the viewport to see them in action. The breakpoints can be changed if you're building the css via less or sass/SCSS.

.hidden-xxs
.hidden-md

Examples #

There are a handful of examples to show you what is possible with minimal effort on the demo page

Acknowledgements #

I would like to acknowledge the following resources which all helped in some way while I was building this: