【完全ガイド】CSS論理プロパティから見る 新しいCSSの考え方

あなたは
「**CSS論理プロパティを知っていますか？**」「**モダンなCSSをかけていますか？**」

本記事はCSS論理プロパティについてまとめた記事です。

まだ`margin: 0 auto;`使ってない？`margin-inline`のような書き方知ってる？

一言でまとめると、上記のような内容が載ってます。まとめ過ぎましたが...

Webサイトやアプリの多言語対応やアクセシビリティにも関連するテーマなので、
興味がある方はぜひご一読いただけると嬉しいです:raised_hand:

## 論理プロパティとは
CSSの論理プロパティは、2018年にW3Cによって提案された比較的新しいCSS仕様です。これは、私たちが慣れ親しんできた「上下左右」という物理的な方向ではなく、「コンテンツの流れ」に基づいてレイアウトを定義する方法です。

この概念が生まれた背景には、ウェブの国際化という大きな課題がありました。例えば、アラビア語のように右から左に読む言語や、日本語の縦書きのように上から下に読む言語など、世界には様々な書字方向が存在します。従来のCSSでは、これらの多様な書字方向に対応する為、言語ごとに異なるスタイルを書く必要がありました。

### 従来の物理プロパティとの違いは？
#### 物理プロパティの場合
![direction-arrows-svg-12-06-2024_06_31_PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/3bf72fe1-25f7-f735-2948-d2ab612228b4.png)

従来の物理プロパティは、画面上の絶対的な位置を基準にしています。
```style.css
.traditional-button {
  margin-left: 20px;
  padding-top: 10px;
  border-right: 1px solid black;
}
```
この場合、左からのマージン、上からのパディング、右側のボーダーは、どの言語でも同じ物理的な位置に適用されます。

#### 論理プロパティの場合
![CSS論理プロパティについての解説.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/5d5af949-41ba-3fe0-2511-48fa68428c93.png)
一方、論理プロパティは、コンテンツの流れる方向を基準にします。
```style.css
.logical-button {
  margin-inline-start: 20px;
  padding-block-start: 10px;
  border-inline-end: 1px solid black;
}
```
ここで重要なのは、`inline-start`や`block-start`という概念です。

`inline`：テキストが流れる方向（左から右、右から左、上から下など）
`block`：テキストが積み重なっていく方向（上から下、右から左など）

### メリットまとめ
| メリット | 説明 | 具体例 |
|---------|------|--------|
| 国際化対応の簡素化 | 1つのCSSコードで、異なる言語や書字方向（LTR/RTL/縦書き）に自動的に対応できます。言語ごとに個別のスタイルを書く必要がありません。 | アラビア語版のサイトを作る際、`margin-inline-start: 20px`は自動的に右側のマージンとして解釈されます。 |
| メンテナンス性の向上 | 書字方向が変更された場合でも、CSSコードを修正する必要がありません。これにより、長期的なコードの保守が容易になります。 | サイトを左書きから右書きに変更する際、論理プロパティを使用していれば、CSSの変更は不要です。 |
| レイアウトの一貫性確保 | 異なる言語や書字方向でも、デザインの意図が正確に保持されます。ユーザー体験の品質を維持できます。 | ナビゲーションメニューの配置が、どの言語でも常にテキストの開始位置に維持されます。 |
| コード量の削減 | 方向ごとの個別指定が不要になり、より少ないコードで同じ機能を実現できます。 | `margin-left`と`margin-right`の代わりに、`margin-inline`一つで済みます。 |
| レスポンシブ対応の簡略化 | 画面サイズやデバイスの向きが変更されても、論理プロパティは適切にレイアウトを調整します。 | コンテナの向きが変わっても、`inline-size`は自動的に適切な方向のサイズを指定します。 |
| 将来の変更への耐性 | 新しい書字方向や表示方式が登場しても、論理プロパティを使用したコードは柔軟に対応できます。 | 新しいブラウザ機能や表示方式が導入されても、論理的な指定は意図通りに解釈されます。 |
| 直感的なデザインフロー | コンテンツの流れに基づいた指定により、デザイナーとの協業がスムーズになります。 | デザイナーが「コンテンツの開始位置に余白を」と指示した場合、そのまま`margin-inline-start`として実装できます。 |

「いやでもさ、物理プロパティの方が直感的じゃない？？」
そう感じる方も多いと思います。私も論理プロパティを知った当初はそう感じました...
これは、恐らく私たちが長年「top」「right」「bottom」「left」という物理方向概念に慣れ親しんできたからだと思います。人間の「慣れ」という感覚は恐ろしいものですね。

最初は若干違和感を感じるものかもしれませんが、グローバル化が進む現代のウェブ開発において、論理プロパティは非常に有用だと思います。

## 実際の使い方
論理プロパティの実践的な使用方法を見ていきましょう。従来の物理プロパティと論理プロパティを並べて示すことで、その違いをより明確に理解できると思います。

### サイズ指定
```style.css
/* 従来の方法 */
.physical-box {
  width: 200px;
  height: 100px;
  min-width: 150px;
  max-width: 300px;
}

/* 論理プロパティを使用した方法 */
.logical-box {
  inline-size: 200px;      /* テキストが流れる方向のサイズ */
  block-size: 100px;       /* テキストが積み重なる方向のサイズ */
  min-inline-size: 150px;  /* 最小インラインサイズ */
  max-inline-size: 300px;  /* 最大インラインサイズ */
}
```
### マージンとパディング
```style.css
/* 従来の方法 */
.physical-spacing {
  margin-top: 20px;
  padding-left: 15px;
}

/* 論理プロパティを使用した方法 */
.logical-spacing {
  margin-block-start: 20px;    /* ブロック方向の開始位置のマージン */
  padding-inline-start: 15px;  /* インライン方向の開始位置のパディング */
}
```

### ボーダーとボーダーradius
```style.css
/* 従来の方法 */
.physical-border {
  border-left: 1px solid black;
  border-top-left-radius: 5px;
}

/* 論理プロパティを使用した方法 */
.logical-border {
  border-inline-start: 1px solid black;
  border-start-start-radius: 5px;  /* 開始側の開始角の丸み */
}
```

### 位置指定（inset）
```style.css
/* 従来の方法 */
.physical-position {
  position: absolute;
  top: 0;
  left: 0;
}

/* 論理プロパティを使用した方法 */
.logical-position {
  position: absolute;
  inset-block-start: 0;  /* ブロック方向の開始位置 */
  inset-inline-start: 0; /* インライン方向の開始位置 */
}
```

## サポート状況は？
### 最新の主要ブラウザサポート状況
現在（2024年時点）、主要なモダンブラウザ（Chrome、Firefox、Safari、Edge）では、ほとんどの論理プロパティがサポートされています。ただし、以下2点には注意してください。

- 古いバージョンのブラウザでの対応
- 一部のプロパティ（特にボーダーラジウス関連）のサポート状況

これらの問題に対するフォールバック方法を見ていきましょう。
```style.css
.safe-logical-box {
  /* フォールバック：古いブラウザ用 */
  width: 200px;
  /* モダンブラウザ用の論理プロパティ */
  inline-size: 200px;
  
  /* @supportsを使用した方法 */
  @supports (inline-size: 200px) {
    width: unset; /* 物理プロパティをリセット */
    inline-size: 200px;
  }
}
```

### CSSフレームワーク・CSS in JS でのサポート状況
現代のフロントエンド開発では、TailwindCSSなどのCSSフレームワークの使用が一般的です。これらでの論理プロパティの扱いを見ていきましょう。

#### TailwindCSSでの論理プロパティの扱い
TailwindCSSは、バージョン2.0から論理プロパティのサポートを開始し、バージョン3.0でさらに強化されました。具体的には以下のような形でサポートされています。

##### マージンとパディング
```index.html
<!-- 物理プロパティを使用した従来の方法 -->
<div class="ml-4">左マージン</div>
<div class="pr-2">右パディング</div>

<!-- 論理プロパティを使用した新しい方法 -->
<div class="ms-4">開始位置マージン</div>
<div class="pe-2">終了位置パディング</div>

<!-- RTL言語でも正しく動作 -->
<div dir="rtl" class="ms-4">右マージンになります</div>
```

##### ボーダー
```index.html
<!-- 物理プロパティ -->
<div class="border-l">左ボーダー</div>

<!-- 論理プロパティ -->
<div class="border-s">開始位置ボーダー</div>
```

##### テキストの配置
```index.html
<!-- 物理プロパティ -->
<div class="text-left">左揃えテキスト</div>

<!-- 論理プロパティ -->
<div class="text-start">開始位置揃えテキスト</div>
```
##### スクロールスナップ位置
:::note
スクロールスナップとは、ユーザーがスクロールを終えた時に、コンテンツを特定の位置に自動的に「スナップ（ぴたっと合わせる）」させる機能です。

例えば、iPhoneでホーム画面を左右にスワイプする時、画面が途中で止まらずに、次のページにぴたっと収まりまると思います。このような現象を制御するプロパティです。
:::
```index.html
<!-- 物理プロパティ -->
<div class="snap-left">左スナップ</div>

<!-- 論理プロパティ -->
<div class="snap-start">開始位置スナップ</div>
```

ただ、TailwindCSSを使用する際も通常のCSS使用時と同じく以下注意してください。
- バージョンの互換性

対処法は以下が挙げられます。

**configファイルに記載する**
```tailwind.config.js
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      margin: {
        'start': 'margin-inline-start',
        'end': 'margin-inline-end',
      },
    },
  },
}
```
**フォールバックの実装**
```index.html
<!-- フォールバック付きの実装 -->
<div class="ml-4 ms-4 rtl:mr-4">
  コンテンツ
</div>
```



### CSS Modulesやstyled-componentsの場合
これらのモダンなCSS手法では、通常のCSSと同様に論理プロパティを使用できます。
```index.jsx
// styled-componentsの例
const LogicalBox = styled.div`
  inline-size: 100%;
  margin-inline-start: 1rem;
`;
```

## まとめ
CSS論理プロパティは、グローバル化が進む現代のウェブ開発において、非常に重要な概念となっています。確かに、最初は従来の物理プロパティと比べて直感的でないように感じるかもしれません。しかし、以下の利点を考えると不要とは言えないと思います。

- 多言語対応が容易になる
- コードの保守性が向上する
- レイアウトの一貫性が保てる
- 将来的な方向の変更に強い

ブラウザ対応状況があるので、絶対に導入すべきとは言えませんが、徐々にプロジェクトでもCSS論理プロパティを活用していきましょう！

本記事をご一読いただきありがとうございました！:bow_tone1: