TGAM Flexbox Grid | The Globe and Mail Pattern Library

Overview

This adaptive grid system uses a single container, row(s), and column(s) to layout and align content. A mobile-first flexbox grid system based on the CSS flex display property.

  • A container provides a means to center your site's contents. Use .l-container for fixed width.
  • Content should be placed within columns, and only columns may be immediate children of rows.
  • There are four grid tiers, one for each responsive breakpoint: all breakpoints (extra small), small, medium, and large.
  • It supports different column counts for each of the grid tiers. Which are extra-small (1), small (8), medium (12), and large (16).
  • Grid tiers are based on minimum widths, meaning they apply to that one tier and all those above it (e.g., .l-col-sm-4 applies to small, medium, and large devices).
  • Unlike Bootstrap grid, which is percentage based, TGAM flexboxgrid columns are fixed width. Which allows easier nesting, but also forces you to explicitly define that columns width for each tier.

Be aware of the limitations and bugs around flexbox, like the inability to use some HTML elements as flex containers.

Containers

Containers are the most basic layout element and are required when using the grid system. Containers are fixed-width, meaning its max-width changes/adapts at each breakpoint, to a pre-determined fixed-width.

Containers should not be nested. You only require a single parent container. Resize your screen to see how the container adapts when between breakpoints.

8
1
7

HTML

<div class="l-container"> <div class="l-row"> <div class="l-col"> 8 </div> </div> <div class="l-row"> <div class="l-col-sm-1"> 1 </div> <div class="l-col-sm-7"> 7 </div> </div> </div>

Consistent fixed-width columns

REM based widths allow consistent column sizes regardless of grid nesting. However, you need to he explicit for each grid tier. If you don't specify the current tier, then the next smaller tier's column width will be used instead.

This could be also be desired behaviour, depending on what you were trying to accomplish. But as you see below, those columns may not align with the current grid tier's columns.

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O

HTML

<div class="l-container--overlay"> <div class="l-container"> <div class="l-row"> <div class="l-col-1 l-col-sm-8"> A </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-1"> B </div> <div class="l-col-1 l-col-sm-7"> C </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-2 l-col-md-4"> D </div> <div class="l-col-1 l-col-sm-6 l-col-md-8"> E </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-3 l-col-md-4 l-col-lg-6"> F </div> <div class="l-col-1 l-col-sm-5 l-col-md-8 l-col-lg-10"> G </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-4 l-col-md-6 l-col-lg-8"> H </div> <div class="l-col-1 l-col-sm-4 l-col-md-6 l-col-lg-8"> I </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-5 l-col-md-8"> J </div> <div class="l-col-1 l-col-sm-3 l-col-md-4"> K </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-6"> L </div> <div class="l-col-1 l-col-sm-2"> M </div> </div> <div class="l-row"> <div class="l-col-1 l-col-sm-7"> N </div> <div class="l-col-1 l-col-sm-1"> O </div> </div> </div> </div>

Responsive modifiers

Responsive modifiers enable specifying different column sizes, offsets, alignment and distribution at xs, sm, md & lg viewport widths.

A
B
C
D
E
F
G

HTML

<div class="l-container"> <div class="l-row"> <div class="l-col l-col-sm-2 l-col-md-2 l-col-lg-1"> A </div> <div class="l-col l-col-sm-4 l-col-md-8 l-col-lg-14"> B </div> <div class="l-col l-col-sm-2 l-col-md-2 l-col-lg-1"> C </div> </div> <div class="l-row"> <div class="l-col l-col-sm-2 l-col-md-2 l-col-lg-1"> D </div> <div class="l-col l-col-sm-6 l-col-md-10 l-col-lg-15"> E </div> </div> <div class="l-row"> <div class="l-col l-col-sm-4 l-col-md-8 l-col-lg-13"> F </div> <div class="l-col l-col-sm-4 l-col-md-4 l-col-lg-3"> G </div> </div> </div>

Responsive column counts

Each of the 4 breakpoint tiers has a different column count. Extra-small (1), small (8), medium (12), large (16).

Large: 1260px max-column, 1280px (80rem) breakpoint. Medium: 940px max-column, 980px (61.25rem) breakpoint. Small: 700px max-column, 768px (48rem) breakpoint. X-Small: 100%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

HTML

<div class="l-container"> <div class="l-row"> <div class="l-col l-col-sm-8 l-col-md-12 l-col-lg-16"> <span class="d-none d-none-sm d-none-md d-block-lg">Large: 1260px max-column, 1280px (80rem) breakpoint.</span> <span class="d-none d-none-sm d-block-md d-none-lg">Medium: 940px max-column, 980px (61.25rem) breakpoint.</span> <span class="d-none d-block-sm d-none-md d-none-lg">Small: 700px max-column, 768px (48rem) breakpoint.</span> <span class="d-block d-none-sm d-none-md d-none-lg">X-Small: 100%</span> </div> </div> <div class="l-row"> <div class="l-col l-col-sm-1 l-col-md-1 l-col-lg-1"> 1 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 2 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 3 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 4 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 5 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 6 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 7 </div> <div class="l-col-sm-1 l-col-md-1 l-col-lg-1 d-hidden-xs-down"> 8 </div> <div class="l-col-md-1 l-col-lg-1 d-hidden-sm-down"> 9 </div> <div class="l-col-md-1 l-col-lg-1 d-hidden-sm-down"> 10 </div> <div class="l-col-md-1 l-col-lg-1 d-hidden-sm-down"> 11 </div> <div class="l-col-md-1 l-col-lg-1 d-hidden-sm-down"> 12 </div> <div class="l-col-lg-1 d-hidden-md-down"> 13 </div> <div class="l-col-lg-1 d-hidden-md-down"> 14 </div> <div class="l-col-lg-1 d-hidden-md-down"> 15 </div> <div class="l-col-lg-1 d-hidden-md-down"> 16 </div> </div> </div>

Customizing the grid

Using our built-in grid Sass _variables.scss and maps, it’s possible to completely customize the predefined grid classes. Change the number of tiers, the media query dimensions, and the container widths—then recompile.

Columns and gutters

The number of grid columns and their horizontal padding (aka, gutters) can be modified via Sass variables. $grid-columns is used to generate the widths (in REMs) of each individual column while $grid-gutter-width-base sets padding-left and padding-right for the column gutters.

SCSS

// This value is used to convert PX based values into EM values, for media query breakpoints $grid-base-font-size: 16px; // Set the the width of the gutters between columns. // Choose 0px if you nest more grids than not, // and you prefer to manually set the gutter on // the final child column only. Which holds the content. $grid-gutter-width-base: grid-rem(20); // Set the number of columns, within a tier container. $grid-columns: ( xs: 1, // 100% column sm: 8, // 70px columns md: 12, // 60px columns lg: 16 // 60px columns );

Grid tier sizes

Moving beyond the columns themselves, you may also customize the tier sizes themselves. You can do so by updating the below Sass variables to:

SCSS

// Define the maximum width of a full column, within a tier container. $grid-sizes: ( // xs: 0, - intentionally excluded sm: grid-rem(700), md: grid-rem(940), lg: grid-rem(1260) ); // Optionally add extra padding to the left/right sides, within a tier container. // Final padding value will be this plus half of $grid-gutter-width-base $grid-paddings: ( xs: grid-rem(10), sm: 0, md: 0, lg: 0 ); // Define breakpoints that determine when to switch between the grid tiers. // These values could be equal to or greater to the $grid-containers values. $grid-breakpoints: ( xs: 0, // locked at zero sm: grid-rem(768), md: grid-rem(980), lg: grid-rem(1280) );

When making any changes to the Sass variables or maps, you’ll need to save your changes and recompile. Doing so will out a brand new set of predefined grid classes for column widths, offsets, pushes, and pulls. Responsive visibility utilities will also be updated to use the custom breakpoints.

Grid summary table

See how aspects of the grid system work across multiple devices with a handy table.

Extra small devices
Portrait phones
(≤767px)
(≤47rem)
Small devices
Landscape phones
(≥768px - ≤979px)
(≥48em - ≤61.24rem)
Medium devices
Tablets
(≥980px - ≤1279px)
(≥61.25em - ≤79rem)
Large devices
Desktops
(≥1280px)
(≥80rem)
Grid behavior Horizontal at all times Collapsed to start, horizontal above breakpoints
Max-column width None (auto) 700px 940px 1260px
Class prefix l-col- l-col-sm- l-col-md- l-col-lg-
# of columns 1 8 12 16
Gutter width 20px on left and right sides, of a single column. 20px between columns.
Nestable Yes
Offsets Yes
Column ordering Yes

Disable/exclude features

In the _variables.scss file. Disable any of the below (undesired) features to reduce the grid bundle size.

For details, refer to: Visibility classes, or display classes, or flexbox classes, or various grid classes.

SCSS

// Responsive visibility utility classes // Enable or disable features of the grid system $grid-include-hidden: true; // Display property utility classes // Enable or disable sub-features for this feature $grid-include-display-block: true; $grid-include-display-flex: true; $grid-include-display-inline-block: true; $grid-include-display-inline-flex: true; $grid-include-display-inline: true; $grid-include-display-none: true; $grid-include-display-table-cell: true; $grid-include-display-table: true; // Flexbox grid utility classes // Enable or disable sub-features for this feature $grid-include-flex-align-content: true; $grid-include-flex-align-items: true; $grid-include-flex-align-self: true; $grid-include-flex-direction: true; $grid-include-flex-justify-content: true; $grid-include-flex-order: true; $grid-include-flex-text-align: true; $grid-include-flex-wrap: true; // Flexbox grid layout classes // Enable or disable sub-features for this feature $grid-include-grid-debug: true; $grid-include-grid-overlay: true; $grid-include-grid-no-gutters: true; $grid-include-grid-offset: true; $grid-include-grid-pull: true; $grid-include-grid-push: true;

Responsive breakpoint mixins

Since the grid is developed to be mobile first, we use a handful of media queries to create sensible breakpoints for our layouts and interfaces. These breakpoints are mostly based on minimum viewport widths and allow us to scale up elements as the viewport changes.

The grid primarily uses the following media query ranges—or breakpoints—in our source Sass files for our layout, grid system, and components.

Since we write our source CSS in Sass, all our media queries are available via Sass mixins:

SCSS

@include grid-breakpoint-up(xs) { ... } @include grid-breakpoint-up(sm) { ... } @include grid-breakpoint-up(md) { ... } @include grid-breakpoint-up(lg) { ... } // Example usage: @include grid-breakpoint-up(sm) { .some-class { display: block; } }

We occasionally use media queries that go in the other direction (the given screen size or smaller). Once again, these media queries are also available via Sass mixins:

SCSS

@include grid-breakpoint-down(xs) { ... } @include grid-breakpoint-down(sm) { ... } @include grid-breakpoint-down(md) { ... } @include grid-breakpoint-down(lg) { ... }

There are also media queries and mixins for targeting a single segment of screen sizes using the minimum and maximum breakpoint widths. These media queries are also available via Sass mixins:

SCSS

@include grid-breakpoint-only(xs) { ... } @include grid-breakpoint-only(sm) { ... } @include grid-breakpoint-only(md) { ... } @include grid-breakpoint-only(lg) { ... }

Similarly, media queries may span multiple breakpoint tiers (inclusively). Think of "between" as: from the start of TIER-1 and going to the end of TIER-2.

SCSS

// e.g. from start of XS, including to end of SM, excluding MD and LG @include grid-breakpoint-between(xs, sm) { ... } @include grid-breakpoint-between(xs, md) { ... } @include grid-breakpoint-between(xs, lg) { ... } @include grid-breakpoint-between(sm, md) { ... } @include grid-breakpoint-between(sm, lg) { ... } @include grid-breakpoint-between(md, lg) { ... }

Custom column mixins

Since this grid's columns are fixed-width, there may be situations where you want to have percentage-width columns.

In order to do that, you need to use the following l-col-ready, and a SASS mixin or manually apply custom CSS to the column.

SCSS

// constant percentage columns across all grid tiers .col-half { @include grid-make-col-ready(); @include grid-make-col-percent(1, 2); // 50% } .col-third { @include grid-make-col-ready(); @include grid-make-col-percent(1, 3); // 33% } .col-fourth { @include grid-make-col-ready(); @include grid-make-col-percent(1, 4); // 25% } // usage with `grid-make-col-ready()` mixin, and without `make-col-ready` class .content-1 { @include grid-make-col-ready(); @include grid-breakpoint-down(sm) { @include grid-make-col-percent(5, 8); // 62% } @include grid-breakpoint-up(md) { @include grid-make-col-percent(10, 12); // 83% } } .content-2 { @include grid-make-col-ready(); @include grid-breakpoint-down(sm) { @include grid-make-col-percentage(3, $grid-columns, sm); // 37% } @include grid-breakpoint-up(md) { @include grid-make-col-percentage(2, $grid-columns, md); // 16% } } // usage without `grid-make-col-ready()` mixin, and with `make-col-ready` class .content-3 { @include grid-breakpoint-down(sm) { @include grid-make-col-percent(5, 8); // 62% } @include grid-breakpoint-up(md) { @include grid-make-col-percent(10, 12); // 83% } } .content-4 { @include grid-breakpoint-down(sm) { @include grid-make-col-percentage(3, $grid-columns, sm); // 37% } @include grid-breakpoint-up(md) { @include grid-make-col-percentage(2, $grid-columns, md); // 16% } }

HTML

<div class="l-container"> <div class="l-row"> <div class="col-half">...</div> <div class="col-half">...</div> </div> <div class="l-row"> <div class="col-third">...</div> <div class="col-third">...</div> <div class="col-third">...</div> </div> <div class="l-row"> <div class="col-fourth">...</div> <div class="col-fourth">...</div> <div class="col-fourth">...</div> <div class="col-fourth">...</div> </div> </div> <div class="l-container"> <div class="l-row"> <div class="content-1">...</div> <div class="content-2">...</div> </div> </div> <div class="l-container"> <div class="l-row"> <div class="l-col-ready content-3">...</div> <div class="l-col-ready content-4">...</div> </div> </div>

▲ TOP