スタイルが当たらない時に、知っておきたいCSSテクニック

今日、仕事仲間に**あるテクニック**を紹介したら、意外と喜ばれたので、22ヶ月ぶりにQiitaに投稿してます @BYODKM です。

以前に書いたCSS系の記事は、こんな感じでした。（カッコ内の数字は現時点のもの）

- [破綻しにくいCSS設計の法則 15](https://qiita.com/BYODKM/items/b8f545453f656270212a) （1464いいね）
- [CSSが破綻する4つの理由](https://qiita.com/BYODKM/items/8c777db2d89f4e830c93)（785いいね）
- [二行目の最後を「...」をクロスブラウザで実現](https://qiita.com/BYODKM/items/83442749a985cb81448e)（173いいね）

## スタイルが当たらない！

さて、スタイルが当たらない訳ですが、考えられる原因として大きく二つあると思います。

1. HTML側にマッチする内容がない
2. 他のスタイルが強くて打ち消されてしまう

1の方は多分凡ミスなので、よくコードを見ましょう。今回扱うのは、2の方です。

### スタイルが当たらない単純な例

```html
<input type="text" class="input-text" value="value">
```

上のようなHTMLに対して、下のようなスタイルが提供されていたとします。

```css
// Reset Style

input[type="text"] {
  color: red;
}
```

```css
// Form Style

.input-text {
  color: green;
}
```

この場合、`input`要素の色は`green`ではなく`red`になります。これは詳細度の計算上から、そうなります。

### 詳細度計算

<img width="699" alt="Screen Shot 2018-06-13 at 22.02.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/48d63807-21a0-dfc6-ab60-462b0180a4c6.png">

 [Specificity Calculator](https://specificity.keegan.st)で計算してみると、`.input-text`よりも`input[type="text"]`の方がスコアが高くなっているのが分かります。これではスタイルが当たりません。

次に、解決方法を見ていきましょう。

## 好ましくない解決方法（1）

```css
.input-text {
  color: green !important;
}
```

おい、やめろ

## 好ましくない解決方法（2）

```css
form .input-text {
  color: green;
}
```

構造に依存する書き方をすると、スタイルを当てるためにその構造を維持し続ける必要が出てくるので、可能ならやめておきましょう。

## 好ましくない解決方法（3）

```css
input.input-text {
  color: green;
}
```

これは一見アリだと思いますが、`input`要素以外ではアンチパターンとして知られています。

```css
li.list-item {
  color: green;
}
```

ほらね。ということで、一旦ナシで。

## 汎用的な解決方法

ここに、スタイルが当たらない`.your-class`があるとします。

```css
.your-class {
  color: green;
}
```

このままだとスタイルが当たらないので、クラス名に続けて`:not(:root)`と記述します。

```css
.your-class:not(:root) {
  color: green;
}
```

これで大抵の場合、スタイルがあたるようになります。

## 証拠

<img width="689" alt="Screen Shot 2018-06-13 at 22.56.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/25368d14-c9b9-db32-db7f-7ba8acec8165.png">

ただの`.your-class`に比べて、詳細度が倍になりました。

<img width="690" alt="Screen Shot 2018-06-13 at 22.17.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/5055e225-212f-93f6-5bd8-842e68be41cf.png">

`.input-text`の場合でも同様です。

## 解説

今回登場した`:not()`は[否定擬似クラス](https://www.bing.com/search?q=%E5%90%A6%E5%AE%9A%E6%93%AC%E4%BC%BC%E3%82%AF%E3%83%A9%E3%82%B9)、`:root`は[ルート擬似クラス](https://www.bing.com/search?q=%E3%83%AB%E3%83%BC%E3%83%88%E6%93%AC%E4%BC%BC%E3%82%AF%E3%83%A9%E3%82%B9)で、`.your-class:not(:root)`だと、「ルート要素ではない`.your-class`」という意味になります。これは後述する「使いものにならないケース」を除いて常にValidになります。

下のように、`:root`の代わりに`html`を入れた場合は、少し控えめな数値になります。

<img width="691" alt="Screen Shot 2018-06-13 at 22.59.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/79eca78d-8293-3c36-2096-3a9194a06f3c.png">

逆にIDを入れると、スコアが高騰します。

<img width="690" alt="Screen Shot 2018-06-13 at 23.07.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/fa345c3c-f76c-7a53-6e00-77ceb07e263f.png">


### 使いものにならないケース

<img width="691" alt="Screen Shot 2018-06-13 at 23.00.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/38383/1613bd0c-f1fe-042d-3a91-9ae5d31863a1.png">

`html:not(html)`は矛盾となるので、詳細度が高くても使い物になりません。

同じ理由で、`html.your-class:not(html)`や`html.your-class:not(:root)`も矛盾になるので、使い物になりません。

## 本日のまとめ

- スタイルの当たらないクラスに`:not(:root)`を付けると、大抵の場合、これだけで解決する（便利！）
- CSSのご利用は計画的に

現場からは以上です。