https://drafts.csswg.org/selectors-4/
Please add ::text
or ::text-node
selector to select all text nodes inside any element
for example for
<p>
#text1: Here is text
<span>
#text2: Here also is text
</span>
#text3: Here is second text in the paragraph
</p>
the p::text
will select #text1 and #text3 and the pseudoelement can be styled like::after
and ::before
(without need to set "content").
I’ve also been thinking about pseudo-elements for anonymous boxes, first to the WICG to be eventually moved here. I talked about it at bit at https://github.com/w3c/csswg-drafts/issues/2084#issuecomment-351280093 – and I’ve have been writing a strawman when I can. I could find barely any prior mention of this idea before, when I searched on the web and in the old mailing lists.
For instance, a pseudo-element for anonymous block boxes would be generally useful in other cases as an approximate analogue to HTML’s paragraphs, e.g., anonymous-block “paragraphs” such as those in
<h1>First block</h1> This is the <em>second</em> block in this example. <p>This is the third.</p> <ul> <li>Fourth.</li> <li> <p>Fifth.</p> <p>Sixth.</p> </li> </ul>
. Such pseudo-elements, however, might have broad ramifications for rendering performance, so I had planned on courting authors in the WICG before the CSSWG to bolster my case. This is the first mention of this idea I have yet seen elsewhere on the web, so it’s good to have another use case.
My own biggest use case would be uniformly styling the boxes of paragraph text in <p>
s, <li>
s, <dt>
s and <dd>
s, <th>
s and <td>
s, <h1>
s, and so forth, even when they’re arbitrarily nested. @AmeliaBR wrote about some other use cases in https://github.com/w3c/csswg-drafts/issues/2084#issuecomment-351185353. These include selecting <details>
text content not within a <summary>
element and fallback text for things like <meter>
and <progress>
.
I don’t know if I should keep working on my WICG strawman if there’s going to be discussion here. I would be happy with any discussion: I’m certainly still surprised that there’s been barely any discussion about this idea over the past thirty years.
I'm definitely supportive of the idea in general.
A more detailed proposal with examples would probably be helpful in gaining more supporters, so if you're already working on something @js-choi, please don't stop just because this has now been formally raised as a working group issues.
Some things to think of:
Which are all probably good prompts for a WICG discussion if you want to start one.
2) In my opinion ::text should select only direct childs. we can write in my example:
p::text, p ::text /* note a space before ::*/
to select all text nodes.
3) Yes, whitespace nodes should be treated in other manner.
It's unclear about what most of the CSS properties would mean on a text-node, though, right? Specially non-inheriting ones.
In my opinion all styles including absolute positioning. But ::text::before forbidden.
What does an absolutely positioned text-node mean? Can you set display: block
on a text-node? What about display: none
? What happens to text layout when you combine stuff using display: contents
and such?
There's two ways to go about this. One is to style the text node itself - only a subset of the CSS properties would apply, those that work on text. (More or less just the properties that are inherited, but there are some inherited properties that wouldn't apply.) We'd have to define the precedence of this vs ::first-line and ::first-letter.
The second is to create an anonymous box around the text node and style that. In this case all of CSS applies. There is a minor problem here, tho - one of the use-cases for this is to solve issue 2 in the Scoping spec, and it's not totally clear where in the flat tree the anonymous box would be.
@tabatkins What about selecting anonymous inline blocks? They’re not exactly the same as text nodes (especially regarding positioning), but they overlap quite a bit. My impression had been that those are already being generated by current agents and thus would not necessitate creating new boxes.
It's unclear about what most of the CSS properties would mean on a text-node, though, right? Specially non-inheriting ones.
Works it like ::after and ::before.
::text
{
display:block;
border:2px solid red;
}
will be shown identically like:
::before
{
content:"the node text";
display:block;
border:2px solid red;
}
I think it is the easiest solution.
display: none
The text is removed and not shown.
display: contents
Need clarification and any idea. It can be by exception treated as display:inline
The second is to create an anonymous box...
Yes, in my opinion the anonymous inline box will be the solution. Only exception to styles that cannot be applied like display:contents. Please note, if the element <p/>
in my example will be styled display:flex;
the text nodes are switched to show like display:block
.
I have desired something like this several times when I have <div>Foo: <textarea></textarea></div>
and I want to vertically center the text with the textarea via vertical-align: middle
, but there is no way to select the text.
Always wrapping text runs inside new boxes may be a breaking change, e.g. boxes inside a flex container become flex items, so this would prevent sequences of text runs to be wrapped inside a single anonymous flex item. CSS Flexbox could discriminate boxes generated by ::text
from all the other ones, but this would be confusing and inconsistent.
It has also been suggested to inject the styles into anonymous boxes, but I think this is a bad idea because the cascade is supposed to happen in the element tree, and I prefer to avoid another fiasco like ::first-line
.
I think what makes more sense would be:
::text
pseudo-element in the CSS element tree.::text
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, which would be the current behavior. (There is precedence for this)display
, so they do generate boxes if desired. But maybe mark this at-risk.What is formal initial display
value for ::after
if the display, float and position are not defined?
BTW ::first-letter
is greater fiasco than ::first-line
@Nadya678 ::before
and ::after
have the initial display: inline
by default. But they also have content: none
, which behaves like display: none
.
OK. Thus here one exception: ::text
- default display:contents
.
I wasn't aware of this ticket existing when I wrote this: https://github.com/w3c/csswg-drafts/issues/2406#issuecomment-371568265
The basic take-away is that I don't think a text node selector should be a pseudo element prefixed with colon(s) - that creates all kind of problems with specificity imho.
Instead it should be like an invisible p-tag with slightly less specificity than tags that auto opens on text and auto closes before any new block context / when the parent element closes.
I believe some of the above thinking too tightly tied to an artifact in the DOM (that never results from parsing) which is the possibility of having empty or adjacent text nodes. Let's have CSS, if in a DOM-based implementation of the host language, pretend that document.normalize()
was performed before styling. (And do something sensible for APIs using CSS selectors.)
@ByteEater-pl It could be tied to the concept of text run:
each contiguous sequence of sibling text nodes generates a text run [...]. If the sequence contains no text, however, it does not generate a text run.
Most helpful comment
@ByteEater-pl It could be tied to the concept of text run: