Skip to content

Commit 6a6a84f

Browse files
mstenshosvgeesus
authored andcommitted
Column-wrap explainer.
1 parent 857af91 commit 6a6a84f

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# Column wrapping
2+
3+
Implementing the CSS properties `column-height` and `column-wrap` from https://drafts.csswg.org/css-multicol-2/
4+
5+
In multi-column (multicol) layout, content is fragmented into columns. When one column is full, another is created next to it, in the inline direction. If the block-size of the multicol container is unconstrained, and there are no forced breaks inside the columns, there will not be more columns than specified via the `column-width` and/or `column-count` CSS properties. If the multicol container block-size is constrained, and the multicol container isn't nested inside another fragmentation context, any additional columns needed will simply be created in the inline direction, overflowing the multicol container. If block-size is constrained by an outer fragmentation context, when paginating for printing, for instance, columns will take up all the available block-size on the page, and create at most as many columns as specified (still via `column-count` and `column-width`). If that's not enough to fit all the content, a page break will be inserted, and multicol layout will resume on the next page. This is essentially a form of implicit column wrapping.
6+
7+
The new `column-wrap` property is intended to enable column wrapping in other scenarios than for nested multicol described above. If the value of `column-wrap` is `wrap`, and all the specified columns have been filled in the inline direction, instead of overflowing in the inline direction, a new row for columns will be created, so that more content can be added *below* the previous row of columns. The block-size of the rows can be set via the new `column-height` property. If it is `auto`, the block-size of the content box will be used instead. Treating `auto` like this is useful for scrollable overflow, so that there's room for one row of columns in the scrollport.
8+
9+
Column layout, or paginated / fragmented content in general, with lots of content (like articles and bigger), where the order of the content matters, has been working well for paged media (where it wraps into reasonably sized chunks, aka pages), whereas for interactive media on screen it is not that convenient. When the user has read and scrolled to the end of one column, the user then has to scroll all the way back up to the beginning of the next column to continue reading, which is tedious (much more so than e.g. turning a page).
10+
11+
Like this:
12+
13+
https://github.com/user-attachments/assets/4b6c2b2b-8858-4543-8082-c5be82f4861a
14+
15+
Adding column wrapping should allow for large-content use cases on screen as well. On that note, Wikipedia uses multicol for the references at the end of articles, and the columns become really tall if there are many references, but that's not much of a problem, since the reading order here isn't crucial.
16+
17+
Another use case is paginated vertical carousels.
18+
19+
## Example 1: simple vertical pagination
20+
21+
Here's one example that sets `column-wrap` but no `column-height`. The height of the columns will be the same as that of the content box of the multicol container.
22+
23+
```html
24+
<!DOCTYPE html>
25+
<style>
26+
#mc {
27+
overflow: auto;
28+
scroll-snap-type: both mandatory;
29+
padding: 20px;
30+
width: 450px;
31+
height: 600px;
32+
columns: 1;
33+
column-fill: auto;
34+
column-wrap: wrap;
35+
row-gap: 30px;
36+
}
37+
#mc::column {
38+
scroll-snap-align: start;
39+
}
40+
#container {
41+
padding: 10px;
42+
border: 1px solid;
43+
box-decoration-break: clone;
44+
box-shadow:10px 10px 10px gray;
45+
}
46+
</style>
47+
<div id="mc">
48+
<div id="container">
49+
<h2><a id="chap01"></a>CHAPTER I.<br>
50+
Down the Rabbit-Hole</h2>
51+
<p>
52+
Alice was beginning to get very tired of sitting by her sister on the bank, and
53+
of having nothing to do: once or twice she had peeped into the book her sister
54+
was reading, but it had no pictures or conversations in it, “and what is
55+
[...]
56+
```
57+
58+
https://github.com/user-attachments/assets/37855721-3b05-493b-8ea5-a99a8e66ad98
59+
60+
## Example 2: 2D columns
61+
62+
Here's an example that sets both column width and height. It will create as many columns as there is room for along the inline axis, with a column height close to that of the viewport, and wrap into multiple rows as needed.
63+
64+
```html
65+
<!DOCTYPE html>
66+
<style>
67+
#mc {
68+
column-width: 20em;
69+
column-height: 80vh;
70+
column-fill: auto;
71+
column-wrap: wrap;
72+
row-gap: 40px;
73+
padding: 10px;
74+
background: #eee;
75+
}
76+
.chapter {
77+
break-before: column;
78+
}
79+
#container {
80+
display: flow-root;
81+
padding: 0 10px;
82+
text-align: justify;
83+
background: white;
84+
}
85+
</style>
86+
<div id="mc">
87+
<div id="container">
88+
<div class="chapter">
89+
<h2><a id="chap01"></a>CHAPTER I.<br>
90+
Down the Rabbit-Hole</h2>
91+
<p>
92+
Alice was beginning to get very tired of sitting by her sister on the bank, and
93+
of having nothing to do: once or twice she had peeped into the book her sister
94+
was reading, but it had no pictures or conversations in it, “and what is
95+
[...]
96+
```
97+
98+
https://github.com/user-attachments/assets/c66bf44c-4487-4cb1-b8c0-69a77292693c
99+
100+
## Example 3: vertical paginated carousel
101+
102+
And here's an online ice cream shop, with one column per row, but potentially room for more than one item in each column.
103+
104+
```html
105+
<!DOCTYPE html>
106+
<style>
107+
ul#carousel {
108+
margin: 0 0 0 40px;
109+
padding: 0;
110+
overflow: auto;
111+
height: 450px;
112+
anchor-name: --carousel;
113+
columns: 1;
114+
column-wrap: wrap;
115+
scroll-snap-type: block mandatory;
116+
counter-reset: item;
117+
scroll-marker-group: after;
118+
119+
&::scroll-marker-group {
120+
position: absolute;
121+
position-anchor: --carousel;
122+
right: anchor(left);
123+
top: anchor(top);
124+
bottom: anchor(bottom);
125+
display: flex;
126+
flex-flow: column;
127+
justify-content: safe center;
128+
}
129+
&::column {
130+
scroll-snap-align: start;
131+
}
132+
&::column::scroll-marker {
133+
content: "";
134+
flex: none;
135+
border: 5px solid black;
136+
border-radius: 50%;
137+
width: 15px;
138+
height: 15px;
139+
margin: 4px 8px;
140+
background: gray;
141+
}
142+
&::column::scroll-marker:target-current {
143+
background: gold
144+
}
145+
li {
146+
display: inline-flex;
147+
justify-content: center;
148+
align-items: center;
149+
box-sizing: border-box;
150+
width: 300px;
151+
height: 100%;
152+
border: solid;
153+
border-radius: 5px;
154+
}
155+
li::before {
156+
content: "Icecream " counter(item);
157+
counter-increment: item;
158+
}
159+
}
160+
</style>
161+
162+
<ul id="carousel">
163+
<li style="background: #cba;"></li>
164+
<li style="background: #ffe;"></li>
165+
<li style="background: #bdc;"></li>
166+
<li style="background: #dbc;"></li>
167+
<li style="background: #987;"></li>
168+
<li style="background: #789;"></li>
169+
<li style="background: #798;"></li>
170+
<li style="background: #897;"></li>
171+
<li style="background: #879;"></li>
172+
<li style="background: #fed;"></li>
173+
<li style="background: #def;"></li>
174+
<li style="background: #fde;"></li>
175+
<li style="background: #dfe;"></li>
176+
<li style="background: #efd;"></li>
177+
</ul>
178+
```
179+
180+
https://github.com/user-attachments/assets/b96c4ce2-b3e3-4c9f-978d-cb1d96dc3a1c
181+
182+
## What do web developers currently do to achieve such layout?
183+
184+
If the author has full control over the size of the contents, the author may of
185+
course create a page-like experience with vertical scrolling (and
186+
snapping). Alternatively, the author may use some heavy javascriptery to measure
187+
the size of the contents, and place it into "pages" somehow. Currently there is
188+
no way of creating fragmentainers stacked in the block direction.
189+
190+
## Alternatives to column wrapping
191+
192+
An alternative approach would be explicit paginated overflow:
193+
https://drafts.csswg.org/css-overflow-5/#paginated-overflow , which hasn't yet
194+
been specced, but is in many ways a continuation of
195+
https://www.w3.org/TR/2011/WD-css3-gcpm-20111129/#paged-presentations , which
196+
got implemented in Opera's Presto engine one and a half decades ago.
197+
198+
This would easily support [example 1](#example-1-simple-vertical-pagination) and
199+
[example 3](#example-3-vertical-paginated-carousel). It would also be possible
200+
to get paginated column layout by specifying both paged overflow AND `columns`
201+
(or by speccing something like `pagination-layout: horizontal 2` as mentioned in
202+
[ISSUE 22](https://drafts.csswg.org/css-overflow-5/#issue-e78fc89d)).
203+
204+
One limitation, though is that this approach would depend on overflow, so that
205+
[example 2](#example-2-2d-columns), which has auto `height` and non-auto
206+
`column-height` wouldn't work.
207+
208+
Another thing to figure out for the paginated overflow approach, is the gaps
209+
(and rules / decoration) between the pages. With the `column-wrap` approach we
210+
get it for "free", since there's both [`column-gap` /
211+
`row-gap`](https://drafts.csswg.org/css-align/#column-row-gap) and
212+
[`column-rule` /
213+
`row-rule`](https://drafts.csswg.org/css-gaps-1/#gap-decoration-shorthands)
214+
already.
215+
216+
## Are there any privacy, security and accessibility considerations?
217+
218+
There are no such additional concerns, compared to multicol without this
219+
feature. There is no accessibility functionality specifically for columns. It
220+
just relies on regular scrolling mechanisms and tab focus.

0 commit comments

Comments
 (0)