Hacker News new | past | comments | ask | show | jobs | submit login
CSS Selectors: A Visual Guide (fffuel.co)
302 points by CosmosSeb on Aug 15, 2023 | hide | past | favorite | 57 comments



You can make nth-child repeat by using an arithmetic expression inside the parentheses, like nth-child(3n). They also stack, so you can create pseudorandom transformations to a sequence of elements by adding styles for the first few prime numbers.


Or nth-child(even), or nth-child(odd). (Keeping in mind that children are 1-indexed in CSS.)


And maybe some folks could be interested about little known fact that each selector has even a namespace part on the left; the void implicit one having effect depending on presence or absence of `@namespace` prologue in given stylesheet: - In stylesheet without explicit unnamed namespace it is like '*|', so everything is like `*|<element-selector>`; - In stylesheet with explicit unnamed namespace (`@namespace "<URI>");`) all element selectors without `<some-prefix>|<element-selector>` match only elements from that namespace. - In stylesheet with explicit named namespace (`@namespace <name> "<URI>";`) all element selectors with `<name>|<element-selector>` match only elements from that namespace.

    @namespace "bogus"; /* unnamed */
    @namespace aitchtee "http://www.w3.org/1999/xhtml";
    @namespace esvee "http://www.w3.org/2000/svg";
    * {  /* will not match anything, because "bogus" NS */ } 
    html {  /* also nothing, because "bogus" NS */ } 
    *|* { /* will match everything */ }
    aitchtee|title { /* will not match SVG title element, only the HTML one */ }
    aitchtee|*:root { /* will match html */ }
    esvee|* { /* all SVG elements */ }


Here are a couple quotes from https://developer.chrome.com/articles/css-nth-child-of-s/#pr... :

New in CSS Selectors Level 4 is the ability to optionally pass a selector list into :nth-child() and :nth-last-child().

For example, :nth-child(2 of .highlight) selects the second matching element that has the .highlight class. Put differently: out of all children with the class .highlight, select the second one.


10 years ago I created an algorithm to generalize CSS selectors based on applying the "sequence alignment" algorithm (from bioinformatics / string matching) to objects (bags of attribute / key values, ie, HTML elements). This let you select two or more examples and produce a selector that captures what you meant.

More here: https://github.com/00000o1/selector-generalization

There've been multiple attempts at such a thing over the years, but I like this approach for its essentially simple foundation in solid algorithms.

Be warned tho this code is old! I haven't yet got around to updating it to make it more "modern" etc!!


Updated link for the live example:

https://dosyago.github.io/selector-generalization/


THank you lazylion2! That's very kind of you!


Very nice, but some of the examples could do with more elements to indicate what is _not_ selected. For example, the "child selector" image could have some more "div"s which are descendants but not direct children of the ".wrapper" element.


Very cool. It seems to be missing the begins with and ends with selectors for the attr-val.

[title^=“old”]

and

[title$=“old”]


[title^=“old”]

and

[title$=“old”]

Once you get used to using these, and their relatives, you find all kinds of uses for them, like applying styles only to telephone links:

  a[href^="tel:"]


You can do [data-foo*="banana"] and trigger it by changing the dataset to something that contains banana.

https://jsfiddle.net/gaby_de_wilde/s729uk61/


Definitely, also, they're called CSS selectors but I use them a lot in javascript for query selection too.


I'm constantly amused by how often regular expression syntax can be found in all sorts of unexpected places. It really is foundational knowledge these days.

    ^ means match input start
    $ means match input end
Makes remembering the CSS selector syntax easier once you know that. (Or makes the regex syntax easier to remember?)


Regular selectors... (pun intended)


`* + *` works, but I think `:not(:first-child)` is a much clearer way of doing this. (Unless you need to support IE8 for some horrific reason?)


I assume the author is alluding to a certain blog post. https://alistapart.com/article/axiomatic-css-and-lobotomized...

To the point, the :not(:first-child) option should similarly be able to minimize the total number of rules.


`:not(:first-child)` has specificity 0.1.0 that is some orders higher than 0.0.0 of `* + *` (since `:first-child` is a pseudoclass), so you'd have to adjust anything that you'd need to override it with.

Strict equivalent of

    * + *
would be

   :where(:not(:first-child))


The ~ selector should be labeled "general sibling combinator" instead of "subsequent selector" (thanks for sharing!)


Amazing, nice curation. Had a look at the other blog posts, great work.


Wonderful. Note that :target works only after the whole page is loaded, including any JS. :has() is revolutionary, but unsupported by FF.


Nice!

Minor typo nit: the ::placeholder bold selector name has been copy-pasted in the sections for ::selection and ::marker.


Thanks for pointing that out, fixed it.


Fixed on ::marker, not on ::selection ;-)


I either forgot or never knew there's a difference between ".class1.class2" and ".class1 .class2" (without and with a space). I didn't even think the first is valid. That bit alone was worth the entire article for me.


Nice resource - very handy. I've shared with some slack groups I frequent and mentor in!


There's a lot of division between frontenders and non-frontenders. Project like this help making frontend concepts more accessible to other developers. Great way to make things simple here!


This is really cool and useful! I don't know a huge amount of CSS beyond the basics of tweaking sites via ublock origin or devtools, but this explained things clearly. Kudos!


What makes scrolling on this page so sluggish? (FF mobile)


It might be using a 'fuck-with-the-scrolling' JS library, like a few poor sites do here and there. Does it get better if you disable JS?


Really not sure what does that. Not using any JS scrolling library. Perhaps a performance hit from using backdrop-filter on the table of contents section for a background blur effect.


Are you on iOS or on Android? Are you using any ad filtering extension?

I checked on both FF and FF Focus on iOS and got regular scrolling behavior.


I'm using FF on android and had no issues scrolling.


+1


A great overview! Thanks for creating this :)


Now, create a similar page for XPath...


does anyone still use XPath nowdays?


XPath and XSLT are still active, especially in the publishing space where documents are not stored in HTML, but in other formats like JATS or DocBook and need converting to HTML when displaying to the user, or converting to other XML formats when interfacing with other formats/vendors like crossref. It's also still used for things like processing the US bill XML data (e.g. https://www.govinfo.gov/bulkdata/BILLS/resources).


Does anyone still use XML? I would imagine the answer to both is yes. I often wish JSON had something as good as xpath.


The `jq` command line tool has some neat expressions for selecting things from JSON. Not sure if it's a standard though.


Some typos regarding :placeholder pseudo selector - in the sections after (:marker)

Scrolling seems fine. Firefox on Pixel3


This is absolutely wonderful!


Will be so useful for me


Cool but also reminds me why I use inline styles for everything. I don't want to fiddle with selectors. I want to put the styling right on the element.


In a large app you often can’t easily find all of the html. It’s less work by far to ensure you can find all of the CSS though.

And when the company decides to rebrand and change the color scheme for the whole app, which they will at least half the time, you’ll be glad not to be playing whack-a-mole. Problems that aren’t done when you think they’re done create a lot of friction with the rest of the org. Open ended problems cause engineering to look incompetent. The cost of that problem is immeasurable, and doubly so in a bad economy.


> In a large app you often can’t easily find all of the html.

Which is often a warning sign of a bad design. The times I've dealt with systems that bury a certain piece of text in either a content file or a template or the database...

> It’s less work by far to ensure you can find all of the CSS though.

Hmm... depends. I've seen things like React embedding the CSS directly in with the markup and component logic etc. So this hasn't necessarily gotten any better — in fact, a site consisting JUST of html files would probably be easier to find CSS in even if it's all added via inline style attributes.


There are no clean designs on a large team. Anyone who tells you otherwise is selling something.

Zealots provide solutions that cannot possibly survive contact with actual humans. The rest of the team talks about them behind their backs.

> I've seen things like React embedding the CSS directly in with the markup and component logic etc.

You were talking about bad designs? Embedded styling is not Cascading Style Sheets. It’s embedded styling. There’s no sheet, and no cascade.

Nothing is free, and few things are easy. There are lines that are easier to maintain in practice than others, and separation of CSS is one of the former.


> Embedded styling is not Cascading Style Sheets

I think that's needless pedantry; the contents of the `style` attribute still needs to be valid CSS.


It’s not needless pedantry. Calling it CSS is using a crescent wrench as a hammer and calling it a hammer (a running joke on r/tools). You’ve missed the entire point and someone needs to remind you - and everyone listening in - what the point was.

We had in-line style before we had CSS. We are going back and nobody remembers why we’ve had CSS for twenty years? Read some history.


We're not in 2003, though. If you're working on a project with somebody and you insist they refrain from calling the contents of a style attribute CSS because it wasn't always technically CSS, nobody will thank you.

Edit: actually, even when I was working with CSS in 2003 (IIRC, we absolutely were using separate CSS files then), this attitude would have been unhelpful, to say the least.


How do you create reusable styles this way?


With components. Same thing as when isolating styles to a component in various frameworks (e.g. Single-File Components in Vue) but instead of its own style tags I just put the styling directly in the HTML.


modern JS has a bunch of half-assed scenarios for solving this problem that allows you to solve almost everything CSS did a few years ago and helps keep people stuck in ineffective legacy ways of doing it because all their code would have to be rewritten to use straight css.

I know because every place I've worked in the last few years uses some form of CSS in JS.


Every five years or so prior to CSS 3, there was a push to purge styling and animation decisions from JS. We are meant to be past that now.

Calling it a feature that you have CSS in your JS is tantamount to saying you’re writing legacy code. Which happens, but don’t be cheerful about it.


FWIW, these are useful for more than styling. I don't do any front-end dev work, but I use these regularly in selenium to find components in the page to interact with.


So you’re using S, not CSS


Presumably you never use hover styles, media queries, or quite a lot of other CSS features?


I use Tailwind when I need that.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: