CaptainCSS on GitHub

Layout

An object for creating simple flex layouts, with variable column widths and customisable spacing

Default class reference

Class
Properties
layout--layout-gap: 1rem;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
margin: 0;
padding: 0;
list-style: none;
margin-top: calc(var(--layout-gap) * -1);
margin-left: calc(var(--layout-gap) * -1);
layout__itembox-sizing: border-box;
width: 100%;
margin-top: var(--layout-gap);
padding-left: var(--layout-gap);
order: 5;
layout__item.is-firstorder: 1;
layout__item.is-lastorder: 10;
layout--gap-0--layout-x-gap: 0px;
--layout-y-gap: 0px;
layout--gap-1--layout-x-gap: 0.25rem;
--layout-y-gap: 0.25rem;
layout--gap-2--layout-x-gap: 0.5rem;
--layout-y-gap: 0.5rem;
layout--gap-3--layout-x-gap: 0.75rem;
--layout-y-gap: 0.75rem;
layout--gap-4--layout-x-gap: 1rem;
--layout-y-gap: 1rem;
layout--gap-5--layout-x-gap: 1.25rem;
--layout-y-gap: 1.25rem;
layout--gap-6--layout-x-gap: 1.5rem;
--layout-y-gap: 1.5rem;
layout--gap-7--layout-x-gap: 1.75rem;
--layout-y-gap: 1.75rem;
layout--gap-8--layout-x-gap: 2rem;
--layout-y-gap: 2rem;
layout--gap-9--layout-x-gap: 2.25rem;
--layout-y-gap: 2.25rem;
layout--gap-10--layout-x-gap: 2.5rem;
--layout-y-gap: 2.5rem;
layout--gap-11--layout-x-gap: 2.75rem;
--layout-y-gap: 2.75rem;
layout--gap-12--layout-x-gap: 3rem;
--layout-y-gap: 3rem;
layout--gap-14--layout-x-gap: 3.5rem;
--layout-y-gap: 3.5rem;
layout--gap-16--layout-x-gap: 4rem;
--layout-y-gap: 4rem;
layout--gap-20--layout-x-gap: 5rem;
--layout-y-gap: 5rem;
layout--gap-24--layout-x-gap: 6rem;
--layout-y-gap: 6rem;
layout--gap-28--layout-x-gap: 7rem;
--layout-y-gap: 7rem;
layout--gap-32--layout-x-gap: 8rem;
--layout-y-gap: 8rem;
layout--gap-36--layout-x-gap: 9rem;
--layout-y-gap: 9rem;
layout--gap-40--layout-x-gap: 10rem;
--layout-y-gap: 10rem;
layout--gap-44--layout-x-gap: 11rem;
--layout-y-gap: 11rem;
layout--gap-48--layout-x-gap: 12rem;
--layout-y-gap: 12rem;
layout--gap-52--layout-x-gap: 13rem;
--layout-y-gap: 13rem;
layout--gap-56--layout-x-gap: 14rem;
--layout-y-gap: 14rem;
layout--gap-60--layout-x-gap: 15rem;
--layout-y-gap: 15rem;
layout--gap-64--layout-x-gap: 16rem;
--layout-y-gap: 16rem;
layout--gap-72--layout-x-gap: 18rem;
--layout-y-gap: 18rem;
layout--gap-80--layout-x-gap: 20rem;
--layout-y-gap: 20rem;
layout--gap-96--layout-x-gap: 24rem;
--layout-y-gap: 24rem;
layout--gap-px--layout-x-gap: 1px;
--layout-y-gap: 1px;
layout--gap-0.5--layout-x-gap: 0.125rem;
--layout-y-gap: 0.125rem;
layout--gap-1.5--layout-x-gap: 0.375rem;
--layout-y-gap: 0.375rem;
layout--gap-2.5--layout-x-gap: 0.625rem;
--layout-y-gap: 0.625rem;
layout--gap-3.5--layout-x-gap: 0.875rem;
--layout-y-gap: 0.875rem;
layout--gap-x-0--layout-x-gap: 0px;
layout--gap-x-1--layout-x-gap: 0.25rem;
layout--gap-x-2--layout-x-gap: 0.5rem;
layout--gap-x-3--layout-x-gap: 0.75rem;
layout--gap-x-4--layout-x-gap: 1rem;
layout--gap-x-5--layout-x-gap: 1.25rem;
layout--gap-x-6--layout-x-gap: 1.5rem;
layout--gap-x-7--layout-x-gap: 1.75rem;
layout--gap-x-8--layout-x-gap: 2rem;
layout--gap-x-9--layout-x-gap: 2.25rem;
layout--gap-x-10--layout-x-gap: 2.5rem;
layout--gap-x-11--layout-x-gap: 2.75rem;
layout--gap-x-12--layout-x-gap: 3rem;
layout--gap-x-14--layout-x-gap: 3.5rem;
layout--gap-x-16--layout-x-gap: 4rem;
layout--gap-x-20--layout-x-gap: 5rem;
layout--gap-x-24--layout-x-gap: 6rem;
layout--gap-x-28--layout-x-gap: 7rem;
layout--gap-x-32--layout-x-gap: 8rem;
layout--gap-x-36--layout-x-gap: 9rem;
layout--gap-x-40--layout-x-gap: 10rem;
layout--gap-x-44--layout-x-gap: 11rem;
layout--gap-x-48--layout-x-gap: 12rem;
layout--gap-x-52--layout-x-gap: 13rem;
layout--gap-x-56--layout-x-gap: 14rem;
layout--gap-x-60--layout-x-gap: 15rem;
layout--gap-x-64--layout-x-gap: 16rem;
layout--gap-x-72--layout-x-gap: 18rem;
layout--gap-x-80--layout-x-gap: 20rem;
layout--gap-x-96--layout-x-gap: 24rem;
layout--gap-x-px--layout-x-gap: 1px;
layout--gap-x-0.5--layout-x-gap: 0.125rem;
layout--gap-x-1.5--layout-x-gap: 0.375rem;
layout--gap-x-2.5--layout-x-gap: 0.625rem;
layout--gap-x-3.5--layout-x-gap: 0.875rem;
layout--gap-y-0--layout-y-gap: 0px;
layout--gap-y-1--layout-y-gap: 0.25rem;
layout--gap-y-2--layout-y-gap: 0.5rem;
layout--gap-y-3--layout-y-gap: 0.75rem;
layout--gap-y-4--layout-y-gap: 1rem;
layout--gap-y-5--layout-y-gap: 1.25rem;
layout--gap-y-6--layout-y-gap: 1.5rem;
layout--gap-y-7--layout-y-gap: 1.75rem;
layout--gap-y-8--layout-y-gap: 2rem;
layout--gap-y-9--layout-y-gap: 2.25rem;
layout--gap-y-10--layout-y-gap: 2.5rem;
layout--gap-y-11--layout-y-gap: 2.75rem;
layout--gap-y-12--layout-y-gap: 3rem;
layout--gap-y-14--layout-y-gap: 3.5rem;
layout--gap-y-16--layout-y-gap: 4rem;
layout--gap-y-20--layout-y-gap: 5rem;
layout--gap-y-24--layout-y-gap: 6rem;
layout--gap-y-28--layout-y-gap: 7rem;
layout--gap-y-32--layout-y-gap: 8rem;
layout--gap-y-36--layout-y-gap: 9rem;
layout--gap-y-40--layout-y-gap: 10rem;
layout--gap-y-44--layout-y-gap: 11rem;
layout--gap-y-48--layout-y-gap: 12rem;
layout--gap-y-52--layout-y-gap: 13rem;
layout--gap-y-56--layout-y-gap: 14rem;
layout--gap-y-60--layout-y-gap: 15rem;
layout--gap-y-64--layout-y-gap: 16rem;
layout--gap-y-72--layout-y-gap: 18rem;
layout--gap-y-80--layout-y-gap: 20rem;
layout--gap-y-96--layout-y-gap: 24rem;
layout--gap-y-px--layout-y-gap: 1px;
layout--gap-y-0.5--layout-y-gap: 0.125rem;
layout--gap-y-1.5--layout-y-gap: 0.375rem;
layout--gap-y-2.5--layout-y-gap: 0.625rem;
layout--gap-y-3.5--layout-y-gap: 0.875rem;

.o-layout__item.u-is-first { order: 1; }

.o-layout__item.u-is-last { order: 10; }

Usage

The layout object is used to quickly lay items out in flex columns on the page.

By default, each item in the layout will take up 100% width. This can be customised per item to achieve quick layout compositions.

Each layout item is given left and top spacing, to give it some breathing room from the other items.

The parent layout then applies a negative margin on the left and top, matching the value applied to the items. This off any excess margin and pulls the layout flush against the container edge.

This ensures the layout lays out your content, without adding any extra margin on the outsides. Great!

Items are laid out with spacing between them, all taking 100% width

A full width item
And another
And a final one
<div class="layout">
    <div class="layout__item">A full width item</div>
    <div class="layout__item">And another</div>
    <div class="layout__item">And a final one</div>
</div>

The Layout object in Captain provides a standardised way to define a layout of items, and then use it effortlessly.

For anything more advanced, we'd recommend looking at CSS Grids instead.

The negative margin

Note that the layout applies a negative margin that chops off the extra margin on the top and left items, pulling the layout flush against its container.

The following example shows the margin between the items, and the thick purple line is the container. Any margin outside the container is completely hidden and will not affect any other elements.

1
2
3
4
5
6
<div class="layout">
    <div class="layout__item w-1/3">1</div>
    <div class="layout__item w-1/3">2</div>
    <div class="layout__item w-1/3">3</div>
    <div class="layout__item w-1/3">4</div>
    <div class="layout__item w-1/3">5</div>
    <div class="layout__item w-1/3">6</div>
</div>

Do try to keep just the layout and width classes on these elements

  <div class="layout">
    <div class="layout__item">An item</div>
  </div>

Don't add other classes that interfere with margin or padding as they'll break the layout

-  <div class="layout my-10">
    <div class="layout__item">A layout that's will have too much top margin</div>
  </div>

When support for Flex Gap (`gap`) becomes wider, we can remove this margin clipping functionality. Support for it in Captain is already available. To make use of it early, add `flexGap` to the `captain.support` object in `tailwind.config.js`. At time of writing it's only recently available in Safari, and for a short while in Chrome.

Changing the width

The layout works with the width utilities to allow the items to take up different sizes.

1/2
1/2
Full width
1/4
1/4
1/3
1/6
<div class="layout">
    <div class="layout__item w-1/2">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">1/2</div>
    </div>
    <div class="layout__item w-1/2">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">1/2</div>
    </div>
    <div class="layout__item w-full">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">Full width</div>
    </div>
    <div class="layout__item w-1/4">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">1/4</div>
    </div>
    <div class="layout__item w-1/4">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">1/4</div>
    </div>
    <div class="layout__item w-1/2">
      <div class="rounded-md bg-indigo-500 text-white font-semibold py-2 px-3">1/2</div>
    </div>
</div>

Modifiers

Spacing size

The layout class also includes spacing modifiers out of the box. The default config creates these classes from Tailwind's space config, which in turn defaults to Tailwind's global spacing config.

A layout without a modifier defaults to a spacing of 1rem on both the top and left side.

1/2
1/2
1/2
1/2
1/2
1/2
1/2
1/2
<div class="layout layout--gap-10">
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
</div>

<div class="layout layout--gap-32">
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
</div>

You can also size x and y spacing independently, using classes like layout--gap-x-8 and layout--gap-y-10.

1/2
1/2
1/2
1/2
<div class="layout layout--gap-x-10 layout--gap-y-32">
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
</div>

Responsive

You're also able to adjust the size of the layout when the active breakpoint changes:

1/2
1/2
1/2
1/2
<div class="layout layout--gap-10 md:layout--gap-24 xl:layout--gap-32">
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
    <div class="layout__item w-1/2">1/2</div>
</div>

Customizing

Gap

To change the gaps available to the layout class, specify the name and gap size using the gap option in the theme.layout section of your config file:

// tailwind.config.js
module.exports = {
  theme: {
    layout: (theme) => ({
+     gap: {
+       DEFAULT: '1rem',
+       ...theme('space'),
+     },
    }),
  },
}

If you only have a single layout gap size, you can specify a single size as a shorthand:

// tailwind.config.js
module.exports = {
  theme: {
    layout: {
+     gap: '1rem',
    },
  },
}

Variants

By default, only responsive variants are generated for layout utilities.

You can control which variants are generated for the layout utilities by modifying the layout property in the variants section of your tailwind.config.js file.

For example, this config will disable all variants:

  // tailwind.config.js
  module.exports = {
    variants: {
      // ...
+     layout: [],
    }
  }

Disabling entirely

If you don't plan to use the layout utilities in your project, you can disable them entirely by setting the layout property to false in the captain.plugins section of your config file:

  // tailwind.config.js
  module.exports = {
    captain: {
      plugins: {
        // ...
+       layout: false,
      }
    }
  }