一.LVHA
実際には LVFHA であるべきです。つまり:
a:link {/* 未訪問のハイパーリンクのスタイル */}
a:visited {/* 訪問済みのハイパーリンクのスタイル */}
a:focus {/* フォーカスを持つハイパーリンクのスタイル */}
a:hover {/* マウスホバー時のハイパーリンクのスタイル */}
a:active {/* ユーザー入力によってアクティブ化されたハイパーリンクのスタイル */}
これら 5 つはすべて擬似クラスで、5 つの状態を表します。その中で link と visited はハイパーリンク専用のもので、リンク擬似クラスに分類できます。一方、focus、hover、active はハイパーリンクだけでなく他の要素にも適用可能で、動的擬似クラスと呼ばれます
LVFHA 原則とは、ハイパーリンク(href 属性を持つ a タグ)に上記の 5 つの擬似クラスを適用する際、この固定された順序を守るべきだということです
二.擬似クラスと擬似要素
擬似クラスはクラスのように、DOM ツリー上に既に存在する特定の要素を選択するために使用されます。選択条件には 2 種類あります:
-
状態:要素が特定の状態にあるかどうか。例えば、ユーザーが訪問済み(
link/visited)、現在フォーカスを持っている(focus)、特定の言語環境にある(lang) -
構造:要素が DOM 構造に関する特定の要件を満たしているかどうか。例えば、長男である要素(
first-child)、CSS3 で追加されたルート要素である要素(root)や多数の構造的擬似クラス(nth-*、*-of-typeなど)
擬似要素は要素に近く、DOM ツリー上に存在しない要素(または要素の一部)を選択するために使用されます。擬似クラスの繁栄した大家族に比べると、擬似要素はやや寂しい存在です。現在(2017/11/4)まで、CSS3 仕様には依然として 4 つの擬似要素しかありません(CSS2.1 も 4 つでした):
-
最初の文字:要素に含まれるテキストコンテンツの最初の文字を選択します(テキストコンテンツには子要素からのものが含まれ、つまりタグ階層を越えてテキストを選択できます)
-
最初の行:要素に含まれるテキストコンテンツの最初の行を選択します(同上)
-
before:コンテンツ生成に使用され、指定された要素のコンテンツの先頭位置に要素を生成します(生成されたコンテンツは要素のコンテンツ領域内に位置します)
-
after:コンテンツ生成に使用され、指定された要素のコンテンツの末尾位置に要素を生成します(同上)
擬似クラスと擬似要素の最大の違いは、選択対象のコンテンツが DOM 上に存在するかどうかです。存在すれば擬似クラス、存在しなければ擬似要素に属します。別の角度から見ると、ドキュメントの一部のコンテンツにスタイルを指定したい場合、まず(セレクターを使用して)その部分のコンテンツを選択する必要があります。この時、2 つの状況に遭遇します:
-
対象のコンテンツがたまたまあるタグで囲まれている場合、このタグ全体にスタイルを設定すれば目的を達成できます
-
対象のコンテンツの前後に範囲を定めるタグがなく、直接スタイルを設定できない場合、対象のコンテンツを囲むために一時タグを挿入し、この一時タグにスタイルを設定する必要があります
最初の状況は擬似クラスで処理し、擬似クラスセレクターを使用して特定の状態または特定の構造的特徴を持つ既存の要素を見つけ出し、スタイルを適用します。2 番目の状況は、追加のタグを手動で挿入して最初の状況に変換するか(一部のシナリオではタグを追加しても実現できない場合があります。例えば、最初の行やタグ階層を越えたシナリオ)、擬似要素で解決します。これはブラウザに仮想タグを挿入して対象コンテンツを囲み、スタイルを適用するよう依頼するのと同等です
P.S. CSS3 セレクターの詳細については、CSS セレクター分類まとめ をご覧ください
三.a タグの 6 つの状態
LVFHA 擬似クラスはハイパーリンクに 5 つの状態を提供し、6 番目はアンカーポイントではなくハイパーリンクを指します
link 擬似クラスが存在する意義の一つは、ハイパーリンクとアンカーポイントを区別することです。link 擬似クラスは href を持つ a タグ(つまりハイパーリンク)のみをマッチ���グし、アンカーポイントはマッチングしません
一般的なデスクトップブラウザ環境では、a タグの 6 つの状態と対応するトリガー動作はそれぞれ以下の通りです:
a {/* 任意の状態の a タグ、ハイパーリンクかアンカーポイントかを問わない */}
a:link {/* 未訪問のハイパーリンク */}
a:visited {/* 訪問済みのハイパーリンク、ハイパーリンクをクリックして現在のページに戻ると、このハイパーリンクは visited 状態になります */}
a:focus {/* フォーカスを取得したハイパーリンク、tab キーでハイパーリンクを選択するか、ハイパーリンクを長押ししてマウスを移動 */}
a:hover {/* マウスホバー時のハイパーリンク、マウスがハイパーリンクを通過するかハイパーリンク上にホバーすると、このハイパーリンクは hover 状態になります */}
a:active {/* アクティブ状態のハイパーリンク、マウスがハイパーリンク上で押下された時 */}
その中で focus, hover, active は区別が難しく、focus は継続的な状態であり、hover, active は短時間の状態です。さらに hover, active を細分化すると、後者は前者の特殊な状態です(タッチデバイスを除く)。例えば:
a:focus {border: 1px solid green;}
a:hover {border-color: red;}
a:active {border-style: dashed;}
那么、以下の連続操作に対応する状態とスタイルはそれぞれ:
tab キーを押下 -> focus -> 緑色の実線ボーダー
他の空白部分をクリック -> a & link | visited -> 対応するスタイル
マウスが通過した時 -> hover -> ボーダーなし
マウスがホバーした時 -> hover -> ボーダーなし
マウスを押下 -> focus & hover & active -> 赤色の点線ボーダー
マウスをハイパーリンクの外に移動して離す -> focus -> 緑色の実線ボーダー
(他の場所をクリックしない場合、ハイパーリンクは常に focus 状態のままです)
マウスが通過した時 -> focus & hover -> 赤色の実線ボーダー
focus が継続的な状態であるため、短時間の hover, active の前に配置する必要があります。そうしないと、最後にマウスが通過した時に hover スタイルが表現されません(カスケード規則により、先に宣言された hover が focus に上書きされるため)
focus, hover, active の 3 つの状態には重複があるため、特定の宣言順序を維持して、カスケード結果がスタイルシート作成者の期待に合致することをお勧めします。一方、link と visited は相互排他的で、重複が存在しないため、二つの相対的な順序は重要ではありません(VLFAH も合理的で、「愛憎」順序は覚えやすいだけです)。同様に、link/visited は永続的な状態であるため、短時間の状態と永続的な状態に表現の機会を与えるために、focus/hover/active を後に配置し、長状態のカスケード優先度を低くするため、LVFHA 原則が生まれました
さらに、仕様書は focus, hover, active に対応する状態の開始および終了条件を明確に説明していません:
CSS はどの要素が上記の状態になり得るか、およびこれらの状態にどのように入り退出するかを定義していません。スクリプトは要素がユーザーイベントに応答するかどうかを変更でき、異なるデバイスと UA は要素を指し示しアクティブ化する方法が異なります
CSS 2.1 は、':active' または ':hover' 要素の親もこの状態にあるかどうかを定義していません
(5.11.3 動的擬似クラス::hover、:active と:focus より抜粋)
したがって、動的擬似クラスのトリガー動作を確定することも、これらの擬似クラスがどの要素に適用されるかを確定することもできません(フォーム要素、div などはサポートする場合もあればサポートしない場合もあります)。すべてユーザーエージェントの実装に依存します
四.組み合わせ擬似クラス
LVFHA 順序に従うことをお勧めするのはカスケード規則を考慮したもので、そうでないと上書きされて同名の規則が無効になる可能性があります。例えば:
a:hover {text-decoration: underline overline;}
a:link {text-decoration: none;}
a:visited {text-decoration: none;}
hover スタイル(小技巧:マウスが通過した時に上線と下線を同時に表示)は永遠に有効になりません。text-decoration プロパティが常に以下の 2 つのいずれかに上書きされるためです
もちろん、前提条件はスタイル規則に競合が存在する場合(同名のプロパティで、ソース、重要性、特殊性がすべて同じ)で、宣言順序によって競合を解決します。この時初めて LVFHA 順序が実際に機能します。言い換えれば、スタイル競合が存在しない場合、宣言順序は重要ではありません
つまり、他の方法でスタイル競合の発生を回避すれば、LVFHA 順序に従う必要はありません。例えば、組み合わせ擬似クラスを使用して状態を展開する:
/* 順序を要求しない */
:link
:visited
:link:hover
:visited:hover
/* 順序を要求する 上記 2 行の後 */
:link:active
:visited:active
/* または上記 2 行を置き換える 順序を要求しない */
:link:hover:active
:visited:hover:active
展開すると重複状態がなくなり、各規則を厳密に相互排他的に変えるため、自然と競合がなくなります
P.S. 注意:IE6-は組み合わせ擬似クラスを正しく処理できず、最後のみを認識するため、LVHA がより広く適用されています(実際には組み合わせ擬似クラスのセマンティクスがより明確で、「隠れた奇妙な規則」がありません)
さらに、カスケード規則を使用して特殊効果を実現できます。例えば:
// lhva を使用して、未訪問のリンクのみが hover 効果を持つようにする
a:link {}
a:hover {}
a:visited {}
a:active {}
非常に興味深い小技巧で、これと同等です:
a:link:hover {}
これは組み合わせ擬似クラスのセマンティクスが明確という利点を体現しています
コメントはまだありません