CSS gaps
The CSS gaps module lets you specify spacing, or "gaps", between items in multi-column, flexbox, and grid layouts. The CSS multi-column layout module originally defined gaps and rules that control the spacing between columns in multi-column containers. This module expands on these visible separators, called gap decorations, extending it to grid and flexbox.
While margin and padding specify visual spacing around individual boxes, the properties in this module enable specifying the spacing between adjacent boxes within a given layout context for layouts that have gutters and gaps, when the spacing is different between sibling boxes as opposed to between the first box, last box, and the container's edge. You can show rules in every gap or in a subset of gaps, defining fully animatable rule widths, colors, and insets.
Gaps in action
In this example, the 2021 poem from the USA inauguration, The Hill We Climb, by Amanda Gorman, is displayed across multiple columns, similar to the way articles are displayed in printed newspapers. If you have JavaScript enabled, controls enable changing the column-gap, column-rule-color, column-rule-style and column-rule-width properties, as well as the preferred number of columns and whether the title and a quote should span all of the columns.
<article>
<div class="title">
<h1>The Hill We Climb</h1>
<p>&mdash;Amanda Gorman, 2021</p>
</div>
<p>
When day comes, we ask ourselves where can we find light in this never
ending shade? The loss we carry, a sea we must wade. We braved the belly of
the beast.
</p>
<p>
We've learned that quiet isn't always peace and the norms and notions of
what just is, isn't always justice. And yet the dawn is hours before we knew
it, somehow we do it, somehow we've weathered and witnessed a nation that
isn't broken but simply unfinished.
</p>
<p>
We, the successors of a country and a time, where a skinny black girl
descended from slaves and raised by a single mother can dream of becoming
president, only to find herself reciting for one.
</p>
<p>
And yes, we are far from polished, far from pristine, but that doesn't mean
we are striving to form a union that is perfect. We are striving to forge
our union with purpose, to compose a country committed to all cultures,
colors, characters, and conditions of man. And so we lift our gazes not to
what stands between us but what stands before us. We close the divide
because we know to put our future first. We must first put our differences
aside.
</p>
<p>
We lay down our arms so we can reach out our arms to one another We seek
harm to none and harmony for all. Let the globe, if nothing else, say this
is true, that even as we grieved, we grew. That even as we hurt, we hoped.
</p>
<p>
That even as we tired, we tried. That we'll forever be tied together,
victorious, not because we will never again know defeat, but because we will
never again sow division.
</p>
<p>
Scripture tells us to envision that everyone shall sit under their own vine
and fig tree, and no one shall make them afraid.
</p>
<p>
If we’re to live up to our own time, then victory won't lighten the blade
but in all the bridges we've made, that is the promise to glade, the hill we
climb if only we dare, it's because being American is more than a pride we
inherit. It's the past we stepped into and how we repair it.
</p>
<blockquote>
<p>
We've seen a force that would shatter our nation rather than share it,
would destroy our country if it meant delaying democracy.
</p>
</blockquote>
<p>
And this effort very nearly succeeded. But while democracy can be
periodically delayed, it can never be permanently defeated. In this truth,
in this faith, we trust. For while we have our eyes on the future, history
has its eyes on us.
</p>
<p>
This is the era of just redemption. We feared -- at its deception. We did
not feel prepared to be the heirs of such a terrifying hour, but within it
we found the power to author a new chapter, to offer hope and laughter to
ourselves.
</p>
<p>
So, while once we asked, "how could we possibly prevail over catastrophe?",
now we assert, "how could catastrophe possibly prevail over us?" We will not
march back to what was, but move to what shall be, a country that is bruised
but whole, benevolent but bold, fierce and free. We will not be turned
around or interrupted by intimidation.
</p>
<p>
Because we know our inaction and inertia will be the inheritance of the next
generation. Our blunders become their burdens. But one thing is certain. If
we merge mercy with might and might with right, then love becomes our legacy
and change, our children's birth right.
</p>
<p>
So let us leave behind a country better than one we were left with, every
breath from my bronze pounded chest, we will raise this wounded world into a
wondrous one. We will rise through the gold-limbed hills in the west, we
will rise from the windswept northeast where our forefathers first realized
revolution. We will rise from the lake-rimmed cities of the Midwestern
states.
</p>
<p>
We will rise from the sun-baked South. We will rebuild, reconcile, and
recover, in every known nook of our nation, in every corner called our
country, our people diverse and beautiful, will emerge battered and
beautiful.
</p>
<p>When day comes, we step out of the shade, aflame and unafraid.</p>
<p>
The new dawn blooms as we free it for there is always light if only we're
brave enough to see it, if only we're brave enough to be it.
</p>
</article>
<fieldset id="options" class="open">
<legend>
<button aria-expanded="true" aria-controls="controls">
Column options
</button>
</legend>
<div id="controls">
<p>
<label for="colCount">Number of columns:</label>
<input type="number" min="0" max="5" value="5" id="colCount" />
</p>
<p>
<input type="checkbox" checked id="colSpan" />
<label for="colSpan">Byline spans all columns</label>
</p>
<p>
<input type="checkbox" id="blockSpan" />
<label for="blockSpan">Blockquote spans all columns</label>
</p>
<p class="code">
<input type="range" min="0" max="10" value="1" step="0.5" id="gapSize" />
<label for="gapSize">column-gap: </label><output id="gap">1em;</output>
</p>
<p class="code">
<input
type="range"
min="0"
max="10"
value="0.25"
step="0.25"
id="columnRuleWidth" />
<label for="columnRuleWidth">column-rule-width: </label
><output id="ruleWidth">0.25em;</output>
</p>
<p class="code">
<label for="colColor">column-rule-color:</label>
<input type="color" id="colColor" />
</p>
<p class="code">
<label for="columnRuleStyle">column-rule-style:</label>
<select id="columnRuleStyle">
<option>none</option>
<option>hidden</option>
<option>dotted</option>
<option selected>dashed</option>
<option>solid</option>
<option>double</option>
<option>groove</option>
<option>ridge</option>
<option>inset</option>
<option>outset</option>
<option></option>
</select>
</p>
</div>
</fieldset>
const page = document.querySelector("article");
const title = document.querySelector(".title");
const option = document.querySelector("#options");
const legend = document.querySelector("#options > legend");
const legendBtn = document.querySelector("#options > legend > button");
const blockquote = document.getElementsByTagName("blockquote")[0];
const colCount = document.getElementById("colCount");
const colSpan = document.getElementById("colSpan");
const blockSpan = document.getElementById("blockSpan");
const gapSize = document.getElementById("gapSize");
const gap = document.getElementById("gap");
const columnRuleWidth = document.getElementById("columnRuleWidth");
const ruleWidth = document.getElementById("ruleWidth");
const columnRuleStyle = document.getElementById("columnRuleStyle");
const ruleStyle = document.getElementById("ruleStyle");
const columnRuleColor = document.getElementById("colColor");
// Make options visible if JavaScript is enabled
option.style.display = "revert";
legendBtn.addEventListener("click", () => {
showAndHideMenu();
});
colCount.addEventListener("change", () => {
page.style.columnCount = colCount.value;
});
gapSize.addEventListener("change", () => {
page.style.gap = `${gapSize.value}em`;
gap.innerText = `${gapSize.value}em;`;
});
columnRuleWidth.addEventListener("change", () => {
page.style.columnRuleWidth = `${columnRuleWidth.value}em`;
ruleWidth.innerText = `${columnRuleWidth.value}em;`;
});
columnRuleStyle.addEventListener("change", () => {
page.style.columnRuleStyle = columnRuleStyle.value;
});
colSpan.addEventListener("change", () => {
setColSpan(colSpan, title);
});
blockSpan.addEventListener("change", () => {
setColSpan(blockSpan, blockquote);
});
columnRuleColor.addEventListener("change", () => {
page.style.columnRuleColor = colColor.value;
});
function showAndHideMenu() {
if (legendBtn.getAttribute("aria-expanded") === "true") {
// close it
legendBtn.setAttribute("aria-expanded", "false");
legend.classList.add("closed");
legend.classList.remove("open");
} else {
// open it
legendBtn.setAttribute("aria-expanded", "true");
legend.classList.remove("closed");
legend.classList.add("open");
}
}
function setColSpan(control, element) {
if (control.checked) {
element.style.columnSpan = "all";
} else {
element.style.columnSpan = "none";
}
}
article {
column-count: 5;
gap: 1em;
column-rule: 0.25em dashed currentColor;
}
.title {
column-span: all;
display: flex;
align-items: baseline;
gap: 1em;
flex-wrap: wrap;
}
p {
margin: 0 0 1em 0;
line-height: 1.4;
}
.code {
font-family: monospace;
}
.breakInside * {
break-inside: avoid;
}
#options {
position: fixed;
top: 1rem;
right: 1rem;
background: white;
display: none;
}
fieldset p {
margin-bottom: 0.25em;
}
legend {
position: relative;
top: 0;
transition: 200ms;
}
legend.closed {
top: 0.75em;
}
legend.closed + #controls {
display: none;
}
legend {
background-color: #dedede;
padding: 0.5em;
}
legend > button {
all: unset;
cursor: pointer;
}
legend.closed {
margin: -1em;
display: inline-block;
}
blockquote {
font-weight: bold;
font-style: italic;
margin: 0 0 0.25em 0;
}
blockquote p::before,
blockquote p::after {
content: '"';
vertical-align: baseline;
color: red;
}
When the column rule is larger than the column gap, the decorative line appears behind the text; it doesn't change the size of the gap.
Reference
undefinedProperties
Terms and glossary definitions
Guides
- Styling columns
Guide to styling columns and managing spacing between columns.
- Handling content breaks in multi-column layout
Introduction to the fragmentation specification and how to control where column content breaks.
- Box alignment guides
How box alignment works in the context of flexbox, grid layout, multiple-column layout, and for block, absolutely positioned and table layout.
CSS flexible box layout module
CSS grid layout module
CSS multi-column layout module
CSS box alignment
CSS box sizing module
CSS display module
Specifications
See also