Why can’t I set the font size of a visited link?
Visited links show up purple; unvisited links show up blue.
This distinction goes back to the beginning of the web.
But CSS allows you to customize this visual difference using the
Say you wanted to make visited links gray and smaller,
to indicate to the user that this link is “done”:
This style is applied on this page, and here’s a sample:
Notice that the visited link appears gray, as expected,
but the font size hasn’t changed!
This is because changing the font size would be a security vulnerability!
If CSS could set the font size differently,
I (Jim) could tell whether you’ve visited
Web pages are able to inspect the rendered elements on the page.
The most obvious way is with
Here are the reported properties of the above visited link,
as reported by your browser:
getComputedStyle were to report
6px instead of
18px for visited links,
I could have this page generate a link to
then test its font size,
in order to reveal your browsing history.
I could then serve you targeted ads,
sell your data,
This security hole has been plugged
by not allowing
a:visited to set the
But notice what
getComputedStyle reported for the color of the visited link:
rgb(0, 0, 238), i.e., blue.
This is a lie - the link is gray!
browsers have plugged the security hole in a different way:
instead of disallowing the property to be customized,
getComputedStyle lie about its value.
Why two approaches?
Why can’t we have
getComputedStyle lie for
The reason is that
web pages can inspect the rendered elements via more than
Web pages can check an element’s position in the page,
font-size of the visited link would affect the offset of other elements,
the page could indirectly check whether the link is visited.
a:visited is a brutal, but safer, solution.
There’s a short whitelist of properties that,
shouldn’t affect page layout,
and so shouldn’t be detectable.
They’re all different forms of color.
All other CSS properties are banned.
In theory, there is no way that a web page can determine whether a link has been colored differently. One possibility is a timing attack: say, if it takes longer to color something pink compared to blue, the page could measure how long it took to render the element, and compared this to an expected duration.