CSSのコンビネータって言われてピンとくる人は読まなくていいやつ

コンビネータと聞いてピンときた人は読まなくても良い記事です！
ただ、今回私が初めて知った**「Column combinator」と「Namespace separator」**についても紹介しているので気になる方はそちらから読んでください！

**ページ内リンクの設置**

:::note warn
普段「コンビネータ」というワードを用いて会話はしないので、恥ずかしながら調べ直すまで「？」な状態でした…
:::

ドキュメントを読んでいると時折出てくるコンビネータについて調べたら発見もあったので記事にしました！

## コンビネータってなに？
カタカナで表現されると「ん？」となりますが、結合子のことです！
皆さんもよくお世話になっているであろう**CSSのセレクタの子要素にスタイルを適用する時に使う`>`などです！**

https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Selectors/Combinators

## コンビネータの種類
MDNだと7つがコンビネータとして定義されています。

- [Child combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator)
- [Column combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Column_combinator)
- [Namespace separator](https://developer.mozilla.org/en-US/docs/Web/CSS/Namespace_separator)
- [Next-sibling combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator)
- [Selector list](https://developer.mozilla.org/en-US/docs/Web/CSS/Selector_list)
- [Subsequent-sibling combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Subsequent-sibling_combinator)

普段と表現が異なるとなんやそれ？ってなりますが、ほとんどは慣れ親しんだコンビネータです！

|combinator|セレクタの指定方法|補足|
|--|--|--|
|Child combinator|div > p|直接の子要素指定|
|Next-sibling combinator|div + p|同じ親の子である場合の次の要素を指定|
|Selector list| div, p, img|（,）カンマで区切られたセレクターのリスト|
|Subsequent-sibling combinator|div ~ p|~（チルダ）で同じ親要素かつ、1つ目のセレクタの後続要素に対しての指定|

今回調べて知らなかった「Column combinator」と「Namespace separator」について紹介します！

## Column combinator
`||`でセレクターを区切ります。
1つ目のセレクターでターゲットの列要素を指定し、2つ目のセレクターで要素を指定します。

```css
column-selector || cell-selector {}
```

なので`table`タグで利用できるセレクターのようです！
下記のコードはMDNに掲載されていたものです。

```css
col.selected||td {
  background: gray;
  color: white;
  font-weight: bold;
}
```

```html
<table border="1">
  <colgroup>
    <col span="2" />
    <col class="selected" />
  </colgroup>
  <tbody>
    <tr>
      <td>A</td>
      <td>B</td>
      <td>C</td>
    </tr>
    <tr>
      <td colspan="2">D</td>
      <td>E</td>
    </tr>
    <tr>
      <td>F</td>
      <td colspan="2">G</td>
    </tr>
  </tbody>
</table>
```

ブラウザで表示の確認方法がわからなかった（そもそも現時点ではできないかも）のでおそらく下記のような見た目になるのではないかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/3fc5a1a1-705c-bc57-62ef-0cc9ed799786.png)

```css:上記画像は下記のセレクタで実現しています
col.selected {
  background: gray;
  color: white;
  font-weight: bold;
}
```

「Column combinator」は上記のセレクタに追加の条件として`td`であることを追加しているのでMDNのサンプルコードだと画像と同じ表示になるのではないかと予測されます。

:::note alert
こちらはまだ実験的だそうで、今後はどうなるかわかない状態であることを誤認識ください…
:::

現時点でブラウザ互換はなさそうです…。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/ecab8691-11e3-ef86-3ce8-01d69fd80f6e.png)

https://developer.mozilla.org/en-US/docs/Web/CSS/Column_combinator

## Namespace separator
名前空間を指定することで指定した名前空間内の要素に対してスタイルを当てられます。
`名前空間 | セレクタ`の形式で記述します。

```css
/* myNameSpaceの名前空間内にあるaタグに対してスタイルを適用します */
myNameSpace|a {
  font-weight: bold;
}

/* 全てのpタグに対してスタイルを適用します */
*|p {
  color: darkblue;
}

/* ネームスペースがないh2タグに対してスタイルを適用します */
|h2 {
  margin-bottom: 0;
}
```

> デフォルトでは、HTML または SVG 要素内のすべての要素には、`http://www.w3.org/1999/xhtml`および`http://www.w3.org/2000/svg`名前空間が暗黙的に指定されている

:::note
どんな要素に対しても暗黙的にネームスペースが割り当てられるそうです。
つまり、要素は必ずどこか1つのネームスペース内に存在しているということになります。
:::

もしもネームスペースがない要素を作りたい場合は、
`document.createElementNS`名前空間パラメータに空の文字列を指定したメソッドを使用することで作成できるとのことです。

```javascript
const a = document.createElementNS('', 'a');
```

スタイルの適用についてMDNに記述されたサンプルコードで説明します。

```html
<p>This paragraph <a href="#">has a link</a>.</p>

<svg width="400" viewBox="0 0 400 20">
  <a href="#">
    <text x="0" y="15">Link created in SVG</text>
  </a>
</svg>
```

```css
/* svgとxhtmlに対してnamespaceを設定しています */
@namespace svgNamespace url("http://www.w3.org/2000/svg");
@namespace htmlNameSpace url("http://www.w3.org/1999/xhtml");

/* グローバルなセレクタ */
a {
  font-size: 1.4rem;
}

/*
  namespaceのないaタグに適用するスタイル
  今回はnamespaceのない要素は定義されていないのでどの要素にもスタイルは適用されません
*/
|a {
  text-decoration: wavy overline lime;
  font-weight: bold;
}

/* 全てのnamespaceのaタグに対してスタイルが適用されます */
*|a {
  color: red;
  fill: red;
  font-style: italic;
}

/* 下記2つは、先ほど定義したSVGのネームスペースに対してスタイルが適用されます */
svgNamespace|a {
  color: green;
  fill: green;
}

htmlNameSpace|a {
  text-decoration-line: line-through;
}
```

スタイルが適用された結果HTMLは下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/800c4e94-3837-2218-2b14-8f7aa960d971.png)

上記のCSSから分かる通り、namespaceを利用してスタイルを定義する場合CSSの[カスケード](https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance#%E3%82%AB%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%89)は適用されないようです。

もし適用されるなら、`svgNamespace|a`の後に定義した、`htmlNameSpace|a`はHTML全体に対してスタイルを適用するセレクタのはずなので、「Link created in SVG」にも取り消し戦が適用されるはずだからです。

https://developer.mozilla.org/en-US/docs/Web/CSS/Namespace_separator

## まとめ
改めてMDNなどのドキュメントに定義されているような用語は理解しておかないとドキュメントを読む際の障害になると感じました…。

全てを把握し切るのは難しくても頻度の高い単語はしっかり覚えていきたいと思います！