--- title: Layout --- {% include_relative includes/_header.html %}
This plugin creates classes to handle column layouts:
Where N can be a number of columns, up to the largest amount of
columns defined or a fraction (1/2, 1/3,
1/4, 2/3 or 3/4)
.container or a descendant of
.container
.w-cols-N sets width to
N columns/fraction wide, if inside of
.cols-container also includes an inner gutter
margin-left
v5.0.0
.cols-container makes a container for columns,
flex: row wrap with a negative inner gutter
margin-left
.ml-0 on child, resets margin-left to 0,
adds specificity to the class
.ml-cols-N on child, sets a margin-left of
N columns wide
.mr-cols-N on child, sets a margin-right of
N columns wide
.mx-cols-N on child, sets a margin-right and
margin-left of N columns wide
.ml-cols-N on child, sets a negative
margin-left of N columns wide
.mr-cols-N on child, sets a negative
margin-right of N columns wide
.mx-cols-N on child, sets a negative
margin-right and a negative margin-left of
N columns wide
.ms-cols-N on child, sets a
margin-inline-start of N columns wide
.me-cols-N on child, sets a
margin-inline-end of N columns wide
.ms-cols-N on child, sets a negative
margin-inline-start of N columns wide
.me-cols-N on child, sets a negative
margin-inline-end of N columns wide
.pl-cols-N on child, sets a padding-left of
N columns wide
.pr-cols-N on child, sets a padding-right of
N columns wide
.px-cols-N on child, sets a
padding-right and padding-left of
N columns wide
.ps-cols-N on child, sets a padding-inline-start of
N columns wide
.pe-cols-N on child, sets a padding-inline-end of
N columns wide
.left-cols-N sets left to
N columns
.right-cols-N sets right to
N columns
.inset.x-cols-N sets left and
right to N columns
.left-cols-N sets negative left to
N columns
.right-cols-N sets negative right to
N columns
.-inset.x-cols-N sets negative left and
negative right to N columns
.start-cols-N sets inset-inline-start to
N columns
.end-cols-N sets inset-inline-end to
N columns
.start-cols-N sets negative inset-inline-start to
N columns
.end-cols-N sets negative inset-inline-end to
N columns
.ml-cols-no-gutter-N on child, sets a
margin-leftof N columns wide minus an inner
gutter
.mr-cols-no-gutter-N on child, sets a
margin-right of N columns minus an inner
gutter
.mx-cols-no-gutter-N on child, sets a
margin-right and margin-left of
N columns minus an inner gutter
.ml-cols-no-gutter-N on child, sets a negative
margin-left of N columns wide minus an inner
gutter
.mr-cols-no-gutter-N on child, sets a negative
margin-right of N columns wide minus an
inner gutter
.mx-cols-no-gutter-N on child, sets a negative
margin-right and a negative margin-left of
N columns minus an inner gutter
.ms-cols-no-gutter-N on child, sets a
margin-inline-startof N columns wide minus an inner
gutter
.me-cols-no-gutter-N on child, sets a
margin-inline-end of N columns minus an inner
gutter
.ms-cols-no-gutter-N on child, sets a negative
margin-inline-startt of N columns wide minus an inner
gutter
.me-cols-no-gutter-N on child, sets a negative
margin-inline-end of N columns wide minus an
inner gutter
.pl-cols-no-gutter-N on child, sets a
padding-left of N columns minus an inner
gutter
.pr-cols-no-gutter-N on child, sets a
padding-right of N columns minus an inner
gutter
.px-cols-no-gutter-N on child, sets a
padding-right and padding-left of
N columns minus an inner gutter
.ps-cols-no-gutter-N on child, sets a
padding-inline-start of N columns minus an inner
gutter
.pe-cols-no-gutter-N on child, sets a
padding-inline-end of N columns minus an inner
gutter
.left-cols-no-gutter-N sets left to
N columns minus an inner gutter
.right-cols-no-gutter-N sets right to
N columns minus an inner gutter
.inset.x-cols-no-gutter-N sets left and
right to N columns minus an inner gutter
.left-cols-no-gutter-N sets negative
left to N columns minus an inner gutter
.right-cols-no-gutter-N sets negative
right to N columns minus an inner gutter
.-inset.x-cols-no-gutter-N sets negative
left and right to N columns
minus an inner gutter
.start-cols-no-gutter-N sets inset-inline-start to
N columns minus an inner gutter
.end-cols-no-gutter-N sets inset-inline-end to
N columns minus an inner gutter
.start-cols-no-gutter-N sets negative
inset-inline-start to N columns minus an inner gutter
.end-cols-no-gutter-N sets negative
inset-inline-end to N columns minus an inner gutter
.container, or .breakout or
some other width of container
.*-vw where * is any of the above classes,
eg: .w-cols-vw-4, .mr-cols-vw-2 etc. useful
if your element's container is not
Each of these have tailwind responsive classes and all settings are breakpoint+, read about responsive usage.
Nesting of elements is also possible, read about nesting usage.
v5.0.0The format of the class names has been updated and .cols-container was deprecated in v5.0.0
Before v5.0.0 class names came in the format .w-N-cols - CSS attr, number of columns then -cols/-cols-vw/-cols-no-gutter.
From v5.0.0 onwards, class names will come in an updated format of .w-cols-N - CSS attr, -cols/-cols-vw/-cols-no-gutter and lastly the number of columns. This change was necessary as Tailwind v4.0.0 changes the undocumented rules on how Plugins are generated and our old method was no longer compatible.
v3.0.0 names...
v5.0.0 from v4.x.x/v3.x.x
If you're ok with doing some regex, its possible to transition to
v5.0.0 by:
(\w*)-(\d\/\d|\d*)-cols(-no-gutter|-vw)?$1-cols$3-$2And for any fraction class usage:
(\w*)-(\d\/\d)-cols$1-cols-$2const { Setup, Layout } = require('@area17/a17-tailwind-plugins');
module.exports = {
...
plugins: [Setup, Layout],
theme: {
screens: {
xs: "0",
sm: "544px",
md: "650px",
lg: "990px",
xl: "1300px",
xxl: "1520px"
},
mainColWidths: {
xs: "auto",
sm: "auto",
md: "auto",
lg: "auto",
xl: "auto",
xxl: "1440px"
},
innerGutters: {
xs: "10px",
sm: "15px",
md: "20px",
lg: "30px",
xl: "40px",
xxl: "40px"
},
outerGutters: {
xs: "20px",
sm: "30px",
md: "40px",
lg: "40px",
xl: "40px",
xxl: "0px"
},
columnCount: {
xs: "4",
sm: "4",
md: "8",
lg: "12",
xl: "12",
xxl: "12"
},
}
...
};
Requires Setup plugin with theme.screens,
theme.mainColWidths, theme.innerGutters,
theme.outerGutters and
theme.columnCount configured.
Basic usage of the .w-cols-N classes:
<div class="w-cols-1"></div>
<div class="w-cols-2"></div>
<div class="w-cols-3"></div>
<div class="w-cols-4"></div>
<div class="w-cols-5"></div>
<div class="w-cols-6"></div>
<div class="w-cols-7"></div>
<div class="w-cols-8"></div>
<div class="w-cols-9"></div>
<div class="w-cols-10"></div>
<div class="w-cols-11"></div>
<div class="w-cols-12"></div>
As the plugin reads the config, it works out the maximum amount of columns
it needs - so if your smallest breakpoint has 4 design columns and the
largest has 12 - then it will create classes .w-cols-1 through
.w-cols-12.
Sometimes you want a simpler layout scheme, using %ages of the container width rather than column numbers, but still taking into account the inner gutters. For this you can use fractions.
Fractions can be any of 1/2, 1/3,
1/4, 2/3 or 3/4.
Note Fractions are consistent across all breakpoints. So,
1/2 will be 50% minus some inner gutter on all breakpoints set,
unlike setting via columns whose apparent width will change if the total
number of design columns at a breakpoint changes.
<div class="w-cols-1/4 h-40 bg-column mt-20"></div>
<div class="w-cols-1/3 h-40 bg-column mt-20"></div>
<div class="w-cols-1/2 h-40 bg-column mt-20"></div>
<div class="w-cols-2/3 h-40 bg-column mt-20"></div>
<div class="w-cols-3/4 h-40 bg-column mt-20"></div>
If you use w-cols-10 and your smallest breakpoint only has 4
design columns then you may also want to use max-w-full to stop
a container being wider than 100%. Or better, use w-cols-4 and
lg:w-cols-10.
Which will be 4 design columns wide until the lg breakpoint,
when it will become 10 columns wide:
<div class="w-cols-4 lg:w-cols-10"></div>
And of course, can assign different sizes at all of your breakpoints:
<div class="w-cols-4 sm:w-cols-3 md:w-cols-6 lg:w-cols-10 xl:w-cols-8 xxl:w-cols-6"></div>
As previously mentioned, fractions will be consistent on all breakpoints. They can of course be changed per breakpoint:
<div class="w-cols-3/4 md:w-cols-1/2 lg:w-cols-2/3 xl:w-cols-1/2 h-40 bg-column mt-20"></div>
When using a N number of columns, you can nest elements:
<div class="w-cols-10 xl:w-cols-8 h-120 bg-column mt-20 py-20">
<div class="w-cols-6 h-80 bg-column-alt py-20">
<div class="w-cols-4 h-40 bg-column">8</div>
</div>
</div>
Nesting fractions inside fractions will work, but instead halving the
breakpoint's total columns, you'll the containers total columns. And so, if
you have 12 design columns and you insert w-cols-1/2 inside
w-cols-1/2, you'll get one 6 design column wide element
wrapping a 3 design column wide element:
<div class="w-cols-1/2">
<div class="w-cols-1/2"></div>
</div>
N cols widths
Mixing and matching N cols widths and fractional widths when
nesting may give you unexpected results. A fraction as a child of a
N cols width will work as expected:
<div class="w-cols-8">
<div class="w-cols-1/2"></div>
</div>
But, placing a N cols widths inside a
fractional width column will not work as fractional widths
work cross breakpoint regardless of column count and so don't set/reset the
columns total inside themselves. In this scenario, the N cols
width assumes the fractional width column container has total columns at
that breakpoint. So, if you have 12 design columns and you set a
w-cols-3 inside of w-cols-1/2, you'll end up with
a 1.5 column wide child column:
<div class="w-cols-1/2 h-80">
<div class="w-cols-3 h-40"></div>
</div>
You end up with a 1.5 wide column in that example because 3/12 columns is 1/4 of the total columns, the fractional 1/2 shrinks the 12 columns to fit in a 6 col wide contaner, 1/4 of 6 is 1.5.
GridLayout plugin
As both plugins use the same set of :root variables, they can
be nested inside of each other:
<div class="w-cols-8">
<div class="grid-layout">
<div class="grid-col-span-2"></div>
<div class="grid-col-span-3"></div>
<div class="grid-col-span-1"></div>
</div>
</div>
.cols-container
🚨 Note: deprecated in v5.0.0.
Previously we used .cols-container, which added a left gutter and some auto margins because support for gap with flex layouts was poor. But this isn't the case in 2024 and so we no longer recommend using .cols-container.
If you want to make layout grids, using flex as opposed to CSS Grid, use flex gap-gutter:
<div class="flex gap-gutter">
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
</div>
For legacy usage of .cols-container:
<div class="cols-container">
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
<div class="w-cols-1"></div>
</div>
.cols-container has a negative gutter margin left.
Fractions, responsive and nesting works within
.cols-container.
If you need to zero out the margin left for some reason, you can use
ml-0:
<div class="cols-container">
<div class="w-cols-1"></div>
<div class="w-cols-2 ml-0"></div>
</div>
(ml-0 is essentially Tailwind's ml-0 but with a
child relationship selector to add weight to the selector)
Classes for .ml-, .mr- and .mx-, and
their negative equivalents (.-ml-, .-mr-,
.-mx-) are also generated.
From 3.10.0, ms- and me- classes and
their negative equivalents -ms- and -me- are also
generated (using CSS margin-inline-start and
margin-inline-end).
<div class="flex gap-gutter">
<div class="w-cols-1 ml-cols-2"></div>
</div>
If your content is aligned right, say with justify-end and you
want to push items away from the right, you can use
<div class="flex flex-row justify-end">
<div class="w-cols-1 mr-cols-1 h-40 bg-column"></div>
</div>
You can also push by fractions, which by their design, account for gutters:
<div class="flex flex-row">
<div class="w-cols-1/3 ml-cols-2/3"></div>
</div>
And, within .cols-container:
<div class="cols-container">
<div class="w-cols-1/2"></div>
</div>
<div class="w-cols-1/4"></div>
</div>
New in 3.10.0, margin-inline-start (MDN) and margin-inline-end (MDN) with
<div class="flex flex-row mt-20">
<div class="w-cols-4 ms-cols-2"></div>
</div>
<div class="flex flex-row mt-20">
<div class="w-cols-4 ml-auto me-cols-2"></div>
</div>
Much like margins, padding classes are also generated: .pl-,
.pr- and .px-
From 3.10.0, ps- and pe- classes are
also generated (using CSS padding-inline-start and
padding-inline-end).
<div class="pl-cols-2 pr-cols-4">
<div></div>
</div>
Padding and nesting do not mix very well, as the padded amount isn't accounted for in the width calc. Fractional widths will still align to the grid:
<div class="pl-cols-2">
<div class="w-cols-1/2"></div>
</div>
In our 12 design columm grid, padding the left by 2 columns leaves 10 columns, 1/2 of 10 is 5 and so the child div in the example above is 5 design columns wide.
New in 3.10.0, padding-inline-start (MDN) and padding-inline-end (MDN) with
<div class="ps-cols-2 pe-cols-4">
<div></div>
</div>
You can also .left-cols-N, .left-cols-N-gutter,
.right-cols-N and .right-cols-N-gutter for
position: absolute; type positioning (or maybe with
position: relative; depending on your use case).
From 3.10.0, start- and end- classes
and their negative equivalents -start- and
-end- are also generated (using CSS
inset-inline-start and inset-inline-end).
Fractions and responsive work as expected and nesting will work, if you
apply a
<div class="relative h-96 mt-20">
<div class="w-cols-3 h-40 bg-column absolute top-0 left-cols-1">w-cols-3 left-cols-1</div>
<div class="w-cols-1/3 h-40 bg-column absolute top-56 left-cols-1/3">w-cols-1/3 left-cols-1/3</div>
</div>
Push and pull classes, with or without gutters, will also work:
<div class="relative h-80">
<div class="w-cols-2 h-40 bg-column absolute top-0 left-0 ml-cols-2"></div>
<div class="w-cols-2 h-40 bg-column absolute top-40 right-0 mr-cols-2"></div>
</div>
New in 3.10.0, inset-inline-start (MDN) and inset-inline-end (MDN) with
<div class="relative h-80">
<div class="w-cols-2 absolute top-0 start-cols-2"></div>
<div class="w-cols-2 absolute top-40 end-cols-4"></div>
</div>
Margin, padding and positioning classes also have gutter-less versions. That is, you can position things to the edge of the preceding column rather than the following column:
<div class="flex gap-gutter">
<div class="w-cols-3 ml-cols-no-gutter-2"></div>
</div>
vw calc variants
Regular layout classes w-cols-3 use a CSS
calc() based on 100% container width and a
--grid-columns variable to split the container width as
required.
Sometimes, you might need to set an element on the grid, where you container
is some other width, such as inside .breakout's or perhaps
inside a carousel. In these case the standard w-cols-3 type
classes may not work, and you may need to use vw based
alternatives.
using w-cols-4 ❌ - too wide
using w-cols-vw-4 ✅ - on grid
<div class="breakout">
<div class="w-cols-4 ml-outer-gutter">
<p>using <code>w-cols-4</code> ❌ - too wide</p>
</div>
<div class="w-cols-vw-4 ml-outer-gutter">
<p>using <code>w-cols-vw-4</code> ✅ - on grid</p>
</div>
</div>
w-cols-4 draws the div too wide, as the parent
container is wider than .container. The suffix of
-vw alters the calc to base the calcs off of
100vw.
But, to make this work, we need to account for the scroll bar width.
.breakout
The .*-vw type classes 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
.*-vw type classes, we need to account for the scrollbar width:
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 the .p?-outer-gutter type
Breakout classes (.w-cols-vw-2,
.ml-cols-vw-2 etc.) will work correctly inside of
.breakout type content.