The Basics

    What it is

    Grid ensures that designs are usable and look good across multiple viewports. It consists of the GridRow and GridCol components, which provide structure for web pages and specify how their layout should vary according to the window size.

    How it works

    • A page with GridRow and GridCol components checks the width of the window on load.
    • Depending on the Grid rules set for the page, content loads in the layout best suited for the current window width or device type.
    • If the page was designed to be responsive, it adjusts itself as the window width shrinks or expands to specific breakpoints or pixel widths. The content elements change position or size for the best fit in the new window.

    When to use

    • To build responsive web pages with content that resizes and realigns itself based on the window width

    When not to use

    • For pages that require a specific or pixel-perfect layout, because Grid is fluid and flexible
    • For elements that need to appear in a specific place on the page (that is, they require relative, absolute, or fixed positioning)

    What to use instead

    Doesn’t apply to this component.

    How to use

    Grid is used in the code to organize and lay out content. Designers should understand how to create responsive layouts based on Grid’s framework, but there’s no actual Grid component in the Figma design library. For more information about designing with Grid, see Grid, Spacing, and Layout.

    Grid provides a powerful and predictable way for pages to resize fluidly. This fluidity is a cornerstone of responsive web design, and it relies on breakpoints, or set window pixel widths.

    • When the page renders, CSS is used to display the content in the layout that best fits the available width.
    • If the window is resized, and the viewport width hits a breakpoint, the layout is automatically updated according to the new width. This can involve changing container shapes, moving sections around, or even hiding parts of the content completely.

    This is common on mobile-friendly sites, where content sections displayed horizontally in a row on the desktop are automatically displayed in a stacked, vertical layout on a mobile phone (without coding 2 different versions of the page).

    Forge has 5 breakpoints:

    • Small: viewports narrower than 640px (mobile devices)
    • Medium: viewports between 640 and 1024px (tablets in portrait mode)
    • Large: viewports between 1024 and 1200px (tablets in landscape mode and laptops)
    • XLarge: viewports between 1200 and 1440px (laptops and desktops)
    • XXLarge: viewports over 1440px (desktops)

    In the Forge Grid, each GridRow is divided into columns: 12 equal vertical sections that span the full available width. The content is then laid out inside GridRow, using GridCol to define how many columns the content should span. A GridRow can contain one or more GridCols.

    Consider this example desktop page layout:

    • A lefthand navigation panel, defined by a GridCol that spans 3 columns across (out of the total 12)
    • The main body of content, defined by a GridCol that takes up the remaining 9 columns

    On narrow, mobile screens, a lefthand navigation panel doesn’t work well, so in small viewports, the page layout might change to:

    • The main body of content, now defined by a GridCol that takes up the full width of the page, 12 of 12 columns across
    • An overflow menu that contains the navigation content, which is hidden until users tap to open it

    See Grid, Spacing, and Layout for more information (with diagrams) about using Grid to design layouts.

    Content spacing

    GridCol sections have default padding (called “gutters”) to create visual space between the content of neighboring GridCols. This can be turned off at certain breakpoints, if necessary.

    To add even more space between columns in a GridRow, you can use an “offset”: a space between GridCols, measured in columns. By default, this offset is the same for all breakpoints, but it can be different for small, medium, and large viewports.

    Nesting

    For complex designs, it’s possible to nest a Grid in another Grid. More specifically, this is a GridRow with one or more GridCols inside it, and then one of those GridCols contains a smaller GridRow with its own content. Nested grids can be set to span the full width of the parent GridCol (without the parent’s padding getting in the way).

    Nesting creates finer control on pages intended for desktop use, but this approach can also lead to complications: Grids nested more than 1 level deep can cause unexpected scaling behavior in smaller viewports. GridRow’s 12 columns should be enough for most use cases, without needing to nest a Grid and subdivide the page layout to create additional columns.

    Stacking

    As seen on mobile-first websites, GridCols can be set to switch from a horizontal layout to a stacked, vertical layout in narrow viewports, with GridCols displayed top to bottom instead of left to right. This stacking behavior can be applied to the medium and large breakpoints, as well, though it’s less useful in wider viewports.

    Order of content sections

    If a GridRow has multiple GridCols in it, they’re ranked by default in left-to-right, horizontal order. This order is important because it maps to a top-to-bottom, vertical order if the GridCols switch to that layout in smaller viewports. This means that, on a mobile device, the left GridCol appears first on the page, the middle GridCol appears second, and the right GridCol appears third.

    You can adjust this order for your use case. For example, the left GridCol could be set to appear last instead of first in small viewports. This granular control can be particularly useful for complex pages where the order of GridCol sections might need to change in medium or small viewports.

    Style

    Design details

    GridRow

    A horizontal content section that spans the full width of its container. Each GridRow is divided into 12 equal vertical sections, or columns.

    GridCol

    A vertical content section in a GridRow that can be set to fill 1 or more of its columns. For example, a GridCol could be 3 columns wide (out of the total 12).

    Space between content

    Gutters are the left and right padding inside GridCols. They add visual space between content in adjacent GridCols. The amount of padding is 15px, creating a 30px gutter between content sections and a 15px gutter at the edges (the far left and right sides of the web page).

    Gutters can be turned on or off at different breakpoints, but there are pros and cons. For example, turning gutters off in small viewports saves space, but it also removes the space between columns, making the content harder to read.

    Nested Grids have the same gutter widths as the parent Grid. They can be set to span the full width of their containing GridCol to prevent unsightly double-edge gutters.

    Your use case might call for more than 30px of space between GridCols. This offset is measured in columns. For example, a page layout might be a panel that spans 2 columns, an offset of 1 column, and a main work area that spans the remaining 9 columns.

    Vertical alignment

    In a GridRow, GridCols are set to vertically fill the GridRow space from top to bottom by default (using the CSS flexbox stretch alignment). This can be set to top, middle, or bottom alignment instead.

    Inside each GridCol, the content itself is also set to vertically fill its GridCol space from top to bottom by default. The content can also be set to top, middle, or bottom alignment instead.

    Placement and hierarchy

    No additional information for this component.

    Content

    Grid is invisible (no borders, dividers, or titles) and accommodates any and all web content. For guidance on specific content types, please refer to our other component pages.

    Demos

    Simple Responsive Example Share

    Default Sizing Share

    Offsets Share

    Ordering Share

    Gutters Share

    Nesting Share

    Row Shorthands Share

    Vertical Alignment Share

    Coding

    Developer tips

    Grid is made up of GridRow components whose children are GridCol components. These React components are convenience wrappers that generate elements with the appropriate CSS classes. The CSS does all the work and is based on Foundation's Flex Grid.

    Column widths and offsets are specified in units representing columns. Each unit is 1/12 the width of the GridRow.

    Layout and breakpoints

    The layout can be configured for each breakpoint: small, medium, and large.

    Here’s an example of setting a GridCol to change width at certain breakpoints:

    <GridCol width={{ small: 12, large: 6 }}/>

    On small and medium screens, this GridCol takes up 12 units (the full width of the GridRow). On large screens, it takes up 6 units (half the GridRow).

    Layout breakpoints can also be configured for any props, not just width. For example, <GridCol className={{ small: 'col-small', large: 'col-large' }} /> applies different class names, depending on the breakpoint.

    When a prop is configured for a certain breakpoint, it applies to all larger breakpoints as well, unless explicitly set to something else. In the 2 examples above, the medium breakpoint uses the width and className of the small breakpoint, even though the code doesn’t specifically mention “medium”.

    Vertical alignment

    Vertical alignment is determined using the align props of the GridRow (for all columns) or the GridCol (for a single column). The possible alignments are 'top', 'bottom', 'middle', and 'stretch'. These are based on flexbox align-items (or align-self) and correspond to 'flex-start', 'flex-end', 'center', and 'stretch', respectively.

    Repository

    Implementation links

    GridCol directory in Bitbucket

    GridRow directory in Bitbucket

    Implementation details

    It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

    Storybook files

    Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook-lts.

    Testing library

    Forge strongly encourages using testing-library to write tests for your application.

    "The more your tests resemble the way your software is used, the more confidence they can give you."

    If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

    With that being said, many of Forge's components were not built with accessability in mind. These components do break the recommendations listed above.

    Import statements

    In Nimbus applications

    athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

    import { GridCol, GridRow } from '@athena/forge'

    In standalone applications

    Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

    import GridCol from '@athena/forge/GridCol';
    import GridRow from '@athena/forge/GridRow';

    To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

    {
    "compilerOptions": {
    "moduleResolution": "Node16",
    }
    }

    If this setting doesn't work for your application, use this import statement instead:

    import GridCol from '@athena/forge/dist/GridCol';
    import GridRow from '@athena/forge/dist/GridRow';

    Props