Introduction #

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

Look at me!

I am a Reflex grid!

At the time of writing, browser flexbox support is at 96.63% so it's definitely time to forge ahead with flexbox, especially with a reliable inline-block fallback. 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 browser that does not support flexbox (such as Internet Explorer 9) to see for yourself!

The reason this works is because of the way browsers handle CSS properties that they do not understand. It's possible to include both your fallback and your ideal CSS properties in the same classes and let browsers use the ones that they do understand. I've written at length on this subject if you're interested in learning more.

This is version 2 of Reflex grid which is not compatible with version 1. The last release under version 1 was 1.5.0 and I have maintained the docs for version 1 in case you still need them.

Why use reflex? #

  • It's lightweight - 20KB in it's minified form and 2.5KB gzipped
  • Where flexbox is supported, columns 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 with Sass/SCSS
  • Easily customizable and extendable

Intended use #

  • Creating complex nested flexbox grids which take advantage of flexbox layout properties
  • Using a flexbox layout inside a CSS grid page layout
  • Generating a flexbox grid with dynamic content of varying height e.g. a list of products
  • An addition or replacement for your current css layout framework
  • A set of vendor-prefixed mixins and helper classes to get your flexbox solution off the ground faster

Browser support #

All browser specific implementations of flexbox are supported via vendor prefixes, including the slightly problematic IE10 implementation of an early draft of the flexbox specification. Internet Explorer 6 and 7 are explicitly not supported because there are so many issues and quirks that it renders the exercise futile. However, the basic grid still works in those browsers.

Breakpoints in ie8 #

If you want to use the grid with breakpoints in ie8 you will need to use respond.js which enables media query support in those browsers via JavaScript. There's very little downside to adding this because it's very lightweight and performs well.

HTML5 elements #

If you wish to use html5 elements such as section in older browsers such as ie8 and 9, you will need to use html5Shiv. Again, there's very little downside to using this considering the extra peace of mind it gives you when using html5 elements.

ie10 and ie11 grid heights #

ie10 and ie11 have a flexbox rendering bug which means that unless the height of the grid is set with an unit value, flex items will only stretch to be as large as their largest sibling. The grid will still work in these browsers, but it won't entirely fill the height of it's container unless a height in units is specified for the grid.

Please note that min-height and percentage heights will not work. The height must be set with px em or vh. There's further reading to be had on the bug itself if you wish to understand it further. You can use a CSS hack for ie10 and ie11 to set a unit height and solve these issues in your grid implementation.

.grid {
    min-height: 300px;

    @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
        height: 600px;
    }
}

box-sizing: border-box #

I highly recommend using a wildcard CSS query to set all elements to box-sizing: border-box. Reflex grid applies this to all grid elements so it is sized appropriately but you might want to also add these properties to your CSS framework to ensure consistent behaviour across all elements inside and outside of the grid:

*, *::after, *::before {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

Usage #

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 and build your own version of this grid. You can modify things like the number of columns or the breakpoints.

Use with npm #

If you're familiar with npm you can use npm install reflex-grid to have a look around, or add it as a dependency to your node project.

Visit the reflex-grid npm page for stats and other npm related info.

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.

In a nutshell, any direct child elements of a flexbox container are treated as flex items and can be layed out with flexbox css properties on either axis.

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

You can optionally set any col-x element to operate as a flex container using the class col-grid which sets flex-direction: column and the main axis therefore follows the vertical direction. There's more information on this in the Using flexbox in columns section.

Anatomy of a reflex grid #

Basic example #

I have added some colour as a visual indicator to all the examples on this page so you can clearly see how the layout works. This is just for demonstration purposes.

<div class="grid">
    <div class="col-6">
        <content>
    </div>
    <div class="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.

A closer look #

grid parent

example: grid

This is the top level container element and is similar to a row in bootstrap. Any .col element that is a direct child of a .grid is a flex item and their layout can be affected by any modifer classes placed on the parent .grid.

column child

examples: col-10 col-sm-6 col-auto

This is a child element of .grid and behaves as a flex item.

grid modifier

examples: align-end no-wrap justify-center

Modifier classes can be applied to the .grid element to modify the layout of it's direct children elements.

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="col-6">
        <content>
    </div>
</div>

Unordered list #

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

Html5 elements #

<section class="grid">
    <article class="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:

col-
does not collapse
col-xs-
collapses below 576px
col-sm-
collapses below 768px
col-md-
collapses below 992px
col-lg-
collapses below 1200px
col-xlg-
collapses below 1600px

col-4

col-4

col-4

col-xs-4

col-xs-8

col-sm-6

col-sm-6

col-md-8

col-md-4

col-lg-4

col-lg-8

col-xlg-8

col-xlg-4

Auto columns #

You can add any number of auto sizing col-auto columns to a grid and therefore avoid using numbered columns. You can also use the breakpoint sensitive classes such as col-sm-auto 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. For full browser support, you need to use numbered columns.

col-auto
col-auto
col-sm-auto
col-md-auto
col-lg-auto
col-xlg-auto

Containers #

A Reflex grid will fill the full width of it's parent element which means you can drop it into any containing element you may already have in place.

However, Reflex grid has a responsive .container class available which uses a combination of margins and padding to maintain layout between elements both inside and outside of the grid. By default this uses the same breakpoints as the numbered columns. However, It is possible to modify the max width and breakpoints of the .container class by modifying the included variables.scss file and building a new css file.

Responsive container #

<div class="container">
    <p>This element is inside the container but outside of the grid</p>
    <div class="grid">
        <div class="col-6">
            <p>An element inside the grid</p>
        </div>
        <div class="col-6">
            <p>Another element inside the grid</p>
        </div>
    </div>
</div>

This element is inside the container but outside of the grid

An element inside the grid

Another element inside the grid

Full width container #

If you desire a full width container without a max width but with the same combination of margins and padding to maintain layout between elements both inside and outside of the grid there is also a .container-full class available.

<div class="container-full">
    <p>This element is inside the <em>full width</em> container but outside of the grid</p>
    <div class="grid">
        <div class="col-6">
            <p>An element inside the grid</p>
        </div>
        <div class="col-6">
            <p>Another element inside the grid</p>
        </div>
    </div>
</div>

This element is inside the full width container but outside of the grid

An element inside the grid

Another element inside the grid

No container #

Without a container, the grid fills it's containing element (in this case the body element).

An element inside the grid

Another element inside the grid

Nested grids #

It's possible to nest grids inside each other. Start a new .grid inside a .col-x element and everything lines up correctly. There are some more advanced examples of layouts on the examples page.

<div class="grid">
    <div class="col-sm-6">
        <content>
    </div>
    <div class="col-sm-6">
        <div class="grid">
            <div class="col-6">
                <content>
            </div>
            <div class="col-6">
                <content>
            </div>
            <div class="col-6">
                <content>
            </div>
            <div class="col-6">
                <content>
            </div>
        </div>
    </div>
</div>

col-sm-6

col-6

col-6

col-6

col-6

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

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

default wrap #

Grid columns wrap by default.

col-6

col-6

col-10

.no-wrap #

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

col-6

col-6

col-10

.wrap-reverse #

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

col-6 (I am first in the markup)

col-6 (I am second in the markup)

col-10 (I am third in the markup)

Cross axis modifiers #

These modifiers can be added to your grid element.

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.

.align-start #

When applied to grid 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.

.align-end #

When applied to grid 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.

.align-center #

When applied to grid 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.

.align-baseline #

When applied to grid sets align-items: baseline. This makes col-x elements line up according to the baseline of the first child element (as long as the first elements in each column are an inline element such as headings or paragraphs). This example should make this confusing behaviour a bit clearer:

Biggest text

Medium text

Small text

Cross axis override modifiers #

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

.align-self-stretch #

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

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

.align-self-stretch

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

.align-self-start #

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

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

.align-self-start

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

.align-self-end #

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

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

align-self-end

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

.align-self-center #

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

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

align-self-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 col-x elements inside the grid.

This modifier has no effect when there is only one line of col-x elements in the grid so cannot be used when 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

.align-content-start #

When applied to grid sets align-content: flex-start

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.align-content-end #

When applied to grid sets align-content: flex-end

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.align-content-center #

When applied to grid sets align-content: center

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.align-content-space-between #

When applied to grid sets align-content: space-between

First appear

Great blessed

Years night

Firmament you

To lights

Place good

.align-content-space-around #

When applied to grid 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 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.

.justify-end #

When applied to grid 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.

.justify-center #

When applied to grid 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.

.justify-space-between #

When applied to grid 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.

.justify-space-around #

When applied to grid 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 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. col-x elements are columns by default but can be set to behave as rows by using 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

.direction-row-reverse #

When applied to grid 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

.direction-column #

When applied to grid sets flex-direction: column

I am first in the markup

I am second in the markup

I am third in the markup

.direction-column-reverse #

When applied to grid 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

.order-<n> #

When applied to 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 col-x elements only above certain viewport sizes.

For example: .order-md-2

.order-<breakpoint>-<n> #

When applied to 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

Responsive offsets #

There are responsive offset classes that correspond to the available breakpoints so you can choose to offset your col-x elements at certain viewport sizes.

For example: .offset-md-2

.offset-<breakpoint>-<n> #

When applied to col-x applies an offset when viewport size is above the selected breakpoint.

Offset by 3 columns at all times

Offset by 2 columns when viewport size is above 768px

Offset by 1 column when viewport size is above 1200px

Padding modifiers #

By default, col-x columns have internal padding. It's possible to remove this padding on the entire grid or single columns.

.grid-bleed #

When used on a .grid element, removes internal padding from all child col-x column elements.

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.

.col-bleed #

Removes internal padding from a single col-x column element.

.col-bleed

Default column

.col-bleed-x #

Removes internal horizontal padding from a single col-x column element.

.col-bleed-x

Default column

.col-bleed-y #

Removes internal vertical padding from a single col-x column element.

.col-bleed-y

Default column

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 yourself by building the SCSS files.

.hidden-xxs

.hidden-md

.hidden-xlg

Using flexbox in columns #

By default, a .col-x element behaves like a good old fashioned block element but it is possible to modify it to perform as a flexbox element with flex-direction: column by adding the .col-grid class to any col-x element. This will allow you to take advantage of flexbox layout and (for example) create a footer that is always at the bottom of the column.

When a column has the .col-grid class applied to it, any of the grid modifiers such as .justify-space-between will work on it but be aware that the orientation is in the column direction and therefore the main axis is vertical.

When using flexbox for column layout, be aware that flex items cannot be floated and their margins do not collapse. Here's the relevant information from the flexbox spec:

A flex container establishes a new flex formatting context for its contents. This is the same as establishing a block formatting context, except that flex layout is used instead of block layout. For example, floats do not intrude into the flex container, and the flex container’s margins do not collapse with the margins of its contents.

As long as you're aware of these facts, you won't be surprised when you start using flexbox in columns.

A .flex-footer element that is the last child of a .col-grid column will always appear at the bottom of the column, regardless of how much content you have above it.

<div class="grid">
    <div class="col-6 col-grid">
        <content>
        <div class="flex-footer">
            <p>.flex-footer</p>
        </div>
    </div>
</div>

Aliquam ornare faucibus leo, vel euismod nisi porta non. Donec at arcu eget enim bibendum facilisis. Etiam urna elit, blandit ut libero placerat, iaculis aliquam erat.

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

Aliquam ornare faucibus leo.

.flex-img #

Responsive images are nothing new and most frameworks include classes to create them. For example, bootstrap uses this solution. However, there are some additional complexities in some browsers when using images as a flex item. Therefore, when using an image in a column with the .col-grid class, you should use the class .flex-img which solves these problems.

<div class="grid">
    <div class="col-6 col-grid">
        <img class="flex-img" src="images/1.jpg">
    </div>
</div>

Cards #

A common use case for Reflex grid is to create product cards of the same height. The CSS for this is not part of Reflex grid and you would need to add your own card classes on top of reflex but I have included a few examples below and many more on the examples page to help you get started.

If you want to use these card styles as a starting point for your own implementation you can incorporate the SCSS I wrote for these cards into your CSS build.

Amazing

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

Crazy good

Nunc dignissim in ante sed dapibus. Aenean sit amet aliquet dolor, at auctor erat. Aliquam ornare faucibus leo, vel euismod nisi porta non.

Lovely stuff

Aenean sit amet aliquet dolor, at auctor erat. Aliquam ornare faucibus leo, vel euismod nisi porta non. Donec at arcu eget enim bibendum facilisis.

read more

Examples #

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

Acknowledgements #

Browserstack logo

I use browserstack to test this in different browsers and I'm a big fan of their service in general. Thanks Browserstack!

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