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
::beforeand::afterpseudo-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-lineaffects inheritance (issue 1097), but for::contentsthere is no need to blacklist custom properties.
Issue: Alternatively, inheritance could be from
::contentsfor all properties, and assignall: inherit; unicode-bidi: inherit; display: contentsto::contentsin 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
::contentsin terms of thecontentproperty. But Tab said thatcontentswas 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
::contentspseudo-elements, this computes tocontents.Issue: Should
normalcompute tononeon::contentspseudo-elements in case the computed value of thecontentproperty of the originating element does not includecontents?For
::beforeand::afterpseudo-elements, this computes tonone. -
On elements, this inhibits the creation of the
::contentspseudo-element, as if that pseudo-element haddisplay: none.Note: Inhibiting the
::contentspseudo-element also prevents the actual contents of the element from being rendered, unless::beforeor::afterincludecontentsin the computed value of theircontentproperty.On
::contentspseudo-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: noneon::contentscompletely inhibit it? This would be more consistent with other pseudo-elements, but less useful, because this would be equivalent to usingcontent: noneon 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,::afteror::contentspseudo-elements; the content property replaces their entire contents. -
On elements, this replaces the
::contentspseudo-element with one or more anonymous inline boxes corresponding to the specified values, in the order specified. Unlesscontentsappears in the<content-list>, the::contentspseudo-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
::contentspseudo-element. It is useless to includecontentstwice in a singlecontentproperty, because the second occurrence simply has no effect, as there can only be a single::contentspseudo-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
contentsmore than once in a singlecontentproperty, or usecontentsin 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: