CSSの論理プロパティで、書く向きに合わせて余白を付ける方法
margin-inline-start や padding-block のような論理プロパティを使うと、余白や線を「左」「上」ではなく、「行の始まり」「行の終わり」で指定できます。同じ CSS のまま、右から左に書く言語では左右が入れ替わり、縦書きでは行の始まりと終わりが上と下になるので、向きごとに CSS を書き分けずに済みます。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。ヘッドレスの Chromium で、幅800px・高さ600pxの画面にページを開き、getComputedStyle() で計算後の上下左右の値を、getBoundingClientRect() で位置と大きさを測りました。Firefox と Safari では試していません。右から左の向きは、アラビア語などの文章ではなく、日本語の文に dir="rtl" を付けて確かめています。

論理プロパティは「行の向き」と「行が並ぶ向き」で指定する
論理プロパティでは、辺を inline と block で呼び分けます。inline は文字が並んで1行ができる向き、block は行や段落が積み重なる向きです。日本語や英語の横書きなら、inline は左から右、block は上から下です。それぞれの始まりの辺が start、終わりの辺が end です。
MDN の論理プロパティの基本概念の説明にあるとおり、論理プロパティは、margin-left や width のような画面の向きで決まる物理プロパティに対応するものです。同じく MDN の margin-inline の説明によると、対応先は、要素の writing-mode(横書きか縦書きか)と direction(左から右か右から左か)などで決まります。
検証には、次のお知らせの囲みを使いました。行の始まりの側(横書きなら左)に余白と線を付け、アイコンと本文の間を空けたものです。
.notice {
margin-block: 16px;
margin-inline-start: 24px;
padding-block: 8px;
padding-inline: 16px 8px;
border-inline-start: 6px solid #d85878;
max-inline-size: 280px;
}
.notice .icon {
margin-inline-end: 8px;
}
<div class="notice"><span class="icon">★</span><span class="text">お知らせの本文です。</span></div>
親要素を、指定なしの横書き、dir="rtl"、writing-mode: vertical-rl の3通りにして、計算後の値を調べました。
| 指定 | 横書き・左から右 | 横書き・右から左 | 縦書き |
|---|---|---|---|
margin-inline-start: 24px |
左 24px | 右 24px | 上 24px |
margin-block: 16px |
上下 16px | 上下 16px | 左右 16px |
padding-inline: 16px 8px |
左 16px・右 8px | 右 16px・左 8px | 上 16px・下 8px |
border-inline-start: 6px |
左 6px | 右 6px | 上 6px |
max-inline-size: 280px |
max-width 280px |
max-width 280px |
max-height 280px |
アイコンの margin-inline-end: 8px |
右 8px | 左 8px | 下 8px |
横書きで左から右に書くときは、left や width で書いた場合と同じ値になります。右から左にすると、左右がそっくり入れ替わりました。縦書き(vertical-rl)では、文字は上から下へ進んで1行になり、次の行は前の行の左に並びます(MDN の writing-mode の説明)。そのため、inline の始まりが上、block の始まりが右になります。表のとおり、margin-block は左右の余白に、max-inline-size は高さの上限になりました。
物理プロパティのままだと、右から左のときに線と余白が逆側に残る
同じ囲みを margin-left、padding-left、border-left、margin-right(アイコン)で書き、dir="rtl" の中に置くと、計算後の値は左から右のときと同じで、線も24pxの余白も左のままでした。
一方、右から左の文章では、ブロックは右端に寄り、アイコンは本文の右に来ます。そのため、上の画像の2段目のように、囲みは親の右端にくっつき、線は行の終わりの側に付き、アイコンは本文と詰まって表示されました。論理プロパティで書いた3段目では、余白と線とアイコンの間隔が、そろって右から左の向きに合わせて付いています。
今は右から左の言語に対応していなくても、論理プロパティで書いておけば、あとで対応するときは、CSS を探して書き換えなくても、dir を切り替えるだけで済みます。
margin-inline に値を1つ・2つ書いたとき
margin-inline と padding-inline は、始まりと終わりをまとめて指定する一括指定です。MDN の margin-inline の説明のとおり、値が1つなら両側に同じ値、2つなら1つ目が始まり、2つ目が終わりに入ります。幅400pxの親の中に、幅200pxの子を置いて確かめました。
| 指定 | margin-left |
margin-right |
子の左端 |
|---|---|---|---|
margin-inline: 10px |
10px | 10px | 10px |
margin-inline: 10px 20px |
10px | 20px | 10px |
margin-inline: auto |
100px | 100px | 100px |
margin: 0 auto で中央に寄せていたところは、margin-inline: auto に置き換えられます。margin と違って上下の余白には触れないので、上下に付けた余白をうっかり0にすることもありません。margin-block、padding-block も同じように、上下(縦書きでは左右)をまとめて指定します。
縦書きでは width の代わりに inline-size を使う
幅と高さにも論理プロパティがあります。inline-size は行の向きの大きさ、block-size は行が並ぶ向きの大きさです。inline-size: 200px; block-size: 50px を指定した要素を測りました。
| 向き | 計算後の width |
計算後の height |
|---|---|---|
| 横書き | 200px | 50px |
縦書き(vertical-rl) |
50px | 200px |
縦書きでは、inline-size が高さに、block-size が幅になりました。MDN の inline-size の説明にあるとおりの対応です。囲みの例で使った max-inline-size のように、上限を決めるものもあります。縦書きの段落の1行の長さを決めたいときは、width ではなく inline-size か max-inline-size を使うと、横書きと同じ書き方で済みます。
位置の指定と文字そろえにも始まりと終わりがある
position: absolute の要素を置く top や left にも、inset-block-start や inset-inline-start という論理プロパティがあります。text-align には start と end という値があります。幅400pxの親の中で、inset-block-start: 0; inset-inline-start: 0 で置いた幅50pxの要素と、text-align: start の行を、向きを変えて測りました。
| 向き | inset-inline-start: 0 の計算後の値 |
text-align: start の行 |
|---|---|---|
| 左から右 | left: 0px |
左端に寄る |
| 右から左 | right: 0px |
右端に寄る |
右から左のときは、要素は親の右端に付き、文字も右端に寄りました。MDN の inset-inline-start の説明にあるとおり、位置指定されていない要素には効きません。float にも inline-start と inline-end の値がありますが、下の対応表のとおり、Chrome では118からなので、古いブラウザも対象にするなら注意が要ります。
margin-left と margin-inline-start を両方書くと、後に書いたほうが使われる
左から右の横書きでは、margin-left と margin-inline-start は同じ余白を指します。CSS Logical Properties and Values Level 1 の仕様では、このように同じ辺を指す物理プロパティと論理プロパティは、1つのプロパティとみなしてカスケードし、優先度の高い宣言の値を使う、と決められています。同じ規則の中なら、後に書いたほうが使われます。
| 書いた順 | 向き | margin-left |
margin-right |
|---|---|---|---|
margin-left: 10px; margin-inline-start: 20px; |
左から右 | 20px | 0px |
margin-inline-start: 20px; margin-left: 10px; |
左から右 | 10px | 0px |
margin-left: 10px; margin-inline-start: 20px; |
右から左 | 10px | 20px |
右から左では、margin-inline-start は右の余白になるので、2つの宣言はぶつからず、両方が使われました。物理プロパティで書いた古い CSS に、margin-left を残したまま margin-inline-start を足すと、右から左のときには左右の両方に余白が付きます。書き換えるときは、同じ辺の古い宣言を消しておくと迷いません。
余白や線の向きは、その要素自身の writing-mode と direction で決まる
margin-inline-start がどの辺になるかは、親ではなく、その要素自身の向きで決まります。親に dir="rtl" があっても、子に dir="ltr" を付けると、子の margin-inline-start: 20px は margin-left の20pxになりました。親が縦書きで子が横書きのときも、子の margin-inline-start は上ではなく左の余白になりました。前の節で引いた仕様にも、余白・線・大きさなどのプロパティは、要素自身の計算後の書字方向で対応を決める、と書かれています。ただし、float と clear の inline-start と inline-end だけは、その要素ではなく、包含ブロックの書字方向で決まると、同じ仕様に書かれています。
対応しているブラウザ
MDN の互換性データ(@mdn/browser-compat-data 8.1.8)で調べた、最初に対応したバージョンです。
| 機能 | Chrome | Firefox | Safari | iOS の Safari |
|---|---|---|---|---|
margin-inline-start、border-inline-start |
69 | 41 | 12.1 | 12.2 |
inline-size |
57 | 41 | 12.1 | 12.2 |
margin-inline、padding-block |
87 | 66 | 14.1 | 14.5 |
inset-inline-start、inset-inline |
87 | 63 | 14.1 | 14.5 |
text-align: start |
1 | 1 | 3.1 | 2 |
float: inline-start |
118 | 55 | 15 | 15 |
margin-inline のような一括指定と、inset- で始まる位置のプロパティは、margin-inline-start などより後に対応しています。





