お疲れ。最近、デザインカンプ通りに組んだはずなのに「リンクの色が変わらない」「なんか挙動が怪しい」って頭を抱えていないか?
中級の壁をスルッと抜けてシニアに近づくエンジニアがつまずきがちなポイント、それが今回取り上げる `:visited` 疑似クラス だ。
「いやいや、`.nav-link:visited { color: purple; }`って書くだけっしょ?」と思ったそこの君。甘い。実務の世界はそんなに優しくない。ブラウザのセキュリティ(プライバシー保護)という厳格な壁と、CSSの書き順(LVHAの法則)の呪縛を理解していないと、痛い目を見る。
今日は、現場のリアルな泥臭い知見も含めて、`:visited` の裏側と正しい扱い方を徹底的に叩き込んでやるから、しっかりついてきな。
—
なぜ `:visited` は嫌われるのか?(ブラウザの裏側とプライバシー保護)
まず、大前提として知っておかなきゃいけないのが、セキュリティ上の制限(History Sniffing対策)だ。
昔のブラウザでは、CSSの `window.getComputedStyle` や JavaScript を悪用して、ユーザーが「どのサイト(URL)にアクセスした履歴があるか」を完全に特定する攻撃(History Sniffing)が横行していた。例えば、競合他社のサービスや特定の機密性の高いページにアクセスしているかどうかを、リンクの色を判定することでハッカーが盗み見できてしまったわけだ。
これを防ぐために、現代のモダンブラウザは `:visited` で変更できるプロパティを極限まで制限している。
変更が許可されているのは、基本的に以下のプロパティくらいだ。
- `color`
- `background-color`(※ブラウザによっては制限あり、基本はcolor推奨)
- `border-color` などの色に関するプロパティの一部
- `outline-color`
- 描画に使う `fill` や `stroke`(SVG用)
逆に言うと、`font-size`、`width`、`height`、`padding`、`margin`、そして最も重要な `opacity` や `visibility` などのレイアウトや透明度に関わるプロパティは、すべて書き換えても完全に無視される。
「訪問済みリンクだけ文字サイズをデカくして目立たせよう」なんてコードを書いても、ブラウザのセキュリティエンジンに冷たくスルーされるだけだから覚えておこう。
—
現場で絶対ハマる「記述順序(LVHAの法則)」の罠
CSSを書いていて「あれ? `:hover` が効かない」「`:visited` が上書きされちゃう」って現象にぶつかったことはないか? これ、原因の9割はセレクタの記述順序にある。
CSSの「カスケード(上書き)」の原則を思い出してほしい。詳細度が同じであれば、後に書いたルールが勝つ。
ここに、状態系疑似クラスの鉄の掟である LVHAの法則 が生まれる。
1. Link (`:link`)
2. Visited (`:visited`)
3. Hover (`:hover`)
4. Active (`:active`)
呪文のように「LoVe HAte(ラヴ・ヘイト)」と覚えておくと忘れにくい。
もし `:hover` を `:visited` の前に書いてしまったらどうなるか?
ユーザーが「訪問済みのリンク」にマウスホバーしたとき、`:visited` が後に記述されていると、ホバーしているにもかかわらず `:visited` のスタイルが勝ってしまい、ホバー時のスタイル(色変化など)が消えてしまうのだ。
実務では、以下のような順序で記述するのがプロの基本作法だ。
/ 1. まずベースのリンクと未訪問状態 /
.link {
color: #0066cc;
}
/ 2. 訪問済み /
.link:visited {
color: #551a8b; / 一般的なパープル系 /
}
/ 3. ホバー(訪問済みであっても、マウスを乗せたら色を変えたいはず) /
.link:hover {
color: #004080;
}
/ 4. アクティブ(クリック瞬間) /
.link:active {
color: #ff3300;
}
この順番を間違えるだけで、UX(ユーザー体験)がガタガタになる。デザインレビューで「あれ、ホバーしても色が変わらないんですけど?」って突っ込まれる前に、ここをビシッと合わせておこう。
—
コピペで使える!実践的なスタイリングパターン
百聞は一見に如かずだ。実務のプロダクトでそのまま使える、洗練されたリンクコンポーネントのサンプルコードを置いておく。
背景色やアイコン制御の工夫など、現場で「こう書くと綺麗にまとまるよね」という知見を詰め込んである。
最新のフロントエンドトレンドについては、
こちらの技術ブログ記事
を参考にしてください。また、公式ドキュメントは
こちらから確認できます。
/ ==========================================
リンクコンポーネントのベストプラクティス
========================================== /
.site-link {
/ トランジションを滑らかに効かせる /
color: var(–color-link, #2563eb);
text-decoration: underline;
text-underline-offset: 3px;
transition: color 0.2s ease, text-decoration-color 0.2s ease;
}
/ 未訪問・基本の状態 /
.site-link:link {
color: #2563eb;
}
/ 訪問済み状態
※プライバシー保護のため、色(color)の変更に留めるのが鉄則
/
.site-link:visited {
color: #7c3aed; / 訪問済みは少し落ち着いたパープルに /
}
/ ホバー時(LVHAの法則に従い、必ず:visitedの後に記述) /
.site-link:hover {
color: #1d4ed8;
text-decoration-color: #1d4ed8;
}
/ フォーカスのアクセシビリティ担保 /
.site-link:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
background-color: #dbeafe;
}
/ アクティブ時 /
.site-link:active {
color: #1e40af;
}
チーフアーキテクトからのワンポイント・アドバイス
最近のデザインでは「訪問済みリンクの色を変えたくない」という要望がデザイナーから飛んでくることがよくある。「全部青文字で統一したいんだよ」ってパターンだ。
その場合は、無理にハックを使わず、あえて `:visited` にもベースと同じカラーを明示的に指定して、ブラウザのデフォルトのパープル系上書きを打ち消すのが実務の定石だ。
/ 訪問済みであっても色を変えたくない(統一感を重視する)場合の書き方 /
.site-link:link,
.site-link:visited {
color: #2563eb;
}
これをしておかないと、ユーザーのブラウザの閲覧履歴によって、サイトのデザインが勝手にまだら模様になってしまう。「デザイナーの意図したブランドカラーを守る」という意味でも、この明示的なリセットは覚えておいて損はないテクニックだ。
—
まとめ
`:visited` は、ただの色を変えるだけの地味な疑似クラスに見えて、実はブラウザのセキュリティ仕様やCSSのカスケード構造が複雑に絡み合う、エンジニアの腕の見せ所だ。
1. 動かせるプロパティは制限されている(色系以外は無視される)
2. LVHAの順番(Link, Visited, Hover, Active)を絶対に守る
3. デザインの要件に合わせて、訪問済みの色を制御(あるいは意図的に統一)する
この3つを押さえておけば、もう `:visited` 周りで変なバグを踏むことはないはずだ。
現場で後輩が「リンクの色が変わらないんです〜」と泣きついてきたら、今日の話をドヤ顔で教えてやってくれ。頼れるシニアとしての株が上がるはずだぜ。それじゃ、またコードの海で会おう。

コメント