Privacy and the :visited selector

  • Revision slug: CSS/Privacy_and_the_:visited_selector
  • Revision title: Privacy and the :visited selector
  • Revision id: 235957
  • Created:
  • Creator: Dholbert
  • Is current revision? No
  • Comment Merge unnecessary second :link chunk into first :link chunk.; 6 words added, 9 words removed

Revision Content

{{ gecko_minversion_header("2") }}

Historically, the CSS {{ cssxref(":visited") }} selector has been a way for sites to query the user's history, by using getComputedStyle() or other techniques to walk through the user's history to figure out what sites the user has visited. This can be done quickly, and makes it possible not only to determine where the user has been on the web, but can also be used to guess a lot of information about a user's identity.

To mitigate this problem, changes have been made in {{ Gecko("2") }} to limit the amount of information that can be obtained about visited links.

Little white lies

The first change is that Gecko will lie to web applications under certain circumstances. In particular, getComputedStyle() and similar functions such as {{ domxref("element.querySelector()") }} always return values indicating that a user has never visited any of the links on a page.

Also, if you use a sibling connector such as :visited + span, the {{ htmlelement("span") }} will be styled as if the link were unvisited.

And, in a rare scenario, if you're using nested link elements and the element being matched is different from the link whose presence in history is being tested, the element is drawn as if the link were unvisited as well.

Limits to visited link styles

You will still be able to visually style visited links, but there are now limits on what styles you can use. Only the following properties can be applied to visited links:

  • {{ cssxref("color") }}
  • {{ cssxref("background-color") }}
  • {{ cssxref("border-color") }} (and its sub-properties)
  • {{ cssxref("outline-color") }}
  • The color parts of the fill and stroke properties

In addition, even for the properties you can set for visited links, you won't be able to change the transparency between unvisited and visited links, as you otherwise would be able to using rgba() or hsla() color values or the transparent keyword.

Here is example how to use styles with diccussed restrictions:

  :link {
    outline: 1px dotted;     /* Set outline width, otherwise you don't see outline... */
    outline-color: blue;
    /* Change background color from default 'transparent' value, otherwise you don't see changes for visited links... */
    background-color: white;
  }

  :visited {
    outline-color: orange;   /* You will see different outline color for visited links... */
    color: yellow;           /* You will see selected color for text in visited links */
    background-color: green; /* You will see selected color in backgound around visited links */
  }

Impact on web developers

Overall, this shouldn't affect web developers too significantly. There are, however, a few special cases that may require changes to sites:

  • Using background images to style links and indicate whether or not they've been visited will no longer work, since only colors can be used to style visited links.
  • CSS transitions won't be supported for visited links. Fortunately, CSS transitions are very new, and there are few sites using them at this point, so this isn't likely to impact many people at this point.

See also

Revision Source

<p>{{ gecko_minversion_header("2") }}</p>
<p>Historically, the CSS {{ cssxref(":visited") }} selector has been a way for sites to query the user's history, by using <code>getComputedStyle()</code> or other techniques to walk through the user's history to figure out what sites the user has visited. This can be done quickly, and makes it possible not only to determine where the user has been on the web, but can also be used to guess a lot of information about a user's identity.</p>
<p>To mitigate this problem, changes have been made in {{ Gecko("2") }} to limit the amount of information that can be obtained about visited links.</p>
<h2>Little white lies</h2>
<p>The first change is that Gecko will lie to web applications under certain circumstances. In particular, <code>getComputedStyle()</code> and similar functions such as {{ domxref("element.querySelector()") }} always return values indicating that a user has never visited any of the links on a page.</p>
<p>Also, if you use a sibling connector such as <code>:visited + span</code>, the {{ htmlelement("span") }} will be styled as if the link were unvisited.</p>
<p>And, in a rare scenario, if you're using nested link elements and the element being matched is different from the link whose presence in history is being tested, the element is drawn as if the link were unvisited as well.</p>
<h2>Limits to visited link styles</h2>
<p>You will still be able to visually style visited links, but there are now limits on what styles you can use. Only the following properties can be applied to visited links:</p>
<ul> <li>{{ cssxref("color") }}</li> <li>{{ cssxref("background-color") }}</li> <li>{{ cssxref("border-color") }} (and its sub-properties)</li> <li>{{ cssxref("outline-color") }}</li> <li>The color parts of the <code>fill</code> and <code>stroke</code> properties</li>
</ul>
<p>In addition, even for the properties you can set for visited links, you won't be able to change the transparency between unvisited and visited links, as you otherwise would be able to using <code>rgba()</code> or <code>hsla()</code> color values or the <code>transparent</code> keyword.</p>
<p>Here is example how to use styles with diccussed restrictions:</p>
<pre>  :link {
    outline: 1px dotted;     /* Set outline width, otherwise you don't see outline... */
    outline-color: blue;
    /* Change background color from default 'transparent' value, otherwise you don't see changes for visited links... */
    background-color: white;
  }

  :visited {
    outline-color: orange;   /* You will see different outline color for visited links... */
    color: yellow;           /* You will see selected color for text in visited links */
    background-color: green; /* You will see selected color in backgound around visited links */
  }
</pre>
<h2>Impact on web developers</h2>
<p>Overall, this shouldn't affect web developers too significantly. There are, however, a few special cases that may require changes to sites:</p>
<ul> <li>Using background images to style links and indicate whether or not they've been visited will no longer work, since only colors can be used to style visited links.</li> <li><a href="/en/CSS/CSS_transitions" title="en/CSS/CSS transitions">CSS transitions</a> won't be supported for visited links. Fortunately, CSS transitions are very new, and there are few sites using them at this point, so this isn't likely to impact many people at this point.</li>
</ul>
<h2>See also</h2>
<ul> <li><a class="external" href="http://hacks.mozilla.org/2010/03/privacy-related-changes-coming-to-css-vistited/" title="http://hacks.mozilla.org/2010/03/privacy-related-changes-coming-to-css-vistited/">privacy-related changes coming to CSS :visited</a> on Mozilla Hacks</li> <li><a class="external" href="http://blog.mozilla.com/security/2010/03/31/plugging-the-css-history-leak/" title="http://blog.mozilla.com/security/2010/03/31/plugging-the-css-history-leak/">Plugging the CSS History Leak</a> on the Mozilla Security Blog</li> <li><a class="external" href="http://dbaron.org/mozilla/visited-privacy">Preventing attacks on a user's history through CSS :visited selectors</a></li>
</ul>
Revert to this revision