Open ExE-Boss opened 5 years ago
FWIW, these selectors are somewhat slow, and I planned on trying to hide them from content when I had the chance...
Selectors mainly work on element level, and extending them to node level may cause some confusing, and ignoring white-space and comments isn't really what "last node" should mean...
Selectors mainly work on element level, and extending them to node level may cause some confusing, and ignoring white-space and comments isn't really what "last node" should mean...
I agree, the only reason these selectors exist at all in Gecko is to implement quirks.
The demand to differentiate child elements that don't have any text before them from those that do seems to occur quite often (especially in styling user-generated content, in designing components that can be inserted into arbitrary environment, some more use cases are mentioned in #2208). So it would be great if there would be a standard tool for this, even if the current Gecko's experimental implementation is not perfect (though it's much better than nothing:).
The demand to differentiate child elements that don't have any text before them from those that do seems to occur quite often (especially in styling user-generated content)
For me it’s elements that don’t have any text after them (eg. the last paragraph in a comment shouldn’t have a bottom margin, but I can’t guarantee that there won’t be any text after it, because I’m dealing with making a custom post style for my posts on forum using a horrible frontend that still uses tables for layout in 2018).
As the main use case for this is controlling margins, we've added a 'margin-trim' property, see discussion in https://lists.w3.org/Archives/Public/www-style/2018Nov/0005.html
Are there other major use cases for this?
There are the same use cases as for :first‑child
and :last‑child
, but I don’t know how major those are.
I don’t know how important my use-case is, but on my website, I style <strong>
elements differently (small caps, extra bold) if they appear before any other text in a paragraph.
Currently, I have to use JavaScript to add a CSS class to these elements, but I would use the :first-node
selector instead if it was cross browser.
// add class to paragraphs that begin with a <strong> element
for (let p of article.querySelectorAll('p')) {
let node = p.childNodes[0];
if (node && node.nodeName === 'STRONG') {
p.classList.add('Issue__note');
}
}
I have another use case: I style emojione images differently when they appear in the middle of text, than when they are solo.
@emilio Can you elaborate on why these are slow? Presumably they're slow in comparison to :first-child? Is it related to the "ignore text nodes that are just whitespace" bit?
I just needed this same selector for a project I was working on today. I would like to target a span tag that exists in a block of text. If it is not the first node, I would like to apply margin-left
to space it away from the text to its left, and it is not the last node, I would like to apply margin-right
to space it away from the text to its right. Unfortunately, this isn't currently possible in pure CSS, because one span tag inside a body of other text will match both :first-child
and :last-child
even though it is neither the first nor the last node.
This is true for all three examples below:
<!-- Example 1 -->
Lorem ipsum <span>TEST</span> lorem ipsum
<!-- Example 2 -->
<span>TEST</span> lorem ipsum lorem ipsum
<!-- Example 3 -->
Lorem ipsum lorem ipsum <span>TEST</span>
Another use case for this could be changing back the first abbreviation/number from oldstyle numerals and small caps when it is at the beginning of the paragraph. Currently, we don't have any way to know if some element is there. (motivated by the discussion from https://front-end.social/@kizu/112637529030687445, example CodePen: https://codepen.io/kizu/pen/JjqpKqK; ideally we'd want to actually target the first word/node in the sentence, but I don't know if we could ever achieve this with just CSS).
For me, I am looking at styling these buttons differently:
<button><svg>...</svg> Click Here</button>
<button>Click Here <svg>...</svg></button>
But unfortunately there is no way to determine if the text is before or after the svg.
So maybe we could then do:
button:has( > svg:not(:last-node))
or button:has( > svg:not(first-node))
without it affecting:
<button><svg>...</svg></button>
Right now, CSS Selectors 4 defines
:first-child
and:last-child
, which works as such for the following:For
:first-node
and:last-node
, this would work as follows:Mozilla Firefox already implements the previous in prefixed form and exposes it to the web.