Grid
The grid is an invisible framework responsible for the order and rhythm of a page. By imposing constraints on layout, the grid makes it easy to achieve consistent and proportionate designs across devices.
The grid is divided into 12 even column widths. The most common layouts divide this space up evenly, e.g. three 4-column, or two 6-columns.
On Extra-Small and Small screens (e.g. phones and tablets), you should only divide a row into 3-column, 6-column, 9-column, or 12-column sections.
The grid uses fluid widths for the columns, so as the overall grid widens, so will each of its columns.
Gutter (between grid elements) and margin (around the whole grid) differ according to screen size, where larger screens have more whitespace.
Playground
Usage
The grid is made up of 3 components:
Grid Container - root of the grid. All of its children must be Rows.
Row - a single row within a Grid Container. All of its children must be Columns.
Column - a column within a Row. Its children can be arbitrary content, or a nested Row!
A Grid Container can have any number of Rows, and a Row can have any number of Columns.
Each Row supports 12 columns of content, divided up evenly, and with a gutter between them.
Each Column element needs to specify how many grid columns it spans, using either the span
prop (in React) or a col-*
class (in vanilla).
<GridContainer><Row><Column span={3} backgroundColor="light-grey">Span 3/12</Column><Column span={9} backgroundColor="light-blue">Span 9/12</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="background-light-grey col-3">Span 3/12</div><div class="background-light-blue col-9">Span 9/12</div></div></div>
You can safely place more than 12 columns' worth of content inside a single Row; the Row will show the first 12 columns' worth, and then will line-wrap the rest:
<GridContainer><Row><Column span={4} backgroundColor="light-grey">Span 4/12</Column><Column span={4} backgroundColor="light-blue">Span 4/12</Column><Column span={4} backgroundColor="light-grey">Span 4/12</Column><Column span={4} backgroundColor="light-blue">Span 4/12</Column></Row></GridContainer>
<GridContainer><Row><Column span={3}>Content inside a 3-column element</Column><Column span={9}>Content inside a 9-column element</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-3">Content inside a 3-column element</div><div class="col-9">Content inside a 9-column element</div></div></div>
Nesting
It is possible to nest a Row within a Column in order to create a "nested grid".
<GridContainer><Row><Column span={6}><Row><Column span={3}>Nested content</Column></Row></Column></Row></GridContainer>
Note that it is not necessary to include another Grid Container. Simply adding another Row will do.
Columns don't have any special behavior when nested. They are always proportional to their Row's width. The nested (inner) grid will be divided into 12 new columns, proportional to the width of the nested (inner) grid.
That is: a 6-column element will always take up 6/12ths (50%) of its parent Row, no matter how wide that Row happens to be, and no matter how that Row happens to be nested.
Feel free to recursively nest these components as many times as you want. Just make sure that every Column is a direct child of a Row, and that every Row is a direct child of either a Grid Container or a Column.
Responsive
The grid's layout is adjustable for the different screen sizes that Visage defines:
Large - 1440 pixels or more (e.g. wide monitors)
Medium - 1024-1439 pixels (e.g. small monitors)
Small - 768-1023 pixels (e.g. tablets, some large phones in landscape)
Extra-Small - less than 768 pixels (e.g. most phones)
For a given Column component, you can change how many grid columns it spans at different screen sizes. You can also re-order Column elements within a given Row by "pushing" and "pulling" them leftward and rightward.
Resizing Columns
When you give a Column component a number of columns to span, by default it will have that width across all screen sizes — except for Extra-Small screens, where a Column component defaults to being 12 columns wide, so that the default layout on a phone is a single-column layout with no side-by-side content.
(For example, if you had two Columns each to set span 6 columns, they would be side-by-side on all screen sizes except for Extra-Small screens, where they would each take up the full width of the screen, and would end up stacked on top of one another.)
A Column can then override that value at specific screen sizes:
In React
To override at a given screen size, use the appropriate span*
prop on a Column
component:
span
- sets the default size for theColumn
spanXs
- overrides the default size onxs
screens (default:12
)spanSm
- overrides the default size onsm
screensspanMd
- overrides the default size onmd
screensspanLg
- overrides the default size onlg
screens
In Vanilla
To override at a given screen size, add the the appropriate col-X-N
class to the col-N
element, where "X
" is the screen size (lg
, md
, sm
, or xs
), and "N
" is the number of columns.
For instance, to make a Column element take up 6 columns on Large screens, add the class col-lg-6
to it.
<div class="grid-container"><div class="row"><div class="col-12 col-md-6 col-lg-6">This content has a default of 12/12ths (100%), and will use that value onExtra-Small and Small screens, but has overrides to take up 6/12ths (50%)of the width on Medium and Large screens</div></div></div>
Reordering Columns
If columns in a row need to be re-ordered on a certain screen size, they can be "pushed" rightward or "pulled" leftward, based on the screen size. Use the pull*
and push*
properties to do this.
Note: pulls and pushes are ignored on Extra-Small screens.
In the example below, we have two Column elements that span 6 columns. For Medium and Large screens, we'll push the left-hand Column rightwards by 6 columns, and we'll pull the right-hand Column leftwards by 6 columns. The effect is that the Columns switch places on Medium and Large screens.
<GridContainer><Row><Column span={6} spanXs={6} pushMd={6} pushLg={6}>This on the left on Extra-Small and Small screens, but on the right onMedium and Large screens</Column><Column span={6} spanXs={6} pullMd={6} pullLg={6}>Here's another column</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-6 col-xs-6 col-md-push-6 col-lg-push-6">This on the left on Extra-Small and Small screens, but on the right onMedium and Large screens</div><div class="col-6 col-xs-6 col-md-pull-6 col-lg-pull-6">Here's another column</div></div></div>
Offsets
Offsets let you indent a grid element, or widen the gap between elements. Offsets shift a block over to the right by a certain number of column widths. (This is generally preferable to creating empty space with an empty Column component.)
Offsets are ignored on Extra-Small screens.
<GridContainer><Row><Column span={3} backgroundColor="light-grey">Span 3/12</Column><Column span={7} offset={2} backgroundColor="light-blue">Span 7/12 with an offset of 2</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-3">Content inside a 3-column element</div><div class="col-9 col-offset-2">Content inside a 9-column element</div></div></div>
Responsive Offsets
You can make an offset only occur for a certain screen size:
In React, use an
offset*
property. For instance,offsetSm
will set an offset on Small screens.In vanilla, use an
col-offset-*
class. For instance,col-offset-sm
will set an offset on Small screens.
Grids as Lists
Often times Grid elements are semantically "list" elements. e.g. a Grid Container where each Row is an item in the shopper's cart, or a Row that is a list of tiles and each Column holds a tile.
It may be clear to sighted users that they're looking at a list of items, but that information will not be clear by default in the Accessibility Tree. In these cases, you can (and should) set the grid elements to be list elements (that is, <ul>
and <li>
tags.)
<GridContainer component="ul"><Row component="li"><Column span={12}><CartItem /></Column></Row><Row component="li"><Column span={12}><CartItem /></Column></Row></GridContainer>
Flex Columns
A Flex Column will cause all of its direct children to be arranged vertically, spread out evenly between the top and bottom of the row (rather than all being aligned to the top). This is useful for keeping some elements aligned to the top and bottom of a taller neighboring element.
A
A
A
A
A
C
C
<GridContainer><Row><Column span={4}><Box backgroundColor="light-grey">A<br />A<br />A<br />A<br />A<br />A</Box></Column><Column span={4} backgroundColor="dark-blue" flexColumn><Box backgroundColor="light-blue">First child of B, where B is a Flex Column</Box><Box backgroundColor="light-blue">Second child of B</Box></Column><Column span={4}><Box backgroundColor="light-grey">C<br />C<br />C</Box></Column></Row></GridContainer>
<GridContainer><Row><Column span={4} flexColumn>Flex Column contents go here</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-4 col-flex-column">Flex Column contents go here</div></div></div>
Vertically Center
The "vertically center" option on a Column element will cause its contents to be vertically centered within the row, rather than being aligned to the top.
A
A
A
A
A
C
C
<GridContainer><Row><Column span={4}><Box backgroundColor="light-grey">A<br />A<br />A<br />A<br />A<br />A</Box></Column><Column span={4} verticallyCenterContent><Box backgroundColor="light-blue">B is vertically centered</Box></Column><Column span={4}><Box backgroundColor="light-grey">C<br />C<br />C</Box></Column></Row></GridContainer>
<GridContainer><Row><Column span={4} verticallyCenterContent>contents of vertically centered element</Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-4 col-vertically-center">contents of vertically centered element</div></div></div>
Sticky Columns
Making a Column "sticky" means it will stay on screen as you scroll, so long as some other element in the same Row is also visible.
To make the stickiness function properly, the row will not vertically stretch all its columns to be the same height, as it normally does. This can affect the display of the columns in that row. For instance, if you are using a Card Container with the "even height" option, the cards in that row may not be all the same height.
<GridContainer><Row sticky><Column span={3} sticky><Box backgroundColor="medium-yellow" py={9}>Sticky coolumn</Box></Column><Column span={3}><Box backgroundColor="opal" style={{ padding: '120px 0 700px 0' }}>Column in the same row with really tall content</Box></Column></Row></GridContainer>
<div class="grid-container"><div class="row row-sticky"><div class="col-3 col-sticky"><div class="background-medium-yellow py-9">Sticky column</div></div><div class="col-3"><div class="background-opal" style="padding: 120px 0 700px 0">Column in the same row with really tall content</div></div></div></div>
You can also make a sticky column act normally (that is, not sticky) on Extra-Small screens. In React, add the unsticky="xs"
to the Column element; in vanilla, JS, add the class col-unsticky-xs.
Tight Grids
The "tight" grid uses very narrow gutters between grid elements. It is intended only for use with Standard Tiles with the "gallery" skin.
<GridContainer gutter="tight"><Row><Column span={4}><StandardTile skin="product" component="a" href="#"><StandardTileImage><FluidImage src="https://picsum.photos/400/200" /></StandardTileImage><StandardTileContents><StandardTileName>Name</StandardTileName></StandardTileContents></StandardTile></Column><Column span={4}><StandardTile skin="product" component="a" href="#"><StandardTileImage><FluidImage src="https://picsum.photos/400/200?q=1" /></StandardTileImage><StandardTileContents><StandardTileName>Name</StandardTileName></StandardTileContents></StandardTile></Column><Column span={4}><StandardTile skin="product" component="a" href="#"><StandardTileImage><FluidImage src="https://picsum.photos/400/200?q=2" /></StandardTileImage><StandardTileContents><StandardTileName>Name</StandardTileName></StandardTileContents></StandardTile></Column></Row></GridContainer>
<GridContainer gutter="tight"><Row><Column span={4}>first element</Column><Column span={4}>second element</Column><Column span={4}>third element</Column></Row></GridContainer>
<div class="grid-container grid-container-tight"><div class="row"><div class="col-4">first element</div><div class="col-4">second element</div><div class="col-4">third element</div></div></div>
Floating Container
A Floating Container is a content container that has a width equal to a certain number of grid columns. It pins its contents to the left- or right-hand side of a Column element, with the rest of that parent's content flowing and wrapping around it.
A Floating Container is itself a Column element (but using the "floating container" option), and must be the direct child of a Column element.
Floating Containers are typically used for secondary content, such as a supporting image or pull quote. If the content of the floating container is secondary to the main text (as is usually the case), consider using a semantically-accurate <aside>
tag instead of the default <div>
for the floating container.
A col-12 with additional text that should start to the right of the container, and wrap around the container so that it ends up below the container. (Except on Extra-Small screens, where all the text should sit below the container.) Here's some additional text to make this paragraph a little longer.
This Floating Container is aligned to the right instead. Here's some additional text to make this paragraph a little longer. Here's some additional text to make this paragraph a little longer. Here's some additional text to make this paragraph a little longer. Here's some additional text to make this paragraph a little longer. Here's some additional text to make this paragraph a little longer.
<GridContainer><Row><Column span={12}><Column span={6} floatingContainer><Box backgroundColor="opal">Floating container contents with a span of 6</Box></Column><p>A col-12 with additional text that should start to the right of thecontainer, and wrap around the container so that it ends up below thecontainer. (Except on Extra-Small screens, where all the text should sitbelow the container.) Here's some additional text to make thisparagraph a little longer.</p></Column></Row><Row><Column span={12}><Column span={4} floatingContainer floatingContainerAlignment="right"><Box backgroundColor="opal">Floating container contents with a span of 4</Box></Column><p>This Floating Container is aligned to the right instead. Here'ssome additional text to make this paragraph a little longer. Here'ssome additional text to make this paragraph a little longer. Here'ssome additional text to make this paragraph a little longer. Here'ssome additional text to make this paragraph a little longer. Here'ssome additional text to make this paragraph a little longer.</p></Column></Row></GridContainer>
<div class="grid-container"><div class="row"><div class="col-12"><div class="col-6 floating-container">Floating container contents with a span of 6</div><p>A col-12 with additional text that should start to the right of thecontainer, and wrap around the container so that it ends up below thecontainer. (Except on Extra-Small screens, where all the text should sitbelow the container.) Here's some additional text to make this paragrapha little longer.</p></div></div><div class="row"><div class="col-12"><div class="col-4 floating-container floating-container-right">Floating container contents with a span of 4</div><p>This Floating Container is aligned to the right instead. Here's someadditional text to make this paragraph a little longer. Here's someadditional text to make this paragraph a little longer. Here's someadditional text to make this paragraph a little longer. Here's someadditional text to make this paragraph a little longer. Here's someadditional text to make this paragraph a little longer.</p></div></div></div>
Components
GridContainer
Prop | Type | Default | Description |
---|---|---|---|
cardDividers | boolean | Only applicable if the GridContainer is inside of a Card Adds dividers between each Column | |
gutter | "standard" | "tight" | standard | The gutter width |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
Row
Prop | Type | Default | Description |
---|---|---|---|
sticky | boolean | Whether the row allows sticky columns |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
Column
Prop | Type | Default | Description |
---|---|---|---|
spanXs | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 12 | The number of columns that this Column should occupy on extra-small screens |
spanSm | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this Column should occupy on small screens | |
spanMd | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this Column should occupy on medium screens | |
spanLg | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this Column should occupy on large screens | |
offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The default number of columns that this column should be shifted to the right | |
offsetSm | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this column should be shifted to the right on small screens | |
offsetMd | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this column should be shifted to the right on medium screens | |
offsetLg | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | The number of columns that this column should be shifted to the right on large screens | |
push | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the default order in which the Columns are rendered by | |
pushSm | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on small screens by | |
pushMd | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on medium screens by | |
pushLg | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on large screens by | |
pull | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the default order in which the Columns are rendered by | |
pullSm | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on small screens by | |
pullMd | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on medium screens by | |
pullLg | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Changes the order in which the Columns are rendered on large screens by | |
flexColumn | boolean | false | In a |
verticallyCenterContent | boolean | false | Whether or not the Column's content should be vertically centered within the Row |
sticky | boolean | 'none' | Whether or not the Column's content should be sticky |
unsticky | "none" | "xs" | 'none' | If a Column is normally sticky, which screen sizes the Column should NOT be sticky on |
floatingContainer | boolean | false | Whether the Column is a Floating Container |
floatingContainerAlignment | "left" | "right" | 'left' | Whether Floating Container should float left or right |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
Guidelines
Design Guidelines
Do
Use only 3-column, 6-column, 9-column, and 12-column widths on Extra-Small and Small screens.
Use a nested grid to achieve greater design flexibility.
Specify the layout for each breakpoint at handoff.
Don't
Adjust the widths of columns, margins, and gutters.
Scale or stretch UI to fit the grid. Use components as intended for layout.
Developer Guidelines
Do
If you are placing one Column element inside another, put a Row element around the inner element, or a layout error may occur.
Place more than 12 columns' worth inside a single row, if you have a layout such as a long list of tiles. The grid elements will show the first 12 columns' worth, and then will line-wrap the rest of the content down onto the next row.
Don't
Put spacing, margin, padding, widths, or other layout-oriented styling onto layout grid elements, or a layout errors may occur when grid's code is changed in the future. If you need to add this styling to your content, put that styling on a wrapper element placed just inside the grid element.
Combine grid elements with other components, by putting a grid CSS class and another component's CSS class on the same HTML element. (For instance, don't make a Column component also be a Standard Section component.) Those other components may add spacing that will conflict with the grid component's spacing, and might alter the grid's display. Notable exception: you can put Background Color onto a grid element.
Accessibility Guidelines
If the grid elements are semantically part of a list, use
<ul>
and<li>
tags as appropriate instead of<div>
tags. For instance, if a row contains a sequence of product tiles, the row should be an<ul>
tag, and the column elements should be<li>
tags — because semantically, those tiles are a list.