- CSS
CSS縦書きwriting-modeの使い方|数字・英字の縦中横まで
CSSで文字を縦書きにするには、縦書きにしたい要素に writing-mode: vertical-rl; を指定します。 これだけで、文字が上から下へ、行が右から左へ進む日本語の縦組みになります。半角の数字や英字は横倒しになるので、2桁の数字は text-combine-upright: all;(縦中横)で1文字分の枠に横並びにし、英字を1文字ずつ立てたいときは text-orientation: upright; を使います。
この記事では、writing-mode の5つの値と text-orientation の3つの値を実際に表示して、結果を一覧表にしました。数字・日付・英単語・記号・長音・括弧といった表示パターンごとに「どのプロパティを使うか」を整理し、縦書きにしたときの余白(論理プロパティ)、Flex / Grid の軸の変化、はみ出して横スクロールになる原因、スマホでは横書きに戻す切替まで、コピペ用のコードで示します。表示と数値は Chromium 141(Playwright 1.56.0、フォントは Noto Serif CJK JP) で確認したものです。Firefox と Safari の対応状況は MDN とその元データ(browser-compat-data)の記載によります(手元では未実行)。
縦書きCSSの早見表
| やりたいこと | 書くCSS | 補足 |
|---|---|---|
| 縦書きにする(行は右から左) | writing-mode: vertical-rl; |
日本語の縦組みはこれ |
| 縦書きにする(行は左から右) | writing-mode: vertical-lr; |
モンゴル文字などの組み方向 |
| 文字ごと90度回して縦に置く | writing-mode: sideways-rl; |
表の見出しや帯のラベル向け |
| 下から上へ読むラベル | writing-mode: sideways-lr; |
グラフの縦軸ラベル向け |
| 2桁の数字を横並びで1文字分に | text-combine-upright: all; |
縦中横(たてちゅうよこ) |
| 英字・数字を1文字ずつ立てる | text-orientation: upright; |
略語や4桁の年に |
| 縦書きの中で全部を横倒しに | text-orientation: sideways; |
英文の引用など |
| 縦書きの「行の高さ方向」の長さ | inline-size: 30em; |
縦書きでは height に当たる |
| 段落の間隔 | margin-block-end: 1em; |
縦書きでは左側の余白になる |
| 字下げ | text-indent: 1em; |
縦書きでは上が1字空く |
| スマホでは横書きに戻す | @media (max-width: 600px) で writing-mode: horizontal-tb; |
後半にコピペ用コード |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS縦書きwriting-modeの使い方|数字・英字の縦中横まで」
まず動かす:縦書きの最小コード
次の HTML を1つのファイルに保存してブラウザで開くと、縦書きの段落が表示されます。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>縦書きの最小例</title>
<style>
.tategaki {
writing-mode: vertical-rl; /* 縦書き。行は右から左へ */
inline-size: 20em; /* 1行の長さ(縦書きでは高さ) */
line-height: 1.8;
font-family: "Noto Serif CJK JP", "Hiragino Mincho ProN", "Yu Mincho", serif;
}
.tategaki p {
margin-block: 0 1em; /* 段落の後ろ(左側)に1字分の間隔 */
text-indent: 1em; /* 字下げ(上を1字空ける) */
}
.tcy { text-combine-upright: all; } /* 縦中横 */
</style>
</head>
<body>
<div class="tategaki">
<p>令和8年<span class="tcy">10</span>月<span class="tcy">3</span>日、縦書きの練習をしました。</p>
<p>半角の数字は縦中横で横並びにそろえます。</p>
</div>
</body>
</html>
Chromium 141 で開くと、.tategaki は幅 147px・高さ 320px(20em)の縦書きの枠になり、段落の左側に 16px(1em)の間隔、1文字目の上に 16px の字下げが入りました。指定するのは writing-mode: vertical-rl; の1行です。あとは行の長さ(inline-size)と、数字を整える .tcy を足していけば、読みやすい縦組みになります。
writing-modeの5つの値と表示結果
同じ文字列「日本語とABC、10月。(改行)二行目ー(括弧)」を5つの値で表示し、文字の位置を測りました。高さ 230px の枠に入れています。
| 値 | 文字の進む向き | 行の進む向き | 日本語の文字 | 半角英数字 | 1文字目の位置 | 2行目の位置 |
|---|---|---|---|---|---|---|
horizontal-tb |
左から右 | 上から下 | 正立 | 正立 | 左上 | 1行目の下 |
vertical-rl |
上から下 | 右から左 | 正立 | 時計回りに90度回転 | 右上 | 1行目の左 |
vertical-lr |
上から下 | 左から右 | 正立 | 時計回りに90度回転 | 左上 | 1行目の右 |
sideways-rl |
上から下 | 右から左 | 時計回りに90度回転 | 時計回りに90度回転 | 右上 | 1行目の左 |
sideways-lr |
下から上 | 左から右 | 反時計回りに90度回転 | 反時計回りに90度回転 | 左下 | 1行目の右 |
vertical-* と sideways-* の違いは、日本語の文字が立つか寝るかです。vertical-rl では漢字やかなが正立し、句読点(、。)や長音(ー)、括弧も縦書き用の形に切り替わりました。sideways-rl は横書きの行をそのまま時計回りに90度回した見た目になり、漢字も寝た状態になります。sideways-lr は反時計回りに回るので、下から上へ読む形になります。
使い分けの目安は次のとおりです。
| 場面 | 向いている値 |
|---|---|
| 日本語の本文・見出しを縦組みにする | vertical-rl |
| 表の見出しセルを縦にして幅を節約する(日本語) | vertical-rl |
| 表の見出しセルを縦にする(英語のラベル) | sideways-rl または sideways-lr |
| グラフの縦軸ラベル(下から上へ読ませる) | sideways-lr |
| ページ端の帯ラベル(上から下へ読ませる) | sideways-rl |
2026年時点のブラウザ対応状況
| 値・プロパティ | Chrome / Edge | Firefox | Safari | 状況 |
|---|---|---|---|---|
writing-mode(接頭辞なし) |
48 | 41 | 10.1 | Baseline(2017年3月から広く利用可能) |
vertical-rl / vertical-lr |
48 | 43 | 9 | 主要ブラウザすべてで利用可能 |
sideways-rl / sideways-lr |
132 | 43 | 18.4 | 比較的新しい。少し前の版では効かない |
text-orientation |
― | ― | ― | Baseline(2020年9月から広く利用可能) |
text-combine-upright: all |
― | ― | ― | Baseline(2022年3月から広く利用可能) |
text-combine-upright: digits 数値 |
未対応 | 未対応 | 未対応 | MDN に「どのブラウザも未対応」と記載 |
バージョン番号は MDN の元データ(mdn/browser-compat-data の writing-mode.json)、Baseline の時期は MDN の各プロパティのページの記載です。「―」は今回バージョン番号までは確認していない欄です。手元の Chromium 141 では、CSS.supports() で次の結果を確認しました。
writing-mode: horizontal-tb / vertical-rl / vertical-lr / sideways-rl / sideways-lr → すべて true
text-orientation: mixed / upright / sideways → すべて true
text-combine-upright: all → true
text-combine-upright: digits 2 → false
sideways-rl と sideways-lr は Chrome 132・Safari 18.4 からの対応です。それより前の版も対象にする場合は、vertical-rl と text-orientation: sideways の組み合わせ(上から下へ読む形)で代用できます。IE 向けの -ms-writing-mode: tb-rl は、現在の主要ブラウザを対象にするなら書かなくても動きます。
text-orientationの3つの値と表示結果
text-orientation は、縦書きの中で文字をどの向きに置くかを決めるプロパティです。writing-mode が縦書き(vertical-rl / vertical-lr)のときだけ効きます。
同じ文字列「日本語とABC、10月ー(括)」を vertical-rl の中で表示した結果です。
| 値 | 日本語 | 半角英字 ABC | 半角数字 10 | 長音 ー | 英字1文字の高さ(実測) |
|---|---|---|---|---|---|
mixed(初期値) |
正立 | 横倒し | 横倒し | 縦棒の形 | 約14px(文字幅ぶん) |
upright |
正立 | 1文字ずつ正立 | 1文字ずつ正立 | 縦棒の形 | 20px(1文字ぶん) |
sideways |
横倒し | 横倒し | 横倒し | 横棒のまま回転 | 約14px |
フォントサイズ 20px での実測です。upright では英字も漢字と同じ 20px の枠を1つずつ使うため、英字が多いと行が長くなります。sideways は日本語も含めてすべて寝かせるので、見た目は sideways-rl と同じになりました。
MDN の記載では、upright を指定すると文字の方向(direction)が ltr として扱われます。また sideways-right は sideways の別名として残されています。
.tategaki { writing-mode: vertical-rl; }
.tategaki .up { text-orientation: upright; } /* 英数字を立てる */
.tategaki .side { text-orientation: sideways; } /* 全部を寝かせる */
表示パターン別:縦中横と正立のどちらを使うか
縦書きで手を入れたくなるのは、ほとんどが半角の英数字と記号です。実際に表示して確かめた結果を、パターン別にまとめます。
| パターン | 何もしないとき | おすすめの指定 | 結果 |
|---|---|---|---|
| 1桁の数字(3日) | 横倒し | text-combine-upright: all |
正立して1文字分に収まる |
| 2桁の数字(10月、25日) | 横倒しで2文字ぶん | text-combine-upright: all |
横並びで1文字分に収まる |
| 3桁の数字(100年) | 横倒し | all も使えるが細くなる |
1文字分に圧縮され、やや細い |
| 4桁の数字(2026年) | 横倒し | text-orientation: upright か全角数字 |
1文字ずつ立つ(4文字ぶんの長さ) |
| 英単語(CSS入門) | 横倒し | そのまま、または upright |
略語は upright、長い単語はそのままが読みやすい |
| 半角の感嘆符・疑問符(!?) | 横倒し | text-combine-upright: all か全角 |
2文字が1文字分に並ぶ |
| 半角のパーセント(50%) | 横倒し | 数字を縦中横+全角の% | 数字と記号がそろう |
| 半角の括弧 (a) | 括弧ごと横倒し | 全角の括弧にする | 全角( )は縦書き用の形に変わる |
| 長音(コーヒー) | 縦棒の形に自動で変わる | 指定なしでよい | そのままで正しい形 |
| ダッシュ・波線(―、〜) | 縦向きの形に自動で変わる | 指定なしでよい | そのままで正しい形 |
| 句読点(、。) | 右上寄りの縦書き用の位置 | 指定なしでよい | そのままで正しい形 |
全角文字は縦書き用の形に自動で切り替わり、半角文字は横倒しになる、というのが基本の動きです。手を入れるのは半角の部分だけで済みます。
2桁の数字・日付は縦中横にする
縦中横(たてちゅうよこ)は、縦書きの行の中で、数文字を横に並べて1文字分の枠に収める組み方です。text-combine-upright: all; を、横並びにしたい文字を囲んだ要素に指定します。
<p class="tategaki">
令和8年<span class="tcy">10</span>月<span class="tcy">3</span>日
午前<span class="tcy">9</span>時<span class="tcy">30</span>分
</p>
.tategaki { writing-mode: vertical-rl; }
.tcy { text-combine-upright: all; }
フォントサイズ 20px・行の高さ 1.6 で、縦中横にした要素の大きさを測った結果です(幅×高さ。幅 29px は行の太さ、高さが文字の進む方向の長さ)。
| 中身 | 指定 | 大きさ(実測) | 見え方 |
|---|---|---|---|
| 12 | text-combine-upright: all |
29×20px | 1文字分に横並び |
| 100 | text-combine-upright: all |
29×20px | 1文字分に圧縮(細め) |
| 2026 | text-combine-upright: all |
29×20px | 1文字分に圧縮(かなり細い) |
| 2026 | text-orientation: upright |
29×80px | 4文字ぶんの長さで1字ずつ正立 |
何文字入れても 20px(1文字分)に押し込まれることがわかります。2桁まではきれいに収まり、3桁はやや細く、4桁は読み取りにくい細さになりました。そこで次のように使い分けます。
| 桁数 | 使い分け |
|---|---|
| 1〜2桁 | 縦中横(text-combine-upright: all) |
| 3桁 | 縦中横でも読めるが、フォントによっては upright か漢数字 |
| 4桁以上 | text-orientation: upright、全角数字、または漢数字 |
1桁の数字も .tcy で囲んでおくと、横倒しにならず正立します。日付のように1桁と2桁が混ざる箇所は、すべて同じクラスで囲むと扱いがそろいます。
数字を自動で縦中横にしたいとき
仕様には、連続する数字を自動で縦中横にする text-combine-upright: digits 2; という値が定義されています。ただし MDN には「どのブラウザも未対応」と記載があり、手元の Chromium 141 でも CSS.supports('text-combine-upright', 'digits 2') は false でした。現時点では、数字を span で囲む方法が確実です。
原稿の数字を手で囲むのが大変なときは、JavaScript で1〜2桁の半角数字だけを囲めます。縦書きの要素より後ろ(body の末尾など)に置いてください。
<script>
// .tategaki の中の 1〜2 桁の半角数字を span.tcy で囲む
document.querySelectorAll(".tategaki").forEach((root) => {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode()) nodes.push(walker.currentNode);
nodes.forEach((node) => {
if (node.parentElement.closest(".tcy")) return;
const parts = node.data.split(/(?<![0-9])([0-9]{1,2})(?![0-9])/);
if (parts.length === 1) return;
const frag = document.createDocumentFragment();
parts.forEach((part, i) => {
if (i % 2 === 1) {
const span = document.createElement("span");
span.className = "tcy";
span.textContent = part;
frag.append(span);
} else if (part) {
frag.append(part);
}
});
node.replaceWith(frag);
});
});
</script>
「2026年10月3日、(縦中横済みの12)時5分に100個」という段落で実行した結果の HTML です。3桁以上の数字と、すでに囲んである数字はそのまま残りました。
2026年<span class="tcy">10</span>月<span class="tcy">3</span>日、<span class="tcy">12</span>時<span class="tcy">5</span>分に100個
英単語・略語は正立か横倒しかを選ぶ
<p class="tategaki">
<span class="up">CSS</span>入門と JavaScript の基礎
</p>
.tategaki { writing-mode: vertical-rl; }
.tategaki .up { text-orientation: upright; }
| 文字列 | 向いている指定 | 理由 |
|---|---|---|
| 2〜4文字の略語(CSS、HTML、AI) | text-orientation: upright |
1字ずつ立てても短く、日本語となじむ |
| 長い英単語(JavaScript) | 指定なし(横倒しのまま) | 立てると行が長くなり、単語として読みにくくなる |
| 英文の引用 | text-orientation: sideways か指定なし |
横倒しのほうが文として読める |
| 2文字の単位や記号(kg、!?) | text-combine-upright: all |
1文字分にまとまる |
記号・括弧・長音の扱い
実際に表示して確かめた結果です。
| 文字 | 縦書きでの表示 | 対応 |
|---|---|---|
| 全角の!? | 正立 | そのままでよい |
| 半角の !? | 横倒し | 全角にするか、縦中横にする |
| 全角の( ) | 縦書き用の形(上下に開く括弧) | そのままでよい |
| 半角の ( ) | 横倒し | 全角にする |
| 全角の50% | 1文字ずつ正立 | そのままでよい |
| 半角の 50% | 横倒し | 数字を縦中横、%は全角に |
| 長音 ー | 縦棒の形 | そのままでよい |
| ダッシュ ― | 縦棒の形 | そのままでよい |
| 波線 〜 | 縦向きの波線 | そのままでよい |
| 半角ハイフン A-B | 英字ごと横倒し | 英単語の一部ならそのまま |
| 全角コロン : | 縦書き用の形 | そのままでよい |
縦書きにする原稿は、記号と括弧を全角でそろえておくと、CSS での調整がほとんど要らなくなります。なお、text-orientation: sideways を指定した範囲では、長音も横書きの形のまま回転しました。日本語を含む範囲には sideways を広く掛けず、英文の部分だけに絞るのがよい使い方です。
縦書きの余白は論理プロパティで書く
縦書きにすると、「上下左右」と「文章の向き」がずれます。たとえば段落の後ろの間隔は、横書きでは下(margin-bottom)ですが、縦書きでは左になります。論理プロパティは、上下左右ではなく「行の進む方向(ブロック方向)」と「文字の進む方向(インライン方向)」で指定する書き方で、横書きでも縦書きでも同じ意味で働きます。
次の CSS を、横書きと vertical-rl の両方に当てて、計算後の値を調べました。
.box {
margin-block-start: 10px;
margin-block-end: 20px;
margin-inline-start: 30px;
margin-inline-end: 40px;
padding-block: 1px 2px;
padding-inline: 3px 4px;
inline-size: 200px;
block-size: 100px;
border-inline-start: 5px solid red;
}
Chromium 141 での結果(getComputedStyle の値):
| 論理プロパティ | 横書き(horizontal-tb)では | 縦書き(vertical-rl)では |
|---|---|---|
margin-block-start: 10px |
margin-top: 10px | margin-right: 10px |
margin-block-end: 20px |
margin-bottom: 20px | margin-left: 20px |
margin-inline-start: 30px |
margin-left: 30px | margin-top: 30px |
margin-inline-end: 40px |
margin-right: 40px | margin-bottom: 40px |
padding-block: 1px 2px |
上 1px・下 2px | 右 1px・左 2px |
padding-inline: 3px 4px |
左 3px・右 4px | 上 3px・下 4px |
inline-size: 200px |
width: 200px | height: 200px |
block-size: 100px |
height: 100px | width: 100px |
border-inline-start |
左の枠線 | 上の枠線 |
覚え方は次のとおりです。
| 言葉 | 意味 | vertical-rl での向き |
|---|---|---|
| block-start | 行が始まる側 | 右 |
| block-end | 行が進んでいく側 | 左 |
| inline-start | 文字が始まる側 | 上 |
| inline-end | 文字が進んでいく側 | 下 |
| inline-size | 1行の長さ | 高さ |
| block-size | 行が積み重なる方向の長さ | 幅 |
縦書きと横書きを切り替えるページでは、余白とサイズを論理プロパティで書いておくと、writing-mode を変えるだけで余白の向きも一緒に切り替わります。
Flex・Gridの軸も縦書きで変わる
display: flex や display: grid の「行」「列」も、上下左右ではなく文章の向きに合わせて決まります。300×300px のコンテナに A・B・C を入れて位置を測りました。
| 指定 | 横書きでの並び | vertical-rl での並び(実測) |
|---|---|---|
display: flex(row) |
左から右へ A B C | 上から下へ A B C(y=0, 12, 22) |
flex-direction: column |
上から下へ | 右から左へ A B C(x=282, 264, 246) |
grid-template-columns: 100px 100px |
横方向に 100px の列が2つ | 縦方向に 100px の区切りが2つ |
grid-template-rows: 50px 50px |
縦方向に 50px の行が2つ | 横方向に 50px の区切りが2つ(右から左へ) |
Grid に 1〜4 の4つを入れた場合、横書きでは「1 2/3 4」と左上から右へ並びますが、vertical-rl では 1 が右上、2 がその下、3 が 1 の左、4 が 3 の下に置かれました(1: x=250,y=0 2: x=250,y=100 3: x=200,y=0 4: x=200,y=100)。
/* 縦書きの中で、見出しと本文を「右から左」に並べたい */
.card {
writing-mode: vertical-rl;
display: flex;
flex-direction: column; /* 縦書きでは column がブロック方向=右から左 */
gap: 1em;
}
row は「文字の進む方向」、column は「行の進む方向」と読み替えると、縦書きでも迷いません。justify-content は主軸、align-items は交差軸という関係はそのままです。
はみ出して横スクロールになる原因と対処
縦書きで長い文章を入れると、行が左へ左へと増えていき、枠の幅を超えることがあります。幅 375px・高さ 600px の画面に、長い文章(1,600字)を入れて測りました。
| パターン | 指定 | 要素の幅 | ページの横スクロール | 書き出し(1文字目)の位置 |
|---|---|---|---|---|
| A | 縦書きの div だけ(高さ指定なし) | 630px | あり(ページ幅 630px) | 左から 612px(画面の外) |
| B | html 要素ごと縦書き | 630px | あり(右端から始まる) | 左から 357px(画面内) |
| D | div に height: 300px |
1260px | あり(ページ幅 1260px) | 左から 1242px(画面の外) |
| E | D に width: 100%; overflow-x: auto |
375px | なし(枠の中でスクロール) | 左から 357px(画面内) |
ここからわかることは3つです。
- 縦書きの要素は、高さが決まると、文章量に応じて幅が広がります。 高さを指定しない場合は画面の高さ(今回は 600px)が上限になり、そこで折り返して左へ行が増えました。
- 横書きのページの中に縦書きの div を置くと、div は左端から配置されます。 書き出しは div の右端なので、幅が画面を超えると書き出しが画面の外に出ます(パターン A・D)。
width: 100%とoverflow-x: autoを付けると、枠の中だけがスクロールし、書き出しが見える状態から始まります(パターン E)。このとき枠のスクロール位置は 0 から負の方向(今回は -885 まで)に動きました。
コピペ用の形にすると次のようになります。同じ 1,600字の文章で試すと、枠は幅 375px・高さ 420px(70vh)に収まり、ページの横スクロールは出ず、書き出しは左から 353px の位置(画面内)に表示されました。
/* 横書きのページの中に、縦書きの読み物エリアを置く */
.tategaki-area {
writing-mode: vertical-rl;
inline-size: min(30em, 70vh); /* 1行の長さ(高さ)。画面の7割まで */
block-size: 100%; /* 親の幅いっぱい */
overflow-x: auto; /* 行が増えたら枠の中で横スクロール */
line-height: 1.8;
}
/* 画像や表が枠を押し広げないようにする */
.tategaki-area img {
max-block-size: 100%; /* 縦書きでは「幅」の上限になる */
block-size: auto;
}
画像についても測りました。高さ 300px・幅 375px の縦書きの枠に、幅 600px の画像を入れた場合です。
| 画像への指定 | 画像の幅(実測) |
|---|---|
| 指定なし | 600px(枠からはみ出す) |
max-block-size: 100% |
375px(枠に収まる) |
max-width: 100% |
375px(枠に収まる) |
横書きでおなじみの max-width: 100% はそのまま使えます。論理プロパティで書くなら、縦書きでの幅はブロック方向なので max-block-size です。
| 症状 | 原因 | 対処 |
|---|---|---|
| ページ全体が横に長くなる | 縦書き要素の幅が文章量で広がっている | width: 100%(または block-size: 100%)と overflow-x: auto |
| 書き出しが画面に見えない | 縦書きの枠が左端に置かれ、右端が画面外 | 枠に幅の上限とスクロールを付ける |
| 1行が画面より長く下が切れる | 高さ(inline-size)が画面より大きい |
inline-size: min(30em, 70vh) のように上限を付ける |
| 画像で枠が広がる | 画像に幅の上限がない | max-block-size: 100% |
| 短い文なのに枠が画面の高さまで伸びる | 高さを指定していない | inline-size を指定する |
スマホでは横書きに戻す切替
縦書きは画面の高さを1行の長さに使うので、縦に長いスマホ画面では行が長くなり、横スクロールも増えます。画面幅が狭いときだけ横書きに戻すのが、読みやすさと手間のバランスがよい方法です。
/* 既定:縦書き */
.article {
writing-mode: vertical-rl;
inline-size: min(30em, 80vh);
line-height: 1.8;
}
.article p {
margin-block: 0 1em;
text-indent: 1em;
}
.article .tcy { text-combine-upright: all; }
/* 画面幅 600px 以下:横書きに戻す */
@media (max-width: 600px) {
.article {
writing-mode: horizontal-tb;
inline-size: auto;
}
.article .tcy { text-combine-upright: none; }
}
この CSS を当てたページで、画面幅を変えて計算後の値を確認しました。
画面幅 1000px → writing-mode: vertical-rl / .tcy の text-combine-upright: all
画面幅 400px → writing-mode: horizontal-tb / .tcy の text-combine-upright: none
余白を margin-block や text-indent といった向きに依存しない書き方にしておけば、切り替えるのは writing-mode と行の長さだけで済みます。text-combine-upright は横書きでは効かないプロパティですが、切替の意図が伝わるように none に戻しています。
逆に「スマホでは横書き、広い画面だけ縦書き」と考える場合は、@media (min-width: 601px) の中に縦書きの指定を入れる書き方もできます。
.article p { margin-block: 0 1em; text-indent: 1em; }
@media (min-width: 601px) {
.article {
writing-mode: vertical-rl;
inline-size: min(30em, 80vh);
}
.article .tcy { text-combine-upright: all; }
}
よく使う縦書きパーツのコード
表の見出しを縦にする
<table class="schedule">
<tr>
<th class="v">担当</th>
<th class="v">開始日</th>
<th class="v">備考</th>
</tr>
<tr><td>佐藤</td><td>10/3</td><td>なし</td></tr>
</table>
.schedule th.v {
writing-mode: vertical-rl;
padding-block: 0.25em;
padding-inline: 0.5em;
white-space: nowrap;
}
縦書きの見出しと横書きの本文を並べる
<section class="feature">
<h2 class="feature-title">季節のおすすめ</h2>
<div class="feature-body">
<p>本文は横書きのままにして、見出しだけを縦に立てるレイアウトです。</p>
</div>
</section>
.feature {
display: flex;
flex-direction: row-reverse; /* 見出しを右側に置く */
gap: 1.5em;
}
.feature-title {
writing-mode: vertical-rl;
margin: 0;
letter-spacing: 0.1em;
}
ルビと傍点
<p class="tategaki">
<ruby>縦中横<rt>たてちゅうよこ</rt></ruby>は
<span class="bouten">2桁まで</span>がきれいです。
</p>
.tategaki { writing-mode: vertical-rl; }
.bouten { text-emphasis: sesame; } /* 傍点(ゴマ点) */
Chromium 141 で確認した結果は次のとおりです。
| パーツ | 確認できたこと |
|---|---|
| 表の見出し | 見出しセルが幅 34px・高さ 64px になり、横幅を節約できた(フォント 16px、3文字の見出しに合わせた高さ) |
| 縦見出し+横本文 | 見出しが右端に縦書きで置かれ、本文はその左に横書きで表示された |
| ルビ | ふりがなは親文字の右側に付いた |
| 傍点 | text-emphasis-style の計算値が sesame になった(点の位置の測定は未実行) |
よくある質問
Q. 縦書きにしたら数字が横に倒れました。どう直しますか?
A. 1〜2桁なら数字を span で囲んで text-combine-upright: all; を指定します。4桁の年などは text-orientation: upright; で1字ずつ立てるか、全角数字・漢数字にします。Chromium 141 では、縦中横にした文字は桁数に関係なく1文字分の枠に収まり、4桁ではかなり細くなりました。
Q. vertical-rl と sideways-rl は何が違いますか?
A. vertical-rl は日本語の文字を立てたまま縦に並べます。sideways-rl は横書きの行を丸ごと時計回りに90度回すので、漢字やかなも寝ます。日本語の縦組みには vertical-rl、英語のラベルを縦に置きたいときは sideways-rl や sideways-lr が合います。
Q. writing-mode に -webkit- や -ms- の接頭辞は必要ですか?
A. MDN の元データでは、接頭辞なしの writing-mode は Chrome 48・Firefox 41・Safari 10.1 から使えます。現在の主要ブラウザを対象にするなら、接頭辞なしの1行で足ります。
Q. 縦書きのページで横スクロールの始まりが左端になってしまいます。
A. 横書きのページの中に縦書きの要素を置くと、要素は左端から配置され、書き出し(右端)が画面の外に出ることがあります。縦書きの要素に width: 100% と overflow-x: auto を付けて、枠の中でスクロールさせると、書き出しが見える状態から始まります。
まとめ
- 縦書きは
writing-mode: vertical-rl;の1行で始められる。日本語は正立し、句読点・長音・全角括弧は縦書き用の形に自動で切り替わる - 5つの値の違いは「文字が立つか寝るか」と「行の進む向き」。日本語の本文は
vertical-rl、英語ラベルはsideways-rl/sideways-lr(Chrome 132・Safari 18.4 以降) - 1〜2桁の数字は
text-combine-upright: all(縦中横)、4桁や略語はtext-orientation: upright。digitsの値はまだ使えない - 記号と括弧は全角にそろえると、CSS での調整がほとんど要らない
- 余白とサイズは論理プロパティ(
margin-block、padding-inline、inline-size)で書くと、縦横を切り替えても向きが合う - Flex の row は文字の進む方向、column は行の進む方向。縦書きでは row が上から下になる
- 横スクロール対策は
width: 100%とoverflow-x: auto、スマホではメディアクエリでhorizontal-tbに戻す
参考・出典
- MDN Web Docs: writing-mode(値の説明、Baseline の時期)
- MDN Web Docs: text-orientation(値の説明、upright と direction の関係)
- MDN Web Docs: text-combine-upright(digits の対応状況)
- mdn/browser-compat-data: css/properties/writing-mode.json(各値の対応バージョン)
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS縦書きwriting-modeの使い方|数字・英字の縦中横まで」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。