[HN Gopher] Conditional CSS with:has and:nth-last-child
       ___________________________________________________________________
        
       Conditional CSS with:has and:nth-last-child
        
       Author : shadeed
       Score  : 89 points
       Date   : 2023-05-17 15:40 UTC (7 hours ago)
        
 (HTM) web link (ishadeed.com)
 (TXT) w3m dump (ishadeed.com)
        
       | Sinescape wrote:
       | This combination feels unnecessarily complicated to me, at least
       | for most of the use cases shown.
       | 
       | Suppose we want to style a list differently if it has five or
       | more items. Since :has can detect any child element, the
       | existence of a fifth item is a sufficient indicator that there
       | are at least five items. So instead of ul:has(li:nth-last-
       | child(n+5)), we could just use ul:has(li:nth-child(5)) which is
       | quite a bit clearer in my opinion.
        
       | yakshaving_jgt wrote:
       | I'm looking forward to doing things like
       | select:has([value="foo"]:checked) ~ .bar { ... }
       | 
       | I wish Firefox supported it.
        
         | capitainenemo wrote:
         | Well... firefox has partial support that can be enabled using
         | layout.css.has-selector.enabled in about:config.
         | 
         | The problem is the spec is an unfinalised moving target right
         | now (they've had to _remove_ support for things that were taken
         | out of the spec in their implementation), and when I read their
         | tracking bug, they still have issues related to invalidation.
         | 
         | I imagine the priority of this will move up as the selector
         | becomes official... https://w3c.github.io/csswg-
         | drafts/selectors/
        
           | silverwind wrote:
           | The sooner they enable basic support, the better. There are
           | already sites out there that break in browsers without `:has`
           | support.
        
             | capitainenemo wrote:
             | Sites should not be enabling draft specifications. That's
             | just poor site design.
             | 
             | But of course, nowadays, anything Chrome does becomes a de-
             | facto standard.
        
       | samwillis wrote:
       | There are so many nice new things in CSS, along with :has() and
       | :nth-last-child there is also :is(), :not() and the new nested
       | syntax. All make working with raw css much more pleasant. No more
       | SASS/LESS, and (hopefully) soon no more PostCSS hopefully!
       | 
       | :is() - https://developer.mozilla.org/en-US/docs/Web/CSS/:is
       | 
       | :not() - https://developer.mozilla.org/en-US/docs/Web/CSS/:not
       | 
       | CSS nesting - https://developer.chrome.com/articles/css-nesting/
       | 
       | Interestingly nested css is implemented as a syntactic sugar over
       | :is() in order to achieve the correct specificity.
        
         | jimmaswell wrote:
         | > HTML elements currently require the & symbol in front or
         | being wrapped with :is().
         | 
         | They were so close to capturing how good LESS is, why did they
         | do this?
        
           | samwillis wrote:
           | It's to do with how the parsers are implemented in browsers I
           | believe. I think I read that it would require a large rewrite
           | of them all and potentially make them slower.
           | 
           | Personally I think it good that it makes it more explicit,
           | even for none element nested selectors I'm adding the & to
           | make it clear. So for a class "& .something".
           | 
           | Edit:
           | 
           | Found it in the spec
           | 
           | > _Nesting style rules naively inside of other style rules
           | is, unfortunately, ambiguous--the syntax of a selector
           | overlaps with the syntax of a declaration, so an
           | implementation requires unbounded lookahead to tell whether a
           | given bit of text is a declaration or the start of a style
           | rule._
           | 
           | > _... that is, the parser might have to hold onto an unknown
           | amount of content before it can tell which way it's supposed
           | to be interpreting it. CSS to date requires only a small,
           | known amount of lookahead in its parsing, which allows for
           | more efficient parsing algorithms, so unbounded lookahead is
           | generally considered unacceptable among browser
           | implementations of CSS._
           | 
           | End of this section: https://www.w3.org/TR/css-
           | nesting-1/#nesting
        
           | foolip wrote:
           | The CSS Working Group has resolved to relax the syntax in
           | https://github.com/w3c/csswg-drafts/issues/7961 so what you
           | desire is coming :)
        
         | paavohtl wrote:
         | Little nitpick, but :not() is not a new feature by most
         | definitions of new. It has been in browsers for over a decade
         | (closer to 15 in browsers not related to IE), which is an
         | eternity in the world of web technology.
        
           | samwillis wrote:
           | Correct, although :not() had a _massive_ upgrade only a
           | couple of years ago with complex selectors support.
           | 
           | Prior to the change you could only pass a "simple selector"
           | that only matched against the one node, such as
           | :not(.something).
           | 
           | However you can now do :not(ul > li p.something)
        
         | ozzmotik wrote:
         | x
        
         | hanniabu wrote:
         | I've gone vanilla css since variables were added
        
       | RheingoldRiver wrote:
       | Although :has still shouldn't be use because the spec isn't
       | finalized (and so it's (rightfully) not supported by Firefox),
       | another incredible post.
       | 
       | For the header layout code, the SASS example will be valid CSS
       | once the nested CSS spec is approved & live right? (Although that
       | probably won't be widely implemented enough for use for several
       | years in vanilla css)
       | 
       | Btw, the video for user avatars isn't loading for me
        
         | alwillis wrote:
         | > Although :has still shouldn't be use because the spec isn't
         | finalized (and so it's (rightfully) not supported by Firefox)
         | 
         | I don't it's reasonable to hold off on using :has(), something
         | web developers have wanted for close to 20 years just because
         | it's not supported by Firefox. It's far too important and
         | useful.
         | 
         | Especially when 86.93% of the global web audience uses a
         | browser that supports it [1]. And as much I admire Firefox and
         | what they stand for, it's marketshare is 2.77% [2].
         | 
         | Regarding the spec not being finalized... while that may be
         | technically true, the current draft specification has been
         | stable for several months and is what the browser vendors have
         | agreed to implement.
         | 
         | It's been 14 months (March 14, 2022) since :has() first shipped
         | in Safari 15.4 [3]; I think it should be okay to use :has() in
         | production and lets hope Firefox catches up soon.
         | 
         | [1]: https://caniuse.com/?search=%3Ahas
         | 
         | [2]: https://gs.statcounter.com/browser-market-share
         | 
         | [3]: https://www.webkit.org/blog/12445/new-webkit-features-in-
         | saf...
        
           | RheingoldRiver wrote:
           | > and lets hope Firefox catches up soon.
           | 
           | They won't implement it until the spec is finalized (is my
           | guess, given that they haven't done so, so far). By
           | encouraging users to use :has already, you're encouraging
           | Chrome's monopoly on the open internet, in _direct
           | contradiction_ to the W3c standard.
           | 
           | caniuse is an important tool, yes, but it's also super
           | important to take into consideration what the literal
           | standard says, which is that :has is not part of the
           | specification. And Chrome directly working in contradiction
           | to that is enormously bad for Internet users. Safari's
           | decision to also implement :has early shouldn't make you bow
           | down to Google in this case imo.
        
       | someonewhocar3s wrote:
       | [dead]
        
       | atoav wrote:
       | :has is one of the things I am waiting for, for a while now.
       | Especially when parsing the html output of markdown this would be
       | incredibly useful, as most converters pack images into
       | paragraphs, so you have no way of selecting text paragraphs vs
       | paragraphs with images in them.
        
       | galkk wrote:
       | Can't shake the feeling that this is clever use of available
       | tools but hack.
        
         | simonw wrote:
         | This feels to me like it's an intended use of the :has and
         | :nth-child - I would worry about it if I thought it was a trick
         | that might stop working in the future, but it seems compatible
         | with the intention of the spec to me.
        
           | digging wrote:
           | Both can be true... CSS has a lot of clever tools that feel
           | like hacks. And I'm here for it, even though I almost never
           | want to use most of them. We need more non-JS options in web
           | sites. I just hate that they're so obscure and complex for
           | relatively little gain.
        
       | JadeNB wrote:
       | The title mangler ate the spaces before the colons in
       | "Conditional CSS with :has and :nth-last child".
        
         | ender341341 wrote:
         | I believe if you edit it it doesn't mangle them on update, at
         | least for some cases
        
           | JadeNB wrote:
           | > I believe if you edit it it doesn't mangle them on update,
           | at least for some cases
           | 
           | It's not my post, so I can't edit it, but thanks!
        
       | JoshTriplett wrote:
       | I've wanted :has for 16 years:
       | https://bugzilla.mozilla.org/show_bug.cgi?id=418039
       | 
       | I'm glad it's now available, and enabling all sorts of fun
       | things.
        
       | digging wrote:
       | I feel like this article doesn't explain how `nth-last-child`
       | works clearly.
       | 
       | The example uses (n + 3) in a list of five items. Start counting
       | from the 3rd item - ok, the visualization[1] shows us counting
       | from the 3rd-from-last, so now I'm already confused. And then we
       | count "until the end", which actually shows us counting back
       | toward the beginning[2]. And we end up with 3 items. Are they the
       | last 3? The first 3? I can't tell. The author should have chosen
       | a number that didn't sit at the halfway point of the total number
       | of items.
       | 
       | The description makes it sound like we start at 5 -> 4 -> 3, then
       | select 3 items, so we select 3 -> 4 -> 5. But that's a tautology.
       | I _think_ what it means is that we start at 1 - > 2 -> 3, and
       | select 3 -> 4 -> 5... is that correct?
       | 
       | [1] https://ishadeed.com/assets/css-has-nth-last-child/nth-
       | last-... [2] https://ishadeed.com/assets/css-has-nth-last-
       | child/nth-last-...
        
         | slowwriter wrote:
         | I entirely agree that the explanation in the article is
         | somewhat confusing, because we're selecting 3 items starting
         | from #3 in a list, counting both from the top and the bottom.
         | So which of those three options does the 3 stand for?
         | 
         | The very first demo in the MDN doc for :nth-last-child helped
         | me understand: https://developer.mozilla.org/en-
         | US/docs/Web/CSS/:nth-last-c... - just change the "-n + 3" to "n
         | + 3" to match the example in the article.
         | 
         | In that case the selector starts at the third element from the
         | bottom and ends at the top element, matching a total of 6
         | elements.
        
       ___________________________________________________________________
       (page generated 2023-05-17 23:00 UTC)