🙀
cssの頭に付いている「.」や「#」の処理方法について調べてみた。
色々調べた結果、「.」や「#」があることで
処理高速化の工夫がなされている
というのがよくわかりました。
そもそもcssの頭に付いている「.」は何?
HTMLの要素に付与されたclass属性を指定するため記号で、
クラスセレクタと呼ばれるものです。
使用方法
.クラス名 {
プロパティ: 値;
}
例
/* 青色のテキスト */
.blue-text {
color: blue;
}
/* 複数のクラスを組み合わせる */
.large.bold {
font-size: 20px;
font-weight: bold;
}
HTML側での使用
<p class="blue-text">青い文字</p>
<div class="large bold">大きな太字</div>
特徴
- ドット(.)で始まる
- 複数の要素で再利用可能
- 1つの要素に複数のクラスを適用可能
- IDセレクタ(#)より詳細度が低い
その他のセレクタ
- 要素セレクタ:
div { }
- IDセレクタ:
#header { }
- 属性セレクタ:
[type="text"] { }
- 擬似クラス:
a:hover { }
- 擬似要素:
p::before { }
使用例
<div id="header">ヘッダー</div>
<p class="text">段落</p>
<input type="text" name="username">
<a href="#">リンク</a>
/* 要素セレクタ */
div {
background: gray;
}
/* IDセレクタ */
#header {
font-size: 24px;
}
/* クラスセレクタ */
.text {
color: blue;
}
/* 属性セレクタ */
[type="text"] {
border: 1px solid black;
}
/* 擬似クラス */
a:hover {
color: red;
}
/* 擬似要素 */
p::before {
content: "▶";
}
クラスセレクタ(.)は一般的に使用される方法の一つですが、これらの他の方法と組み合わせることで、より細かいスタイル制御が可能です。
実際のソースを見てみた
実際のWebブラウザにも使われている
CSS処理用のエンジンWebKit
のソースを見てみました。
WebKitをGitHubからクローン
- Ctrl+Shift+P を押してコマンドパレットを開く
- "Git: Clone" と入力し、出てきた「Git:クローン」を選択
- リポジトリURLを入力: https://github.com/WebKit/WebKit
- クローン先のローカルフォルダ選択画面が出るので、好きな場所を選択する
- 「複製したリポジトリを開きますか?または現在のワークスペースに追加しますか?」と表示されるので、「開く」を選択
「.」のパース処理を探す
GitHub Copilotの助けを借りながら探しました。
以下のようなJavaScriptで処理をしているようです。
JavaScript
var matchExpr = {
"ID": new RegExp( "^#(" + identifier + ")" ),
"CLASS": new RegExp( "^\\.(" + identifier + ")" ), // ここでクラスセレクタのドットを検索しています
"TAG": new RegExp( "^(" + identifier + "|[*])" ),
"ATTR": new RegExp( "^" + attributes ),
"PSEUDO": new RegExp( "^" + pseudos ),
"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
};
処理の概要
-
ID
とCLASS
- 最も一般的で高速なセレクタが先頭に来ています-
ID
:#my-id
のような ID セレクタ -
CLASS
:.my-class
のようなクラスセレクタ
-
-
NAME
,TAG
- 次によく使われる基本的なセレクタ-
NAME
:[name='value']
のような name 属性セレクタ -
TAG
:div
やspan
のようなタグセレクタ
-
-
より複雑なセレクタ
-
ATTR
: 一般的な属性セレクタ -
PSEUDO
::hover
などの擬似クラス -
POS
: 位置関連のセレクタ -
CHILD
::first-child
などの子要素セレクタ
-
-
特殊用途
-
needsContext
:.is()
メソッド実装用の特殊パターン
-
この順序の2つの主な理由
-
パフォーマンス最適化:
- より単純で高速なセレクタ(ID、クラス)を先に配置
- より複雑で処理の重いセレクタを後ろに配置
-
依存関係の管理:
- より基本的なパターンを先に定義し、それらを基にして複雑なパターンを構築
この構造により、セレクタのマッチング処理を効率的に行うことができます。
おしまいに
ドットのことを調べすぎて
どっと疲れたワニかず@40歳 出戻りエンジニアでした。
Discussion