HTML の属性値を囲むのはシングルクォートでもダブルクォートでも良い
HTML の属性値というと、大抵はダブルクォートで囲む。
<button type="submit">送信</button>
しかし、HTML5 の仕様上は、シングルクォートで囲んでも誤りではない。
<!-- コレでも OK -->
<button type='submit'>送信</button>
最新の HTML5 の仕様書でいうと、以下で OK と明記されている。
- HTML Standard 日本語訳
-
単一引用符属性値構文
-
<!-- 構文で使われない文字しか扱わないのであれば、引用符で囲まなくても OK -->
<button type=submit>送信</button>
HTML4.01 の仕様書でも OK だったので、HTML は歴代、シングルクォートでもダブルクォートでもどっちでも仕様上は OK だったっぽい。
引用符を使う理由
引用符を使わない場合、クロスサイトスクリプティング (XSS) 脆弱性のリスクが高くなるからと推測。
例えば、ユーザの入力値を基に、JavaScript で HTML を構築して出力するような場合が分かりやすい。
// 変数 userInput はユーザからの入力値の想定
// value 属性に引用符がない
const outputHtml = '<input type="text" value=' + userInput + '>';
↓ユーザの入力値によっては、こんな HTML が生成できてしまうかもしれない。
<input type="text" value=DUMMY onmouseover="location.href = 'https://bad-website.example.com/';">
もちろん、このレベルの XSS は引用符記号を書いていても発生するのだが、引用符記号を意識していない程度の開発者は色々とやらかしやすいことに繋がると思う。
どうしてダブルクォートが主流なのか考察する
じゃあ、どうしてシングルクォートではなくダブルクォートがより多く見かける主流なのか。
一番想像しやすい簡単な答えは、英文中で「アポストロフィ」としてシングルクォート文字を使う機会が多いからだと思われる。
<!-- こういう文章を書きやすい -->
<input type="text" value="I'm a student.">
他のプログラミング言語と引用符
ところで、C 言語や Java 言語なんかでは
- シングルクォートで囲むと文字リテラル (Character 型)
- ダブルクォートで囲むと文字列リテラル (String 型)
といった仕様がある。
コレは、「文字列 (文章)」の中ではシングルクォートをよく使うだろうから、という理由で、扱いやすい記号を採用したのだと推測できる。
そして HTML の仕様を設計していく際も、こうした先発言語に倣って、驚き最小の原則でダブルクォートがより推奨されるようになったのかなと思われる。
他には、Bash やら Perl やら、いくつかの言語で
- シングルクォートで囲めば変数展開しない
- ダブルクォートで囲むと変数展開する
といった仕様があったりする。
コレは個人的にイマイチしっくりきていない。変数展開されないリテラルの方が、安全ではなかろうか?安全な構文をより使いやすいモノにしておいた方が堅牢なのでは?そう思うと、「変数展開されない方式がダブルクォート」である方が、良いような気がしてしまう。でも実際は逆だ。
なぜ最初に「シングルクォートは変数展開しない文字列」と定義されたのか、色々調べてみたが、それらしい理由や哲学が見つけられなかった。あまり「余計な変数展開がされないように安全に書こう!」みたいな意識がなかったのかしら?誰かご存知だったら教えてください。
そういえば、SQL だとシングルクォートはエスケープしないと書けなかったかな。CSV でデリミタ (区切り文字) と区別を付ける際はダブルクォートが使われる。それぞれにそれなりに設計意図があったとは思うのだが、当時の設計意図が明記されている言語はほとんど見当たらない。
他言語との違和感を少なく・調和するように設計した?
まず、英語という言語に対して「英文中にシングルクォートがよく出てくる」という事実があり、続いて C 言語などが「ダブルクォートで文字列を表現しましょう」と設計された。
Bash や Perl における変数展開の扱い方の経緯はよく分からないが、とりあえず C 言語系と同じように読めることを考えると、HTML でも「ダブルクォートで属性値を囲む」と推奨した方が自然だと考えたのだろう。
そのためか、HTML においてダブルクォートは "
という文字実体参照が定義されているが、シングルクォートは '
という数値文字参照しかない (XML では '
という文字実体参照を追加しようという動きが一時期あったらしいが、一般的な仕様には広まらずじまい)。
- 基本はダブルクォートで囲むから、シングルクォートはエスケープしなくて良い (エスケープ手法をあえて用意しなくても良い) だろう
- ダブルクォートを書きたくなったらエスケープすることになるだろうから、書きやすいように
"
を用意してやろうか - まぁシングルクォートで属性値を囲んでも、機能的にはダブルクォートと同じってことで仕様化しておくとするか
という流れなのかなと推測される。
JavaScript との親和性
過去記事にも書いたが、HTML 側でダブルクォートが標準的に使われるのだとしたら、HTML と混ざりやすい JavaScript では、区切り文字が衝突しないようにシングルクォートを多用することにするか、という流れが、近年の JS 界隈でシングルクォートが推奨される理由だと思われる。
考察以上
日本人にはイマイチ感覚のないことかもしれないが、やはり
- 英文中でシングルクォートを普通に使うから、言語の構文としての積極利用は避ける
ということなのかなと思う。それと合わせて、
- 他のプログラミング言語でも同じように考えたのか、ダブルクォートを使う実績があるから、それに倣った
という補強材料もあったのかなーと考えた。
- HTML と連携しやすい JS は、そうした HTML の推奨事項に合わせる形でシングルクォート派が主流になってきた
というのは、後から生まれた影響であろう。
US キーボードは、文章中でシングルクォートを多用するから、Shift キーなしでシングルクォートが入力できる、と考えるとコレもしっくりくる。
- HTMLの属性値はなんでダブルクォートで囲むことが推奨されているのか考えてみた - yukata
- JavaScriptの関数へ「'」はエスケープしないと引数として渡せない? - 小池啓仁 ヒロヒト応援ブログ By はてな
- 区切り文字 - Wikipedia