質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.81%

擬似クラス「:link」の挙動

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,439

te2ji

score 22210

擬似クラス「:link」の需要についた回答が少し気になったので、調べていたのですが理解出来ない挙動があったので教えてください。

:link の挙動に関して、以下の記述があります。

:link - MDN
CSS の :link 疑似クラスは、まだ訪問されていない要素を表します。 <a>, <area>, <link> など、 href 属性を持つ未訪問のすべての要素を選択します。

質問

同ページに以下の例があります。
なぜ、訪問後の link の background-color が gold になるのでしょうか?

<a href="#ordinary-target">これは普通のリンクです。</a><br>
<a href="">このリンクを訪問しました。</a><br>
<a>リンクのプレイスホルダー(スタイルの適用なし)</a>
a:link {
  background-color: gold;
  color: green;
}


![イメージ説明

例の説明としては以下が記述されています。

既定では、大半のブラウザーが訪問済みのリンクに特殊な color の値を適用しています。そのため、この例のリンクは訪問前でしか特殊な文字色にならないでしょう(よって、再度確認するにはブラウザーの履歴をクリアする必要があるでしょう)。しかし、 background-color の値は大半のブラウザーが既定で訪問済みのリンクに設定していないので残るでしょう。

:link 疑似クラスは、まだ訪問されていない要素への設定だと思うのですが、説明を素直に読むと、:link が訪問後のリンクの装飾にも影響を及ぼしています。

CSS :link の値 < ブラウザの既定値 < CSS :visited の値
の優先順位のようです。

ブラウザの挙動としては想定どおりみたいですが、どういった原理に則っているのでしょうか?

よろしくお願いいたします。

おかしな挙動の追記

*確認した環境は、「firefox 66.0.3」+「codepen」です。

本件の挙動確認をしていたのですが、a:link でbackground-colorを設定しない場合、a:visited のbackground-colorが反映されませんでした。
MDN にある「上書き~」な記述はこれのことなんですかね?
にしては、colorは反映されていて、意味がわからんのですけど。

a:link {
  background-color: gold;
  color: green;
}

a:visited {
  background-color: black;
  color: red;
}


イメージ説明

a:visited {
  background-color: black;
  color: red;
}


イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • think49

    2019/04/21 22:06

    初心者マークが付いていますが、te2jiさんは初心者ではないとずっと思っていました…。

    キャンセル

  • te2ji

    2019/04/22 09:10

    質問作るときにだれに回答してもらうか想定して作るんですけど、そのうちの一人が初心者マークあったほうが見てくれるだろうと判断してつけました。ちなみに CSS はよく分かっていない初心者ですw

    キャンセル

回答 4

+5

:link, :visited の定義順

昔からある注意事項ですが、「:link:visited は順番を意識して定義しなければ、期待通りの表示にならない」という決まり事がありました。

大抵のサイトでは、状態が上書きされるので順番を守ろうというものです。
改めて考えてみると、これはおかしな話で「未訪問」「訪問済」の状態は排他的なので、本来はどちらを先にしようとも上書きされないはずです。

仕様

スタイルシート作者が 利用者の同意なしに利用者が訪問済みのサイトを調べる目的に, :link / :visited 疑似クラスを濫用することも可能なので、 UA は,リンクを 訪問済みか未訪問かに応じて異なるように具現化しつつ,利用者のプライバシーを守るために、すべてのリンクを未訪問のリンクとして扱うなど, 他の措置を実装してもよい。
【 例えば 多くのブラウザでは、 :visited に適用し得るスタイルは,レイアウトも含め,他のどの状態にも影響しないもの(ほぼ色のみ)に限られている (参考)。 】

というわけで、すべてのリンクを未訪問のリンクとして扱うが機能している可能性があります。
このロジックなら、

a:link {}
a:visited {}

の順番で記述しないと期待通りに動作せず、逆順定義で a:link が a:visited を上書きする挙動になります。

MDN

MDNに気になる一文があります。

既定では、大半のブラウザーが訪問済みのリンクに特殊な color の値を適用しています。そのため、この例のリンクは訪問前でしか特殊な文字色にならないでしょう(よって、再度確認するにはブラウザーの履歴をクリアする必要があるでしょう)。しかし、 background-color の値は大半のブラウザーが既定で訪問済みのリンクに設定していないので残るでしょう。

これはWebブラウザが有するデフォルトスタイルシートで a:visited が指定されていた場合、製作者スタイルシートの a:link 宣言よりも優先させる事を表していると思われます。
しかし、CSS仕様におけるカスケ―ド規則では優先順位が逆で、制作者スタイルシートはデフォルトスタイルシートよりも優先されます(詳細は下記仕様および過去ログを参照して下さい)。

検証

Google Chrome 73.0.3683.103で下記HTMLを開いて検証しました。

<style>
a:link {
  background-color: gold;
  color: green;
}
</style>
</head>
<body>
<a href="#ordinary-target">これは普通のリンクです。</a><br>
<a href="">このリンクを訪問しました。</a><br>
<a>リンクのプレイスホルダー(スタイルの適用なし)</a>

<a href="">このリンクを訪問しました。</a> の訪問済みリンクに対して、Google Chrome Developper Toolsの [Styles] タブでは、下記の制作者スタイルシートを全て有効と判定しました。

a:link {
  background-color: gold;
  color: green;
}

しかし、実際にはGoogle Chromeの内部で設定された訪問済みリンク色で出力されました。
(このスタイルは開発者ツールに表示されませんでした)

結論としては、次の挙動になっていると想定出来ます。

  • a:link は a:visited を包含する(未訪問+訪問済の状態を表し、全てのリンクを表す)
  • カスケード法処理完了後、独立した訪問済みスタイル上書き処理が走っており、制作者スタイルシートで a:visited で宣言されなかったプロパティはWebブラウザが内蔵する訪問済みスタイル(デフォルトスタイルシート)に上書きされる

おかしな挙動の追記

本件の挙動確認をしていたのですが、a:link でbackground-colorを設定しない場合、a:visited のbackground-colorが反映されませんでした。
...(中略)...

a:visited {
  background-color: black;
  color: red;
}

Google Chrome 73.0.3683.103で再現する事を確認しました。
開発者ツールの [Styles] タブで background-color: black; は有効な状態でしたが、実際の描画には反映されていません。
前述の「検証」節で仮定した動作に照らし合わせると、下記の仮説を立てることが出来ます。

  • 「カスケード処理」では有効
  • カスケード処理後の「訪問済みスタイル上書き処理」で background-color: black; が無効化されている

仕様上の「利用者のプライバシー云々」は、background-image を併用する事でブラウザ履歴を盗み取れる事実が露見した事を受けての規定と記憶しています。

ここで background 全体を封印する修正が加えられたなら、一応、辻褄は合います。
(background-image と background: url() だけを封印すればいいはずなので、個人的にはどうかと思いますが…)

Re: te2ji さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/22 21:41

    親記事に追記しました。 >おかしな挙動の追記

    キャンセル

  • 2019/04/22 21:44

    仮説は立てましたが、仕様ではなく、実装の問題のようなので、FirefoxやChroniumuのソースコードを読まない事には確かな事はいえないと思います。
    しかし、私には読めません。

    キャンセル

  • 2019/04/22 22:33

    ご確認ありがとうございました!
    仮説、大変興味深く読みました。

    私は Firefox で確認しましたが、Firefox の開発ツール上では「a:link」のみが表示され、「a:visited」は登場しませんでした。
    が、表示は「a:visited」の物となっていたので、結果としては、多分同じ挙動になっているのだと思います。

    > background 全体を封印する修正が加えられたなら

    こちらは、「a:link」に「background-color」があると「a:visited」も反映されるので、封印されているのとは少し違う挙動な気がします。

    私もソースコードは読めないので、もう少し資料を漁ってみますが。。。カオスですねw

    キャンセル

+1

リンク先の質問に回答した者です。ベストアンサーではありませんが、もし私の回答を見てのことであればすみません。
質問者様が参考になさったMDNの解説の以下の部分ではないでしょうか。

少なくとも同等の仕様を持つリンク関連の疑似クラス (:active、:hover、 :visited)によって上書きされます。

上書きということは、:linkで定義した内容が保持されるということだと思います。
W3CによるCSSの仕様書には、擬似クラス:linkと:visitedは相互排他的であると書いてあるので、こんな挙動があるとは知りませんでした(^^;)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/22 09:20

    回答ありがとうございます。

    ta1g3n さんの回答がトリガーの一つです。
    *実は以前から少し気になっていて、質問に記述した「擬似クラス「:link」の需要」を見に行ったときに、検証と違う回答があったので質問しました。

    自身でも少し検証したのですが、頂いた回答とも違う動きをするようです。。。
    後ほど、質問に追記するので、お時間のあるときに見ていただけると幸いです。

    キャンセル

+1

文章として雑で申し訳ないですが、回答を作りました。

考察(結論)

リンクはすべて:linkとして処理された後で、ブラウザで:visitedを追加(上書き)で処理していると考えられる。さらに厄介なことに、「:visitedとは」にあるように「no color or be transparent」であるものは、:visitedで設定しても反映されない。反映させたければ、「a, a:link, a:any-link」のどれかで適当な設定を行った後、:visitedを記述する必要がある。

本回答は、検証から実装を推測したものです。
根拠ドキュメントや実装に関して補足していただけると大変助かります

以下、考察に至った経緯

:link とは

:link :visited

All a elements that have an href attribute, all area elements that have an href attribute, and all link elements that have an href attribute, must match one of :link and :visited.
Other specifications might apply more specific rules regarding how these elements are to match these pseudo-classes, to mitigate some privacy concerns that apply with straightforward implementations of this requirement.

:visited とは

:visited

Properties that would otherwise have no color or be transparent cannot be modified with :visited. Of the properties that can be set with this pseudo-class, your browser probably has a default value for color and column-rule-color only. Thus, if you want to modify the other properties, you'll need to give them a base value outside the :visited selector.

CSSの優先順位

カスケード法

遷移宣言 [css-transitions-1]
important にされた UA 宣言
important にされた 利用者 宣言
important にされた 作者 宣言
アニメーション 宣言 [css-animations-1]
通常の作者宣言
通常の利用者宣言
通常の UA 宣言 

:visited に適用可能なプロパティ

color, background-color, border-color, border-bottom-color, border-left-color, border-right-color, border-top-color, column-rule-color, and outline-color

主要ブラウザのデフォルトCSS

デフォルトCSSをまとめてくれていたページ

検証

検証時に使用した基本コード

以下のコードをベースにブラウザでの見え方を確認。
*確認した環境は、「firefox 66.0.3」+「codepen」

<a href="#new">new link</a><br>
<a href="">visited link</a><br>
a:link::after{content: "(:LINK)";}
a:visited::after{content: "(:VISITED)";}
a:link {
  border: solid 1px;
}
a:visited {
  background-color: black;
  color: black;
  border-color: black;
  border-bottom-color: black;
  border-left-color: black;
  border-right-color: black;
  border-top-color: black;
  column-rule-color: black;
  outline-color: black;
}

SS

上記のイメージを見るとわかるが、:visited:link と判断されている。
ブラウザによる差異はあるかもしれないが、これが:linkの CSS が:visitedに適用される原因と思われる。

実際に Firefox では、処理が重い時:linkの CSS で描画された後、:visitedで上書きされる様子が観測できる。
またその際、(探しきれていないだけかもしれないが)デフォルト CSS として定義もされていない color が反映されている。
*明らかに CSS の優先順位に記述のない処理が走っている。

visited の確認には時間がかかるので遅延反映は初期描画速度を上げるための工夫ではないかと考えられる。セキュリティ観点で visited の実装に幅ができたことが逆にブラウザのおかしな挙動につながっている気がする。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

デフォルトで設定されているのでは?

参考:
:any-link

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/22 10:28

    非常に示唆に富んだコメント、ありがとうございます。
    *回答へ転記とかしてもらうことは可能でしょうか?すげぇもったいないです!

    > ここでW3Cは「:any-link」を登場させ、「a:link」の設定で「a:any-link」も一部デフォルトで設定させることで、辻褄合わせを行っているのでは?と思っています。

    think49 さんの提示してくれた「8.2. リンク履歴 疑似クラス: :link, :visited - Selectors Level 4 (日本語訳)」のブラウザ実装と絡んで、なんかいろいろおかしな状況を作り出しているのかもしれないですね。

    こちらでももう少し追ってみます!

    キャンセル

  • 2019/04/24 00:53

    「追記」の部分ですが、自分なりに推測して、たどり着いた結論(妄想?)ですが・・・

    W3Cの人は頭が良いので、いろんな方向から定義しており、その中に数学的な解釈もあるのでは?と思いました。

    「:visited」を「リンク先へ訪問済み」と、定義する場合に、必ずリンク先は「未訪問」が前提となります。
    これを「0」の状態として、何らかのbackground等を設定すれば「1」であり、設定しなければ「0」のままです。(color等除く)

    よって「:visited」で色んな設定をしても、元が「0」なので、どんな数字を掛け算しても「0」、つまり、「a:visited {background-color: black;}」のスタイルは「無効」となるのでは?

    「think49」さんの回答にもある「ブライバシー保護」が最有力だと思いますが、上記の計算上の考えも当てはまる気がしてきました。

    ・・・やっぱり妄想の気が・・・
    (^^;)

    キャンセル

  • 2019/04/25 17:09

    こちらのコメント、参考になりました。
    根拠となる資料が探せないのが残念です。
    コード読めると一番いいのでしょうけど私では力及ばず^^;

    コメント内容を含めて、後日考察をまとめてみますね。
    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る