CSSの段組みで、文章を新聞のように並べる方法

​​CSS​HTML,Playwright

文章を入れた要素に column-count: 3 を付けると、中身が3つの段に流れ、新聞の紙面のような段組みになります。段の間の線は column-rule、見出しを段にまたがらせるには column-span: all を使います。画面の幅に合わせて段の数を変えたいときは、段の数ではなく column-width で段の幅の目安を決めると、スマホでは自動で1段に戻ります。

補足

検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Noto Sans CJK JP、文字の大きさは 16px、行の高さは 1.7 で、ページの左右に 16px の余白を取っています。要素や段落の位置と幅は、Playwright でページを開いて測りました。Firefox と Safari での表示、縦書き、印刷したときの段組みは試していません。各ブラウザーの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

新聞のような段組みのコード

見出しと段落を1つの要素に入れ、その要素に段組みの指定を書きます。HTML に段の区切りを書く必要はありません。

html
<article class="paper">
  <h2>文章を新聞のように段に分ける</h2>
  <p>新聞の紙面は、横に長い面を細い段に分けて文章を流します。……</p>
  <p>画面の幅が広いときに一段のまま文章を並べると、……</p>
  <!-- 段落が続く -->
</article>
css
.paper {
  column-count: 3;                /* 3段に分ける */
  column-gap: 2em;                /* 段の間のすき間 */
  column-rule: 1px solid #00c8e8; /* 段の間の線 */
}

.paper h2 {
  column-span: all;               /* 見出しは段にまたがらせる */
}

検証環境で幅 728px の要素に入れると、次のように表示されました。画像では、見出しに下線と余白も付けています。

3段に分かれた文章の画面。いちばん上に「文章を新聞のように段に分ける」という見出しが横幅いっぱいに出ていて、その下に本文が3つの段に分かれて並んでいる。段と段の間には、水色の縦線が引かれている
column-count: 3、column-rule、見出しに column-span: all を付けた表示(幅 728px)

文章は1段目の上から下へ流れ、続きが2段目、3段目に入ります。どこで次の段に移るかは、ブラウザーが段の高さをそろえるように決めます。この段のそろえ方は column-fill の初期値 balance の働きです。

column-count は、画面が狭くても段の数を変えない

column-count は、段の数を決めるプロパティです。6つの段落を入れた要素に column-count: 3 を付け、画面の幅を変えて段の幅を測りました。

画面の幅 段の数 1段の幅
800px 3段 245.33px
600px 3段 178.66px
360px 3段 98.66px

段のすき間(column-gap)を指定しないと、すき間は 1em になります。上の表の1段の幅も、要素の幅から 16px のすき間2つを引いて、3で割った値です。

スマホくらいの幅(360px)でも3段のままで、1段の幅は 98.66px になりました。最初の段落は、1行に5〜6文字しか入らず、11行に折り返されました。

幅360pxの画面で、上下2つの段組みを比べた画像。上の「column-count: 3」は3つの細い段に分かれ、1行に5〜6文字しか入らず、「新聞の紙面」「は、横に長い」のように細かく折り返している。下の「column-width: 14em」は1段のままで、1行に20文字ほど入っている
幅 360px の画面で、column-count: 3(上)と column-width: 14em(下)を比べた表示

column-width にすると、狭い画面では1段に戻る

column-width は、段の数ではなく、段の幅の目安を決めるプロパティです。ブラウザーは、段の幅がこの値を下回らない範囲で、入るだけの段を作ります。要素の幅がこの値より狭いときは、要素の幅いっぱいの1段になります。上の画像で下に並べた段組みは、column-width: 14em(16px の文字で 224px)を付けたものです。

css
.paper {
  column-width: 14em;
}

同じ6つの段落で、画面の幅ごとに測りました。

画面の幅 段の数 1段の幅
800px 3段 245.33px
600px 2段 276px
360px 1段 328px

段の幅は 224px ちょうどにはならず、余った幅を分け合って広くなりました。段組みの仕様にある計算方法では、段の数は「(要素の幅+すき間) ÷ (段の幅の目安+すき間)」の小数を切り捨てた数で、段の幅はそこから割り戻して決まります。幅 600px の画面では要素の幅が 568px なので、(568+16) ÷ (224+16) が約 2.43 になり、2段になります。1段の幅は (568+16) ÷ 2 − 16 で 276px です。

メディアクエリを書かなくても、画面の幅に合わせて段の数が切り替わります。幅 360px の画面で1段になったときは、最初の段落が1行に20文字で3行に収まりました。

段の数の上限も決めるなら columns

広い画面で段が増えすぎないようにしたいときは、一括指定の columns に、段の数と幅の目安を両方書きます。column-width も指定すると、column-count は段の数の上限として働きます。

css
.paper {
  columns: 3 14em;
}

幅 1200px の画面では、column-width: 14em だけだと4段(1段の幅 280px)になりました。columns: 3 14em では3段で止まり、1段の幅は 378.66px になりました。幅 800px では3段、幅 360px では1段で、column-width: 14em だけのときと同じでした。

段の間のすき間と線を決める

段の間を広げるには column-gap を、線を引くには column-rule を使います。column-rule は border と同じように、太さ・線の種類・色を並べて書きます。

css
.paper {
  column-count: 3;
  column-gap: 2em;
  column-rule: 1px solid #00c8e8;
}

幅 800px の画面で、column-gap: 2em にすると、1段の幅は 245.33px から 234.66px に狭まりました。すき間の分だけ、段の幅が減ります。

そこに column-rule を足しても、段の位置と幅は変わりませんでした。線の太さを 40px にして、すき間(32px)より太くしても、段落の位置は 1px の線のときと同じです。仕様でも、線はすき間の真ん中に引かれ、場所を取らないと定められています。すき間より太い線は、隣の段と重なるとされています。線と文字の間を空けたいときは、column-gap を広げます。

見出しを段にまたがらせる

段組みの要素の中に見出しを入れると、見出しも段の中に入ります。指定がないときは、h2 の幅は 245.33px で、1段目の上に収まりました。

幅 800px の画面で、見出しに column-span: all を付けると、見出しの幅が要素の幅いっぱい(768px)になり、本文の3つの段は見出しの下から始まりました。冒頭の画像は、この指定をした表示です。

本文の途中の見出しにも column-span: all を付けると、段組みが見出しの前後で2つに分かれます。

css
.paper h2,
.paper h3 {
  column-span: all;
}

h2 の下に3つの段落、h3、3つの段落の順に入れたところ、h3 の前の3つの段落が1段に1つずつ並び、h3 が横幅いっぱいに出て、そのあとの3つの段落がまた1段に1つずつ並びました。紙面を上下に区切って、別の記事を載せるような形です。見出しの前の文章は、見出しの手前で段の高さをそろえて終わります。

引用や図を段の境目で割らない

段の境目には、段落の途中だけでなく、引用や図の途中も来ます。2段に分けた幅 600px の画面で、背景色を付けた blockquote が1段目の下と2段目の上に分かれました。

この分かれ方を止めるには、分けたくない要素に break-inside: avoid を付けます。

css
.paper blockquote,
.paper figure {
  break-inside: avoid;
}
2段に分けた文章を上下に並べて比べた画像。上の「指定なし」では、水色の背景の引用が1段目の下で途切れ、続きが2段目の上に出ている。下の「blockquote { break-inside: avoid; }」では、引用が1段目の下にまとまって収まり、2段目は次の段落から始まっている
引用に指定なし(上)と break-inside: avoid(下)。どちらも column-count: 2

break-inside: avoid を付けると、引用は1段目にまとまりました。このとき、引用を収めるために段の高さが伸び、要素の高さは 347.06px から 401.44px になりました。2段目には引用の続きがなくなった分、下に空きができます。

見出しだけが段の最後に残るのを防ぐ

要素に高さを決めて段組みにすると、見出しが段の最後に来て、本文だけが次の段から始まることがあります。高さ 300px、2段、column-fill: auto(上の段から順に詰める)の要素で試したところ、h3 が1段目の最後に残り、続きの段落は2段目から始まりました。

見出しに break-after: avoid を付けると、見出しのすぐあとでは段を分けないようになり、h3 は続きの段落といっしょに2段目の先頭に移りました。

css
.paper h3 {
  break-after: avoid;
}

ただし、互換性データでは、段組みの中での break-after: avoid に対応しているのは Chrome と Edge の 102 以降だけで、Firefox と Safari は対応なしとされています。

高さを決めると、入りきらない段が横に増える

段組みの要素に height を付けて高さを決めると、入りきらない文章は下ではなく横に増えた段に流れます。幅 800px の画面で column-count: 3 と height: 160px を付けると、段は6段になり、4段目から先が要素の右にはみ出しました。要素の scrollWidth は 1552px で、ページ全体も横にスクロールできる幅(1568px)に広がりました。仕様でも、高さが決められていて入りきらないときは、段が横の方向に追加されると定められています。

注意

文章が増えると段が横にはみ出すので、段組みの要素に高さを決めるなら overflow-x: auto も付けます。

overflow-x: auto を付けたときは、はみ出した段は要素の中で横にスクロールする形になり、ページ全体の幅は画面と同じ 800px に戻りました。

高さを十分に取った(400px)ときは、column-fill が初期値の balance のままなら、高さを決めないときと同じく3つの段の高さがそろいました。column-fill: auto にすると、1段目を下まで埋めてから2段目に移り、3段目には最後の段落の終わりの2行だけが入りました。

対応しているブラウザー

互換性データでは、break-after: avoid を除き、ここで使ったプロパティは主なブラウザーで接頭辞なしで使えます。

プロパティ Chrome・Edge Firefox Safari(iOS を含む)
columns、column-count、column-rule 50(Edge は 12) 52 9
column-width 50(Edge は 12) 50 9
column-span 50(Edge は 12) 71 9
段組みの中の break-inside 50(Edge は 12) 65 10
段組みの中の break-after: avoid 102 対応なし 対応なし

段の境目の扱いのうち、要素を割らない break-inside: avoid は、Chrome・Edge、Firefox、Safari のどれでも使えます。

​Posted by 86