All non-replaced elements have a ::contents
pseudo-element, which wraps all the contents inside the element, not including ::marker
nor the contents generated by ::before
and ::after
, if any.
::contents
pseudo-elements must act as if they were assigned display: contents
via a rule in the UA origin. Therefore, they do not generate any boxes and are treated as if they had been replaced with their children. This must be possible to override via display
, so they do generate boxes if desired.
Note This is consistent with slots in a shadow tree.
A ::contents
pseudo-element can be styled exactly like any normal document-sourced element in the document tree.
When its display
property does not compute to contents
nor none
, the pseudo-element generates boxes as if it was an immediate child of its originating element, and the actual contents of the originating element generate boxes as if they were immediate children of the pseudo-element.
When its display
property computes to none
, the pseudo-element and the actual contents of the originating element generate no boxes. ::marker
, ::before
and ::after
pseudo-elements generate boxes as ausual, according to their display
and content
properties.
When attached to a replaced element, the ::contents
pseudo-element has no effect.
Issue: What about "kinda-replaced" elements?
Example
The fictional tag sequence for this HTML fragment with the following rules
div::before { content: 'A'; } div::contents { display: inline; } div::after { content: 'C'; }<div>B</div>is:
<div> <div::before>A</div::before> <div::contents>B</div::contents> <div::after>C</div::after> </div>
Example
Defining margins that only apply between flex-items (issue 592) can be easily done as follows:
.flex-container { overflow: hidden; } .flex-container::contents { display: flex; margin: -25px; } .flex-container > .flex-item { margin: 25px; }
Example
The
::before
and::after
pseudo-elements generate content inside an element. For example,div { /* border, margin, ... */ } div::before { content: 'A'; } div::after { content: 'C'; }Previous <div>B</div> Followingproduces the following fictional tag sequence:
Previous <div> <div::before>A</div::before> B <div::after>C</div::after> </div> FollowingHowever, sometimes it is desirable to generate content outside the element. This can be accomplished by adding
div { display: contents; } div::contents { display: block; /* border, margin, ... */ }resulting in
Previous <div::before>A</div::before> <div::contents>B</div::contents> <div::after>A</div::after> Following
A ::contents
pseudo-element inherits from its originating element.
A child element or text node inherits inherited properties from the ::contents
pseudo-element originated by the parent element.
For non-inherited properties, inheritance is directly from the parent element.
Note This is consistent with how
::first-line
affects inheritance (issue 1097), but for::contents
there is no need to blacklist custom properties.
Issue: Alternatively, inheritance could be from
::contents
for all properties, and assignall: inherit; unicode-bidi: inherit; display: contents
to::contents
in UA origin.
Interaction with Selectors
The ::contents
pseudo-element selector can be used to select the ::contents
pseudo-element.
Other selectors are not affected. ::contents
is inserted between an element and its children in the CSS element tree, but DOM-based relationships represented for example by the child combinator (>
) remain unaltered.
The ::contents
pseudo-element can be pseudo-classed by pseudo-classes that can pseudo-class ::before
and ::after
.
The ::contents
pseudo-element does not define any internal structure.
Interaction with the CSS Generated Content Module
Issue: This section intends to explain the magic behind
::contents
in terms of thecontent
property. But Tab said thatcontents
was not supposed to affect inheritance, and that it will probably be dropped anyways.
As a tree-abiding pseudo-element, the content
property applies to ::contents
.
-
For elements and
::contents
pseudo-elements, this computes tocontents
.Issue: Should
normal
compute tonone
on::contents
pseudo-elements in case the computed value of thecontent
property of the originating element does not includecontents
?For
::before
and::after
pseudo-elements, this computes tonone
. -
On elements, this inhibits the creation of the
::contents
pseudo-element, as if that pseudo-element haddisplay: none
.Note: Inhibiting the
::contents
pseudo-element also prevents the actual contents of the element from being rendered, unless::before
or::after
includecontents
in the computed value of theircontent
property.On
::contents
pseudo-elements, this inhibits the actual children of the originating element from being rendered as children of this pseudo-element, as if the element was empty.Issue: Should
content: none
on::contents
completely inhibit it? This would be more consistent with other pseudo-elements, but less useful, because this would be equivalent to usingcontent: none
on the originating element.On other pseudo-elements, this inhibits the creation of the pseudo-element as if it had
display: none
. -
Makes the element or pseudo-element a replaced element, filled with the specified
<image>
. Its normal contents are suppressed and do not generate boxes, as if they haddisplay: none
.Note: Replaced elements do not have
::before
,::after
or::contents
pseudo-elements; the content property replaces their entire contents. -
On elements, this replaces the
::contents
pseudo-element with one or more anonymous inline boxes corresponding to the specified values, in the order specified. Unlesscontents
appears in the<content-list>
, the::contents
pseudo-element is suppressed and does not generate boxes, as if it haddisplay: none
.On pseudo-elements, this replaces the pseudo-element’s contents with one or more anonymous inline boxes corresponding to the specified values, in the order specified. Its normal contents are suppressed and do not generate boxes, as if they had
display: none
. -
On elements, this allows the creation of the
::contents
pseudo-element. It is useless to includecontents
twice in a singlecontent
property, because the second occurrence simply has no effect, as there can only be a single::contents
pseudo-element.On pseudo-elements, this makes the contents of the pseudo-element be the actual contents of the originating element. It is useless to include
contents
more than once in a singlecontent
property, or usecontents
in multiple pseudo-elements, because only the first occurrence has an effect, as the actual contents of the originating element cannot be duplicated.When used in multiple pseudo-elements, the first occurrence is searched in the following order: