CSS優先度のちょっと細かい話 !importantから継承まで


# CSSの優先度（簡易版）

1. !important
1. style属性
1. 詳細度
    1. ID セレクター（#example など）
    1. クラスセレクター（.example など）、属性セレクター（[type="radio"] など)、擬似クラス（:hover など）
    1. 要素型セレクター（h1 など）と擬似要素（::before など）
    1. 全称セレクター（*）（詳細度なし）
    1. より後にある定義
1. 祖先からの継承

---
## !important
!importantをつけたルールは優先されます
とても強いルールなので安易につけることは非推奨とされていますが、使い所を抑えておけばとても便利です

```css
div { color: red !important; } /* こちらが適用される */
.class { color: blue; }
```

---
## style属性（インラインスタイル）
要素に直接スタイルを適用できる属性です
外部のスタイルを上書きするため後述する詳細度からも一弾飛び抜けて優先されます

```html
<div style="color: blue;"><!-- こちらが適用される -->
  text
</div>
```

---
## 詳細度（詳細度アルゴリズム）
一般的なCSSセレクターによって適用される優先度です
ざっくりいうと**より具体的**な指定がされているルールが適用されます

これにもちゃんと計算方法があります

---

まずセレクターは種類ごとにランク分けされており、どれがより詳細であるかが決まっています

|詳細度が高い順|セレクター種類|備考|
|---|---|---|
|1|ID セレクター|#example など|
|2|クラスセレクター、属性セレクター、擬似クラス|.example、[type="radio"]、:hover など|
|3|要素型セレクター、擬似要素|h1、::before など|
|4|全称セレクター|* 詳細度なし|

例えば以下のようにIDセレクターを使ったルールがある場合、クラスセレクターより詳細度が高いためIDのほうが適用されます

```css
#id { color: red; } /* こちらが適用される */
.class { color: blue; }
```

---
そして同ランクの場合はより該当するセレクターが多いほうが優先されます

```css
.parent .child { color: red; } /* こちらが適用される クラスセレクター × 2 */
.child { color: blue; } /* クラスセレクター × 1 */
```

セレクターの数まで一致している場合は後に定義されたルールが適用されます

```css
.parent1 .child { color: red; }
.parent2 .child { color: blue; } /* こちらが適用される */
```

---

# 祖先からの継承
最後に一部のCSSは祖先要素から値を継承します。
だいたい文字に関わるCSSは継承されているようです。

```html
<div class="parent">
  <div>
    Child
  </div>
</div>
```

```css
.parent { color: red; }
```

---

# どっちが強い？

---

## 問１

```html
<h1 id="id1" class="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11">
  COLOR
</h1>
```
```css
#id1 { color: red; }
.c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11 { color: blue; }
```

---

## 問１答え
赤色

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/86170c8d-7437-e323-97d0-e522d9ad7a12.png)


詳細度はID セレクターのほうがより優先度が高い仕様なので、クラスをいくらつけたところでID指定には勝てません。

他のサイトだとIDは100点、classは10点という点数換算で詳細度を紹介しているところがありますがあれは正確ではありません。

---

## 問２
```html
<h1 id="id1" style="color: gray !important;">
  COLOR
</h1>
```

```css
#id1 { color: red !important; }
```

---

## 問２答え

灰色

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/e3d9f152-4adf-c10a-dbac-bce003ffd74c.png)

style属性、idセレクターのどちらにも`!important`がついているので次に優先度の高いstyle属性のほうが優先される

多分これが一番優先度が高いと思います

---

## 問３

```html
<h1 id="parent">
  <div class="child">
    <div>
      COLOR
    </div>
  </div>
</h1>
```

```css
* { color: blue; }
.child { color: green; }
#parent { color: red; }
```

---

## 問３答え

青色

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/c8c15034-9226-6d9d-d315-cb11dc53eee2.png)

COLORの文字列は`#parent`の直下でも、`.child`の直下でもない。
全称セレクター(*)は詳細度の範囲で、継承よりも優先度が高くなる

---

# もうちょっと深堀りした話
## CSS宣言のオリジン
CSSの宣言は大きく３つの起源に分けられる

- ユーザーエージェントスタイルシート
    - ブラウザによって定義されたスタイル。いわゆるデフォルトスタイル
- 作成者スタイルシート
    - ページの作成者によって定義されたスタイル。**我々エンジニアがいじっているCSSはこれ**
- ユーザースタイルシート
    - ユーザーによって定義されたスタイル

## カスケードアルゴリズムと詳細度アルゴリズム

CSSの評価は大きく２つのアルゴリズムによって行われている

|適用順序|アルゴリズム|内容|
|---|---|---|
|1|カスケードアルゴリズム|CSSの起源と重要度による適用|
|2|詳細度アルゴリズム|id, class, 要素|

---

カスケードアルゴリズムでは以下のような優先度になっている。

|優先度|起源|重要度| |
|---|---|---|---|
|1|ユーザーエージェントスタイルシート|!important| |
|2|ユーザースタイルシート|!important| |
|3|作成者スタイルシート|!important|普段開発で意識するのはここ|
|4|作成者スタイルシート|通常|普段開発で意識するのはここ|
|5|ユーザースタイルシート|通常| |
|6|ユーザーエージェントスタイルシート|通常| |
※アニメーションの考慮は除く

`!important`が優先されるのはそもそも評価タイミングが違うから！

---

# これらのルールを踏まえた上で、スタイル定義の留意点

- 基本的にはclassによってスタイルをつける
目的別にclassを用意しておけば変更も流用もしやすい。
classじゃ不都合なときに他のセレクターやstyle属性など適切なものを使えば良い

- `!important`はこれ以上のスタイルの変更が加わらない箇所でなら使ってよし
特に極々限定的なデザインのカスタマイズをする必要があるときに詳細度で頑張らなくて良い
逆にライブラリや汎用的なコンポーネント、詳細度の低いルールで`!important`をつけてはいけない

それほど特別なことは無いです。
自分は今までもやっていたけど、仕様を調べたことでより納得感がましたと思います。

---

# CSS優先度のデバッグ

たいていのブラウザはF12キーを押すとdeveloper toolsが開きます。その要素（Element）タブでCSSを確認できます。

適当な要素をクリックするとその要素に関連するCSSルールがすべて表示されます。
その要素は詳細度の高い順に並んでいるため、上にあるCSSが適用されるとおぼえておくと良いでしょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/1f2b3b0b-75a0-f516-7a6c-98bc79f2efdb.png)

他にも上書きされたスタイル、ユーザーエージェントのスタイル、継承されたスタイいるなどの情報ものっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/eb2a8cf3-a5b0-dc7f-d942-28e90f8e3cb6.png)

計算済み（Computed）には最終的に適用されたスタイルの一覧が表示されます。
分類する（Grouping）チェックを入れると関心の近いものが集まって表示されるのでおすすめです。
特定のプロパティを開くと関連するルールもすべて表示されます。（こちらも詳細度順）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/431d42e5-e3a7-d322-3faf-4c0c6ffd152f.png)