Skip to content

Commit 1432231

Browse files
committed
[css-display] More thoroughly review the list of SVG elements and put <a>, <textpath>, and unknown elements (which act like <g>) into the 'normal display:contents behavior' category. Add an explanatory note for the categorization.
1 parent c8be56a commit 1432231

File tree

3 files changed

+184
-22
lines changed

3 files changed

+184
-22
lines changed

css-display-3/Overview.bs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,9 +1094,12 @@ SVG Elements {#unbox-svg}
10941094
''display: contents'' behaves as ''display: none''.
10951095

10961096
: Nested <{svg}>
1097+
: <{a}>
10971098
: <{g}>
10981099
: <{use}> (treated as a Shadow DOM container)
10991100
: <{tspan}>
1101+
: <{textPath}>
1102+
: unknown elements
11001103
::
11011104
''display: contents'' strips the element from the formatting tree,
11021105
and hoists its contents up to display in its place.
@@ -1105,6 +1108,16 @@ SVG Elements {#unbox-svg}
11051108
::
11061109
''display: contents'' behaves as ''display: none''.
11071110

1111+
Note: The intention here is that "nested container" elements--
1112+
elements which have the same sort of "rendering context"
1113+
both outside and inside themselves,
1114+
such that it's <em>meaningful</em> to put their contents
1115+
into the context of their parents--
1116+
get stripped and hoist their contents like normal for ''display: contents''.
1117+
Anything else,
1118+
where their contents are handled in a totally separate context from their parent,
1119+
just removes itself entirely.
1120+
11081121
<h2 class=no-num id="acknowledgments">
11091122
Acknowledgments</h2>
11101123

css-values-4/Overview.bs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,11 +1680,8 @@ Syntax</h4>
16801680
<<min()>> = min( <<calc-sum>># )
16811681
<<max()>> = max( <<calc-sum>># )
16821682
<dfn>&lt;calc-sum></dfn> = <<calc-product>> [ [ '+' | '-' ] <<calc-product>> ]*
1683-
<dfn>&lt;calc-product></dfn> = <<calc-value>> [ '*' <<calc-value>> | '/' <<calc-number-value>> ]*
1683+
<dfn>&lt;calc-product></dfn> = <<calc-value>> [ '*' <<calc-value>> | '/' <<calc-value>> ]*
16841684
<dfn>&lt;calc-value></dfn> = <<number>> | <<dimension>> | <<percentage>> | ( <<calc-sum>> )
1685-
<dfn>&lt;calc-number-sum></dfn> = <<calc-number-product>> [ [ '+' | '-' ] <<calc-number-product>> ]*
1686-
<dfn>&lt;calc-number-product></dfn> = <<calc-number-value>> [ '*' <<calc-number-value>> | '/' <<calc-number-value>> ]*
1687-
<dfn>&lt;calc-number-value></dfn> = <<number>> | ( <<calc-number-sum>> )
16881685
</pre>
16891686

16901687
In addition, [=whitespace=]

selectors-4/Overview.bs

Lines changed: 170 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,35 +1956,187 @@ The Hyperlink Pseudo-class: '':any-link''</h3>
19561956
<h3 id="link">
19571957
The Link History Pseudo-classes: '':link'' and '':visited''</h3>
19581958

1959-
User agents commonly display unvisited <a href="#the-any-link-pseudo">hyperlinks</a> differently from
1960-
previously visited ones. Selectors
1961-
provides the pseudo-classes <dfn id='link-pseudo'>:link</dfn> and
1962-
<dfn id='visited-pseudo'>:visited</dfn> to distinguish them:
1963-
1964-
<ul>
1965-
<li>The '':link'' pseudo-class applies to links that have
1959+
User agents commonly display unvisited <a href="#the-any-link-pseudo">hyperlinks</a>
1960+
differently from previously visited ones.
1961+
Selectors provides the pseudo-classes
1962+
<dfn id='link-pseudo'>:link</dfn> and <dfn id='visited-pseudo'>:visited</dfn>
1963+
to distinguish them.
1964+
Roughly:
1965+
1966+
* The '':link'' pseudo-class applies to links that have
19661967
not yet been visited.
1967-
<li>The '':visited'' pseudo-class applies once the link has
1968+
* The '':visited'' pseudo-class applies once the link has
19681969
been visited by the user.
1969-
</ul>
19701970

19711971
After some amount of time, user agents may choose to return a
19721972
visited link to the (unvisited) '':link'' state.
19731973

1974-
The two states are mutually exclusive.
1974+
The two states are mutually exclusive
1975+
(no element can ever match '':link:visited''),
1976+
but their actual interaction is more complex than that,
1977+
for privacy reasons explained below.
1978+
1979+
In full, the behavior is actually that the '':link'' pseudo-class applies to all links,
1980+
but the '':visited'' pseudo-class applies the following behavior and restrictions:
1981+
1982+
<div algorithm=":visited styling">
1983+
To <dfn>apply :visited styling</dfn> to an element |el|:
1984+
1985+
1. Check to see if |el| has a <a>relevant link</a>.
1986+
The <dfn for=":visited">relevant link</dfn> for an element
1987+
is the element itself,
1988+
if it's an element that would match '':link'',
1989+
or else the closest ancestor that would match '':link''.
1990+
1991+
If |el| does not have a <a>relevant link</a>,
1992+
then '':visited'' has no effect on the element.
1993+
1994+
2. Otherwise, compute |el|’s style,
1995+
treating only its <a>relevant link</a> as matching '':visited''
1996+
(and thus, not '':link'').
1997+
All other links must be treated as matching '':link''.
1998+
1999+
3. From the styling results,
2000+
record the values of the <dfn lt="allowed :visited property">allowed :visited properties</dfn>:
2001+
2002+
* 'color'
2003+
* 'background-color'
2004+
* the 'border-color' sub-properties
2005+
* 'outline-color'
2006+
* 'column-rule-color'
2007+
* 'fill-color'
2008+
* 'stroke-color'
2009+
2010+
These are |el|’s <dfn lt=":visited style">:visited styles</dfn>.
2011+
2012+
4. If |el|’s <a>relevant link</a> is actually visited,
2013+
then for the <a>allowed :visited properties</a>,
2014+
use |el|’s <a>:visited styles</a> for any purposes
2015+
that won't allow the document itself to tell what the style is;
2016+
in all other contexts,
2017+
use the normal, all-'':link'', styling.
2018+
</div>
19752019

19762020
<div class="example">
1977-
The following selector represents links carrying class
1978-
<code>footnote</code> and already visited:
2021+
For example, with the following common example style sheet:
2022+
2023+
<pre class=lang-css>
2024+
:link { color: blue; }
2025+
:visited { color: purple; }
2026+
</pre>
2027+
2028+
Visited links show up as purple only for rendering to the screen.
2029+
If the document uses JS to query the element’s style,
2030+
it will instead report ''color: blue'',
2031+
as if the element only matched '':link''.
19792032

1980-
<pre>.footnote:visited </pre>
2033+
Similarly, if HTML's <{canvas}> element develops an ability to render HTML to the canvas with CSS styling,
2034+
then either the links would be styled blue
2035+
(because by default, <{canvas}> gives the document the ability to inspect the results),
2036+
or the visited links will be purple,
2037+
but <{canvas}> will restrict the page's ability to inspect the pixels of the result.
19812038
</div>
19822039

1983-
Since it is possible for style sheet authors to abuse the :link and :visited pseudo-classes
1984-
to determine which sites a user has visited without the user's consent,
1985-
UAs may treat all links as unvisited links
1986-
or implement other measures to preserve the user's privacy
1987-
while rendering visited and unvisited links differently.
2040+
<div class=example>
2041+
The special '':visited'' behavior also means
2042+
that a single element might be styled by a mix of '':link'' and '':visited'' rules.
2043+
For example:
2044+
2045+
<pre class=lang-css>
2046+
:link {
2047+
color: blue;
2048+
background-image: url("unvisited.png");
2049+
}
2050+
:visited {
2051+
color: purple;
2052+
background-image: url("visited.png");
2053+
}
2054+
</pre>
2055+
2056+
With this style sheet,
2057+
a visited link will be colored purple,
2058+
but have the "unvisited.png" background,
2059+
because 'background-image' is not one of the <a>allowed :visited properties</a>,
2060+
and so whatever value it gets from a '':visited'' style
2061+
is not recorded in the element's <a>:visited styles</a>.
2062+
</div>
2063+
2064+
<div class=example>
2065+
Another consequence of the special '':visited'' behavior
2066+
is that some selectors that look reasonable
2067+
will never match.
2068+
For example:
2069+
2070+
<pre class=lang-css>
2071+
:visited + span { color: red; }
2072+
</pre>
2073+
2074+
Even tho this style sheet is applying an <a>allowed :visited property</a> to the <code>span</code> element,
2075+
the <code>span</code>’s <a>relevant link</a> can never be its previous sibling
2076+
(it can only be the <code>span</code> or one of its ancestors).
2077+
Since the [=apply :visited styling|:visible styling algorithm=]
2078+
only checks if the element's <a>relevant link</a> is '':visited''
2079+
(and treats all other links on the page as unvisited),
2080+
this selector will never actually match anything.
2081+
</div>
2082+
2083+
<details class=note>
2084+
<summary>Why does '':visited'' have this strange behavior and restrictions?</summary>
2085+
2086+
Originally, '':link'' and '':visited'' did indeed work in the simple way
2087+
described at the beginning of this chapter,
2088+
like two ordinary mutually-exclusive pseudo-classes.
2089+
It was eventually discovered, however,
2090+
that this allowed pages to determine what other sites a user had visited,
2091+
by listing a bunch of links off-screen
2092+
and using JS to tell whether they were styled with '':link'' or '':visited''.
2093+
2094+
This was bad both for user's privacy
2095+
(for obvious reasons, sharing a user's browsing history with everyone is bad)
2096+
and for their security
2097+
(phishing attacks could, for example, tell which bank website a user visited,
2098+
and render their phishing page to match that bank specifically,
2099+
making it more likely to fool the user).
2100+
2101+
Rendering visited links in a different style was too useful to throw away entirely,
2102+
so instead user agents developed the above algorithm
2103+
to "lie" about the style in some contexts,
2104+
but still rendering the link with '':visited'' styles normally,
2105+
without paying too much extra computation time.
2106+
2107+
The very limited list of <a>allowed :visited properties</a>
2108+
further limits the possibility of a page figuring things out.
2109+
If '':visited'' could apply any property,
2110+
pages could still,
2111+
for example,
2112+
apply a particular 'background-image' only when a link is visited,
2113+
and then record whether that image was loaded from their server,
2114+
giving them the exact information we were trying to hide!
2115+
Similarly, any layout-affecting property,
2116+
like 'width',
2117+
might affect the positions of <em>other</em> elements on the page;
2118+
lying about these knock-on effects to hide the styling
2119+
would be much more expensive for the user agent.
2120+
Limiting it just a handful of properties that can only apply colors
2121+
ensures that as little information is leakable as possible.
2122+
</details>
2123+
2124+
User agents may treat all links as unvisited at all times.
2125+
(In particular, they can offer a user preference for this,
2126+
allowing the user to decide whether the benefit of seeing when a link has been visited
2127+
is more or less important
2128+
than the possibility of that information being leaked to random pages on the internet.)
2129+
2130+
If the user agent uses some form of "link pre-loading"
2131+
to find resource urls in a stylesheet
2132+
and begin loading them before it's known that they'll actually be used on the page,
2133+
they might find a url that would only be applied by an element matching '':visited''
2134+
(which is impossible, as '':visited'' rules can't cause any properties to apply that load images).
2135+
User agents with this behavior must ensure that either
2136+
such urls are <em>never</em> loaded (preferable),
2137+
or at least that such urls are loaded at the same time
2138+
regardless of whether a link is visited or not.
2139+
19882140

19892141
<h3 id="the-local-link-pseudo">
19902142
The Local Link Pseudo-class: '':local-link''</h3>

0 commit comments

Comments
 (0)