When setting content to display in multiple columns via CSS multi-column layout (using the column-count or column-width property), one issue is that it can be hard to constrain the column height for readability when it exceeds the size of the viewport:
- If you set a fixed height on the content container, excess columns will overflow to the side, and readers will have to scroll in the inline direction to read all the content.
- If you don't set a fixed height on the content container, the columns of content will be very long and require readers to scroll down to the end of a column and then back up to the top of the next column.
The column-height property, along with column-wrap, solves this problem by allowing you to set a specific height for your columns and having them wrap onto a new row of columns when the container edge is reached.
The default value of column-wrap is auto, which resolves to wrap when column-height is set to a <length> value; wrap allows the fixed-height columns to wrap onto multiple rows. When column-height is equal to auto, column-wrap: auto resolves to nowrap, allowing the columns to overflow horizontally if a fixed container height is set.
As a result of this default behavior, generally you don't need to explicitly set column-wrap to get the effect you want.
There is an exception. When column-wrap is explicitly set to nowrap, a column-height <length> value has no effect. This can be used to create layouts that switch between horizontal and vertical (see wrap versus nowrap behavior).
This example shows how to create a multi-column layout with multiple rows of columns, which allows you to toggle the layout between horizontally and vertically scrolling by changing the column container's column-wrap value.
HTML
The markup for this example contains multiple paragraphs of content, taken from MDN landing pages, and a <input type="checkbox"> element to enable you to toggle the column container's column-wrap value between nowrap and wrap. We won't show the HTML source here for brevity.
<form>
<label for="set-wrap"
>Set <code>column-wrap</code> to <code>wrap</code></label
>
<input type="checkbox" id="set-wrap" />
</form>
<h1>HTML, CSS, and JavaScript summaries</h1>
<p>
<strong>HTML</strong> (HyperText Markup Language) is the most basic building
block of the Web. It defines the meaning and structure of web content. Other
technologies besides HTML are generally used to describe a web page's
appearance (CSS) or behavior (JavaScript).
</p>
<p>
"Hypertext" refers to links that connect web pages to one another, either
within a single website or between websites. Links are a fundamental aspect of
the Web. By uploading content to the Internet and linking it to pages created
by other people, you become an active participant in the World Wide Web.
</p>
<p>
HTML uses "markup" to annotate text, images, and other content for display in
a Web browser. HTML markup includes special "elements" such as
<a href="/en-US/docs/Web/HTML/Reference/Elements/head"
><code><head></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/title"
><code><title></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/body"
><code><body></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/header"
><code><header></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/footer"
><code><footer></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/article"
><code><article></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/section"
><code><section></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/p"><code><p></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/div"
><code><div></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/span"
><code><span></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/img"
><code><img></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/aside"
><code><aside></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/audio"
><code><audio></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/canvas"
><code><canvas></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/datalist"
><code><datalist></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/details"
><code><details></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/embed"
><code><embed></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/nav"
><code><nav></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/search"
><code><search></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/output"
><code><output></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/progress"
><code><progress></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/video"
><code><video></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/ul"
><code><ul></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/ol"
><code><ol></code></a
>,
<a href="/en-US/docs/Web/HTML/Reference/Elements/li"
><code><li></code></a
>
and many others.
</p>
<p>
An HTML element is set off from other text in a document by "tags", which
consist of the element name surrounded by <code><</code> and
<code>></code>. The name of an element inside a tag is case-insensitive.
That is, it can be written in uppercase, lowercase, or a mixture. For example,
the <code><title></code> tag can be written as
<code><Title></code>, <code><TITLE></code>, or in any other way.
However, the convention and recommended practice is to write tags in
lowercase.
</p>
<hr />
<p>
<strong>Cascading Style Sheets</strong> (<strong>CSS</strong>) is a
<a href="/en-US/docs/Web/API/StyleSheet">stylesheet</a> language used to
describe the presentation of a document written in
<a href="/en-US/docs/Web/HTML">HTML</a> or
<a href="/en-US/docs/Web/XML/Guides/XML_introduction">XML</a> (including XML
dialects such as <a href="/en-US/docs/Web/SVG">SVG</a>,
<a href="/en-US/docs/Web/MathML">MathML</a> or
<a href="/en-US/docs/Glossary/XHTML">XHTML</a>). CSS describes how elements
should be rendered on screen, on paper, in speech, or on other media.
</p>
<p>
CSS is among the core languages of the <strong>open web</strong> and is
standardized across web browsers according to
<a href="https://www.w3.org/Style/CSS/#specs" class="external" target="_blank"
>W3C specifications</a
>. Previously, the development of various parts of CSS specification was done
synchronously, which allowed the versioning of the latest recommendations. You
might have heard about CSS1, CSS2.1, or even CSS3. There will never be a CSS3
or a CSS4; rather, everything is now just "CSS" with individual CSS modules
having version numbers.
</p>
<p>
After CSS 2.1, the scope of the specification increased significantly and the
progress on different CSS modules started to differ so much, that it became
more effective to
<a
href="https://www.w3.org/Style/CSS/current-work"
class="external"
target="_blank"
>develop and release recommendations separately per module</a
>. Instead of versioning the CSS specification, W3C now periodically takes a
snapshot of
<a href="https://www.w3.org/TR/css/" class="external" target="_blank"
>the latest stable state of the CSS specification</a
>
and individual modules progress. CSS modules now have version numbers, or
levels, such as
<a
href="https://drafts.csswg.org/css-color-5/"
class="external"
target="_blank"
>CSS Color Module Level 5</a
>.
</p>
<hr />
<p>
<strong>JavaScript</strong> (<strong>JS</strong>) is a lightweight interpreted
(or
<a href="/en-US/docs/Glossary/Just_In_Time_Compilation"
>just-in-time compiled</a
>) programming language with
<a href="/en-US/docs/Glossary/First-class_Function">first-class functions</a>.
While it is most well-known as the scripting language for Web pages,
<a
href="https://en.wikipedia.org/wiki/JavaScript#Other_usage"
class="external"
target="_blank"
>many non-browser environments</a
>
also use it, such as <a href="/en-US/docs/Glossary/Node.js">Node.js</a>,
<a href="https://couchdb.apache.org/" class="external" target="_blank"
>Apache CouchDB</a
>
and
<a
href="https://opensource.adobe.com/dc-acrobat-sdk-docs/acrobatsdk/"
class="external"
target="_blank"
>Adobe Acrobat</a
>. JavaScript is a
<a href="/en-US/docs/Glossary/Prototype-based_programming">prototype-based</a
>, <a href="/en-US/docs/Glossary/Garbage_collection">garbage-collected</a>,
<a href="/en-US/docs/Glossary/Dynamic_typing">dynamic</a> language, supporting
multiple paradigms such as imperative, functional, and object-oriented.
</p>
<p>
JavaScript's dynamic capabilities include runtime object construction,
variable parameter lists, function variables, dynamic script creation (via
<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"
><code>eval</code></a
>), object introspection (via
<a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...in"
><code>for...in</code></a
>
and
<a
href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#static_methods"
><code>Object</code> utilities</a
>), and source-code recovery (JavaScript functions store their source text and
can be retrieved through
<a
href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString"
><code>toString()</code></a
>).
</p>
<p>
This section is dedicated to the JavaScript language itself, and not the parts
that are specific to Web pages or other host environments. For information
about <a href="/en-US/docs/Glossary/API">APIs</a> that are specific to Web
pages, please see <a href="/en-US/docs/Web/API">Web APIs</a> and
<a href="/en-US/docs/Glossary/DOM">DOM</a>.
</p>
<p>
The standards for JavaScript are the
<a href="https://tc39.es/ecma262/" class="external" target="_blank"
>ECMAScript Language Specification</a
>
(ECMA-262) and the
<a href="https://tc39.es/ecma402/" class="external" target="_blank"
>ECMAScript Internationalization API specification</a
>
(ECMA-402). As soon as one browser implements a feature, we try to document
it. This means that cases where some
<a href="https://github.com/tc39/proposals" class="external" target="_blank"
>proposals for new ECMAScript features</a
>
have already been implemented in browsers, documentation and examples in MDN
articles may use some of those new features. Most of the time, this happens
between the
<a href="https://tc39.es/process-document/" class="external" target="_blank"
>stages</a
>
3 and 4, and is usually before the spec is officially published.
</p>
<p>
Do not confuse JavaScript with the
<a
href="https://en.wikipedia.org/wiki/Java_(programming_language)"
class="external"
target="_blank"
>Java programming language</a
>
— <strong>JavaScript is <em>not</em> "Interpreted Java"</strong>. Both "Java"
and "JavaScript" are trademarks or registered trademarks of Oracle in the U.S.
and other countries. However, the two programming languages have very
different syntax, semantics, and use.
</p>
<p>
JavaScript documentation of core language features (pure
<a
href="/en-US/docs/Web/JavaScript/Reference/JavaScript_technologies_overview"
>ECMAScript</a
>, for the most part) includes the following:
</p>
CSS
We start by giving the <body> element a height of 90vh and a column-count of 3. We then set a gap of 3em 2em, resulting in a 3em gap between rows and a 2em gap between columns.
Finally, we set a column-height of 90vh to make our columns as tall as the <body>. We also set column-wrap to nowrap. We are doing this because the initial column-wrap value is auto, which resolves to wrap when column-height is set to a <length> value. By setting column-wrap explicitly to nowrap, we force excess content columns to overflow horizontally, creating the horizontal layout. In addition, a column-height <length> value has no effect when column-wrap is set to nowrap.
When the user checks the checkbox, the column-wrap property is set to wrap, which causes the excess content columns to overflow into new columns vertically, creating the vertical layout. At this point, the column-height value has an effect — it causes each row of columns to fill the viewport, which works well for the vertical layout.
* {
box-sizing: border-box;
}
html {
font-family: Arial, Helvetica, sans-serif;
}
p {
line-height: 1.5;
}
@supports not (column-wrap: wrap) {
body::before {
content: "Your browser does not support the 'column-wrap' and/or 'column-height' properties.";
color: black;
background-color: #ffcd33;
display: block;
position: fixed;
inset: 50% 20em;
height: fit-content;
text-align: center;
font-weight: bold;
padding: 1rem 0;
}
}
form {
position: fixed;
top: 0;
right: 0;
background-color: white;
padding: 5px;
border: 1px solid black;
}
body {
height: 90vh;
column-count: 3;
gap: 3em 2em;
column-height: 90vh;
column-wrap: nowrap;
}
Next, we set the <h1> element's column-span property to all, to make the heading span across all the columns, and set the margin-top property of the first <p> to 0 so that it lines up with the top of the columns.
h1 {
column-span: all;
}
p:first-of-type {
margin-top: 0;
}
JavaScript
In our JavaScript, we set a change event listener on the checkbox. When its value changes, we set the <body> element's column-wrap value to wrap if it is checked, and nowrap otherwise.
const checkbox = document.getElementById("set-wrap");
checkbox.addEventListener("change", () => {
if (checkbox.checked) {
document.body.style.columnWrap = "wrap";
} else {
document.body.style.columnWrap = "nowrap";
}
});
Result
The rendered result looks like this:
Initially, try scrolling the content horizontally to see the effect of content-wrap: nowrap. Now check the checkbox, and note how the layout switches to vertically scrolling, with each new row of columns filling the viewport.