css hacks for IE11 [ & Edge ( EdgeHTML ) ]

##続編

[続編](https://qiita.com/feo52/items/b58de2c43e1ba7b10b2e)(?)を投稿しました。

##はじめに

2017年07月時点の内容であり、
2017年07月時点のhackです。
ご利用は自己責任の上でお願い致します。

##結論

素人の結論を先に記載しておきます。
( demoは[こちら](https://qiita.com/feo52/items/b58de2c43e1ba7b10b2e)より確認くださいませ )

```css
/* IE11 */ _:-ms-lang(x)::-ms-backdrop, .selector {}
/* Edge */ _:-ms-lang(x)::backdrop, .selector {}
```

<!--
[`demo`](http://bl.ocks.org/feo52/raw/0677da79114bc24d00cec9c4b018ac4b/)
[`code`](https://gist.github.com/feo52/0677da79114bc24d00cec9c4b018ac4b)
-->

##-ms-high-contrast & -ms-backdrop

```css
@media all and (-ms-high-contrast:none) {
	*::-ms-backdrop, .selector {
		color: blue;
	}
}
```

IE11の css hack を検索すると、検索結果の上部に出てくる上記のhackですが、
[当時はそういうもの](http://qiita.com/feo52/items/7d8176aa99989e9d05f6)、として、あまり深く考えていませんでした。
上記は二つの部位で構成されていますが、各々どういう役割でしょうか。

`@media all and (-ms-high-contrast:none) {}`
[`-ms-high-contrast`](https://msdn.microsoft.com/en-us/library/hh771830)のhackはIE10以上用のhackとして有名(?)でした。
なのでIE9以下を切る役割なのでしょう。

`*::-ms-backdrop, .selector {}`
では上記の役割は?

##-ms-backdrop

~~[MSDN](https://msdn.microsoft.com/en-us/library/dn312072)を見ると~~中段の表に以下が記載されていました。
( [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/::backdrop)に飛ばされてしまい、現在は見れません )

IE11未満は未実装
IE11はベンダープレフィックスが必要
Edgeはベンダープレフィックスが不要

んっ!?、なら以下だけでよくね?

```css
*::-ms-backdrop, .selector {}
```

IE11反応あり、Edge反応なし、Chrome反応なし、Firefox反応なし、Safari(iOS)反応なし。
(・∀・)ｲｲ!!

念の為、
IE11のドキュメントモードを変更して旧IEの反応も見ていきます。
IE10とIE9とIE8までは反応ないのですが、
IE7とIE5は、カンマの実装方法が違うのか、反応します。
(・Ａ・)ｲｸﾅｲ!!

##-ms-high-contrast & -ms-backdrop

つまり、
`@media all and (-ms-high-contrast:none) {}` => IE11,IE10
`*::-ms-backdrop, .selector {}` => IE11,IE7,IE5
これを同時に指定することで、IE11のみが反応する、という状態のようです。

##media queries & -ms-backdrop

しかし、
IE7以下が反応しなければよいわけですから、
`@media all and (-ms-high-contrast:none) {}`
の箇所は検討の余地がありそうです。

そもそも、
`-ms-high-contrast`どうこう以前に、
IEのメディアクエリの多くの実装はIE9からです。

IE7以下を切る役割であれば、
`@media all and (-ms-high-contrast:none) {}`
などとする必要はなく、
レスポンシブ時によくお世話になる、
`@media all and (min-width:hoge) {}`
`@media all and (man-width:hoge) {}`
などを利用すればよいだけなのかと...

```css
@media all and (min-width:0px) {
	*::-ms-backdrop, .selector {
		color: blue;
	}
}
```

##-ms-backdrop & root

ただ、出来れば、
`@media` や `@support` を使用せず、
ワンライナー的にいける方法が欲しいところです。

IE7以下が反応しないhackで、すぐ思い浮かぶのは :root hack です。
:root はIE8以下未実装なのでIE7,IE5は反応しません。
ただ、詳細度が変化してしまうのが玉にきずです。

```css
*::-ms-backdrop, :root .selector {}
```

##-ms-backdrop & -ms-lang

次に思い浮かんだのは、
IE10以上用hackである`_:-ms-lang(x),`の利用です。
これと組み合わせてみたところ、うまくいきました。
詳細度の変動もないはずです...

```css
*::-ms-backdrop, _:-ms-lang(x), .selector {}
```

ところで、
先頭の `*` や `_` とはなんでしょうか...

##asterisk

`*` は[全称セレクタ](https://developer.mozilla.org/ja/docs/Web/CSS/Universal_selectors)だと思いますが、
以下が`*::-ms-backdrop, `の自分なりの解釈です。

例えば、
`* { color: blue; }`
こうすると全要素の文字が青くなります。
`*::after { color: blue; }`
こうすると全要素の`::after`の疑似要素の文字が青くなります。
ということは、
`*::backdrop { color: blue; }`
こうすると全要素の`::backdrop`の疑似要素の文字が青くなります。
( `::backdrop`がどんな要素なのかは知りませんが... )
`*::-ms-backdrop { color: blue; }`
こうすると全要素の`::-ms-backdrop`の疑似要素の文字が青くなります。
( `::-ms-backdrop`が実装されたブラウザであるIE11のみ )

また、
`a, p { color: blue; }`
こうするとa要素とp要素の文字が青くなります。
`a::after, p { color: blue; }`
こうするとa要素の`::after`の疑似要素とp要素の文字が青くなります。
`*::after, p { color: blue; }`
こうすると全要素の`::after`の疑似要素とp要素の文字が青くなります。
この時、
`::after`の疑似要素は絶対使用しない、と、取り決めしたとします、その場合、
`*::after`部分に反応する要素は絶対ないので、
`*::after, p { color: blue; }` と `p { color: blue; }` は同じ効果になります。

では、
`*::-ms-backdrop, p { color: blue; }`
の場合はどうでしょうか。
`::-ms-backdrop`の疑似要素、使いますか?、使わないよね?、使わないなら、
`*::-ms-backdrop, p { color: blue; }` と `p { color: blue; }` は同じ効果だよね。
ということは、
`*::-ms-backdrop, .selector {}` と `.selector {}` は同じ効果だよね、と、なり、
その際、
他のモダンブラウザにとっては、
`-ms-backdrop`という未定義のキーワードがあるため、
`*::-ms-backdrop, .selector {}`
というスタイル規則(or規則セット)自体が無視され、
結果、`-ms-backdrop`が実装されているIE11だけが反応する、
と、いうことなのだろうと思われます。

つまり、
`*::-ms-backdrop, .selector {}`は、
`-ms-backdrop`の疑似要素を使用しない、
という暗黙の約束事の上に成り立っているhackなのではないかと。

##underscore

`_` とは何でしょうか。
正直はっきり分かりません...

[The W3C CSS Validation Service](https://jigsaw.w3.org/css-validator/)で、
`_ { color: blue; }`を検証してもエラーやワーニングは出ません。
なので _ を使用しては駄目ということはないようです。

次にW3Cの仕様書を探してみます。

[Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification](https://www.w3.org/TR/CSS2/)
[4 Syntax and basic data types](https://www.w3.org/TR/CSS2/syndata.html)
[4.1.2.1 Vendor-specific extensions](https://www.w3.org/TR/CSS2/syndata.html#vendor-keywords)
上記によると、
　　`-` と `_` を識別子の先頭に使用可能、
　　`-` と `_` で始まるキーワードやプロパティはベンダー固有の拡張用として予約、
　　`-` と `_` の予約は将来において保証、
ということのようです。

また、
[CSS Syntax Module Level 3](https://www.w3.org/TR/css-syntax-3/)
[10.7. Experimental implementations](https://www.w3.org/TR/css-syntax-3/#experimental)
CSS3にもCSS2.1の上記の予約の件が記載されています。

つまり、
`_` 一文字ではセレクタなどになることは将来的にもないし、
`_` 一文字でベンダープレフィックスとするブラウザも普通に考えればないでしょう。
なので、
`_` にマッチするものは一切ない、
ということなのだろうと思われます。

##underscore + -ms-backdrop & -ms-lang

ですので、素人判断ですが、
IE11の css hack は以下がよいのかな、と思う次第です。

```css
_::-ms-backdrop, _:-ms-lang(x), .selector {}
```

( hack的な意味合いで ) 短縮して以下は如何でしょうか。

```css
_:-ms-lang(x)::-ms-backdrop, .selector {}
```

##Edge ( EdgeHTML )

ちなみに、
IE11未満は未実装
IE11はベンダープレフィックスが必要
Edgeはベンダープレフィックスが不要
ですので、素人判断ですが、
Edgeの css hack は以下がよいのかな、と思う次第です。

```css
_:-ms-lang(x)::backdrop, .selector {}
```