JavaScriptで今まで気になってたことです。
要素の id / class などのセレクタのエスケープ
僕自身も理解をしていなかったので、
どうしてか動かずに困惑する場面もあります。
そこでJavaScriptのセレクタのエスケープ方法、
この具体的な方法とコード例なんかをまとめました。
このページの目次
要素のid・クラスにはどんな文字でも使えるが…
初めにHTML上でのid/classの制限について
実は使用可能文字に制限はありません。
▼ こんな要素も普通に作れる
1 2 3 4 5 6 7 8 9 10 11 |
<!-- 数字から始まるID --> <div id="123"></div> <!-- 数字から始まるクラス --> <div class="item 123"></div> <!-- 非ASCII文字のID --> <div id="あいうえお"></div> <!-- 非ASCII文字のクラス --> <div class="アイテム 123"></div> |
要素のid・classの値は数字から始められるし、なんなら日本語とか使っても問題ありません。構文上はどんな文字でも使えるんですよね。
違和感があるけどなんの問題もないです。
ただし「HTML上では」という条件がつきます。
数字から始まるセレクタはJSから参照できない
ところがJavaScript上ではセレクタに制限があります。
- セレクタの先頭は数字から始められない
- セレクタに特殊文字は含められない
- もし使いたいならエスケープが必要
すこし具体的な例で考えてみます。
例えばこんな要素を定義したとしましょう。
▼ 数字から始まるクラスを含む要素
1 2 3 |
<div class="item 123"> Item No.123 </div> |
▼ これをJavaScriptコードから参照
1 2 3 |
const $item = document.querySelector( '.item.123' /// <= 問題なさそうだが… ); |
▼ DOMExceptionエラーが発生!
1 |
Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '.item.123' is not a valid selector. at <anonymous>:1:25 |
※ 数字から始まるIDでも同様
アイテムを表示するとき、要素にそのIDを紐づけたいみたいな場面。HTML上では問題ないけど、JSコードからそのままセレクタできません。
だからエスケープという工夫が必要です。
セレクタはCSS.escape()でエスケープできる
便利なメソッドが用意されてます。
その名も CSS.escape() というメソッド
名前の通り、セレクタをエスケープできます。
▼ CSS.escape() - Web APIs | MDN
The CSS.escape() static method returns a string containing the escaped string passed as parameter, mostly for use as part of a CSS selector.
引用元 : https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape
セレクタ文字列を渡すことにより、エスケープが必要な文字(数字・特殊文字・記号)をバックスラッシュ(\)でエスケープしてくれます。
以下はエスケープの例です。
- user.name ⇒ user\.name
- ()[]{} ⇒ \(\)\[\]\{\}
- 1234567890 ⇒ \31 234567890
記号とかは前にバックスラッシュが付くだけ
混乱するのは数字の場合ですね。
数字のエスケープでは \31 のようにASCIIコードとしてエスケープします。例えば '1' のasciiコードは16進数で0x30になるので \31 という表現になるわけです。
数字の場合はこのルールが適用されます。
具体的なCSS.escape()の使用コード例
ということで具体的に使ってみます。
▼ このような要素があるとする
1 2 3 |
<div class="item 123"> Item No.123 </div> |
▼ セレクタをエスケープして要素取得
1 2 3 |
const $item = document.querySelector( '.item.' + CSS.escape('123') ); |
今度はDOMExceptionなく正常に取得できました。
ブラウザごとのCSS.escape()の対応状況
少し気になるのがブラウザの対応状況です。
▼ 詳しくは Can i use... をチェック
現時点で95%をカバーしてるので問題ないですね。
ただし例のごとくIEは対応してません、
以上、JavaScriptでセレクタのエスケープでした。ではまた
CSSではセレクタを \ でエスケープ可能
ちなみにCSSでのセレクタエスケープについて。
同様にバックスラッシュでエスケープ可能です。
▼ こんな感じでエスケープできる
1 2 3 4 5 6 7 |
/** * 以下は .item.123 のエスケープ * ルールは CSS.escape() とおなじ **/ .item.\31 23{ background: red; } |
規則は CSS.escape() と全く同じです。
ただ記述が特殊すぎて使うことは少なそう。