Container

Description

By default all components render across the full width of the viewport. You can use the .container class to create a contained layout. The container class uses the values set in outerGutters and mainColWidths in your tailwind.config.js to create a responsive container.

Note that the default Tailwind container plugin will need to be disabled.

Also includes a .breakout class to allow full 100vw elements inside a container.

From v3.6.0 we have a .container-reset, .breakout-reset and there are changes to .breakout to make it more useful.

  • .container makes a container that conforms to your theme.mainColWidths taking into account your theme.outerGutters
  • .breakout breaks out of a .container, to make your element 100vw wide
  • .container-reset resets a .container (from v3.6.0)
  • .breakout-reset resets a .breakout (from v3.6.0)

Setup

tailwind.config.js
const { Setup, Container } = require('@area17/a17-tailwind-plugins');

module.exports = {
  ...
  plugins: [Setup, Container],
  corePlugins: {
    container: false
  },
  theme: {
    mainColWidths: {
      xs: "auto",
      sm: "auto",
      md: "auto",
      lg: "auto",
      xl: "auto",
      xxl: "1440px"
    },
    outerGutters: {
      xs: "20px",
      sm: "30px",
      md: "40px",
      lg: "40px",
      xl: "40px",
      xxl: "0px"
    },
  }
  ...
};

Requires Setup plugin with theme.mainColWidths and theme.outerGutters configured.

Note: if your mainColWidth is set to a fixed number, as it is in the xxl breakpoint above, then your corresponding outerGutter needs to be 0px.

When you have a fixed container, the outer gutter is essentially window.width - mainColWidth - setting outerGutter to be anything but 0px breaks the internal CSS calc() maths.

Demo

Container

This site has its content wrapped in <div class="container">. You'll see it is fluid with outer margins set to the frontend.config.json structure.gutters.outer for each breakpoint. At then, when the window is wider than 1520px wide (structure.breakpoints.xxl) the main column is a fixed width of 1440px (structure.breakpoints.container.xxl) and centered within the window.

Container nesting

Introduced in v3.6.0.

.container > .container > .container

document.html
<div class="container">
  <div class="container">
    ...
  </div>
</div>

(which lives inside of the main page .container)

Nesting of .container inside of .breakout, .breakout-reset and .container-reset should all work as expected.

Container Reset

Introduced in v3.6.0.

Instead of wrapping all your pages in .container, perhaps you wrap each of your components, and then perhaps at some breakpoint you want go full bleed. In which case .container-reset will be useful. Here, at the lg breakpoint, a .container resets to full bleed:

...

document.html
<div class="container lg:container-reset">...</div>

Breakout

Useful for 100vw images or video:

...

document.html
<div class="container">
  ...
  <div class="breakout">
    ...
  </div>
</div>

Note: This is not the same as .container-reset, because .breakout breaks out of a .container and doesn't reset it. .breakout essentially gives you a full bleed 100vw element from inside a .container.

Breakout Reset

Introduced in v3.6.0.

Breaking out until a breakpoint, in this case lg, at which point the div is contained once again inside of the parent <div class="container">:

...

document.html
<div class="breakout lg:breakout-reset">...</div>

Container width elements inside of breakouts

Introduced in v3.6.0.

You might want to use a breakout as a full bleed colour block, where some items are full bleed and some items within are constrained by the main container. There are a few ways to do this.

Nest a .container in .breakout:

...

document.html
<div class="breakout">
  <div class="container">
    ...
  </div>
</div>

Nesting of .container inside of .breakout, .breakout-reset and .container-reset should all work as expected.

Add outer gutter padding to .breakout:

Note: requires --scrollbar-visible-width - see Additional set up for working with gutters inside .breakout

...

document.html
<div class="breakout px-outer-gutter">
  ...
</div>

(.pr-outer-gutter and .pl-outer-gutter are also included)

Add outer gutter padding to a child of .breakout:

Note: requires --scrollbar-visible-width - see Additional set up for working with gutters inside .breakout

...

document.html
<div class="breakout">
  <div class="bg-header py-20 px-outer-gutter">
    ...
  </div>
</div>

(.pr-outer-gutter and .pl-outer-gutter are also included)

Use outer gutter width shims on either side of the content of .breakout:

Note: requires --scrollbar-visible-width - see Additional set up for working with gutters inside .breakout

...

document.html
<div class="breakout flex flex-row flex-nowrap">
  <div class="flex-none w-outer-gutter"></div>
  <div class="flex-grow">
    <p>...</p>
  </div>
  <div class="flex-none w-outer-gutter"></div>
</div>

Additional set up for working with gutters inside .breakout

The .breakout class uses 100vw as its base, which, frustratingly is likely wider than the document as the document can take up 100vw minus the scroll bar width. So, to use p?-outer-gutter type classes on, or within .breakout elements, we need to account for the scrollbar width:

application.js
const scrollbox = document.createElement('div');
scrollbox.style.overflow = 'scroll';
document.body.appendChild(scrollbox);

// Compare inner and out widths of the box to determine scroll bar width
const scrollBarWidth = scrollbox.offsetWidth - scrollbox.clientWidth;

document.body.removeChild(scrollbox);
document.documentElement.style.setProperty('--scrollbar-width', `${ scrollBarWidth }px`);

// test is scroll bar is visible
function setScrollBarVisible() {
  const scrollBarVisible = document.documentElement.scrollHeight > document.documentElement.clientHeight;
  const overflowYSet = window.getComputedStyle(document.documentElement, null).getPropertyValue('overflow-y') === 'scroll';
  document.documentElement.style.setProperty('--scrollbar-visible-width', `${ scrollBarVisible || overflowYSet ? scrollBarWidth : 0 }px`);
}

window.addEventListener('load', setScrollBarVisible, false);
window.addEventListener('resized', setScrollBarVisible, false);
setScrollBarVisible();

This also makes sure than any .*-vw type Layout classes (.w-2-cols-vw, .ml-2-cols-vw etc.) will work correctly inside of none .container width content.