Start with “Why”: why practice selectors?
I think it’s important to understand why we need selectors in the first place. The answer is simple - to select specific elements in the DOM so we can style them the way we want.
I think that building good semantic HTML is the first step to writing good CSS, and that knowing how I’ll end up selecting elements will impact how I structure the HTML itself.
CSS Diner Writeup
Like any other writeup, be warned - spoilers ahead! If you want to try it out yourself, go to CSS Diner before reading this.
Just the name of the element (e.g. “Input”).
With a space between the parent and descendant,
This was very interesting to me: every
. (and later on:
operator withing a selector is a logical AND. For example,
level 7’s solution is:
Translates to, in logical notation:
$$ orange\space\land\space.small $$
And after the \(\land\) operator, we get the \(\lor\) (Logical OR) operator
* matches any element.
Adjacent sibling - with a
+. This was the first new thing I learned so
This selects all B elements that directly follow A. Elements that follow one another are called siblings. They’re on the same level, or depth.
plate + apple
I didn’t understand why we need this, so I asked ChatGPT for some use cases, and got some interesting answers. One that Aviv suggested was a gradient effect on hover. Some that ChatGPT suggested:
- Apply a different style to the first item in a list
- Create a custom-styled checkbox
- Highlight the current item in a navigation menu
- Style an input field based on user interaction
- Apply specific styles to adjacent table cells
This is a great example, IMO, of using LLMs as a learning partner. 🤖
Then we learned about the general sibling selector:
bento ~ pickle
A > B. The difference from
A B is that
> only selects direct
plate > apple
First child pseudo-selector:
:first-child. I’m not super sharp on what are
pseudo-selectors, so I read about it.
plate > orange:first-child
Only child pseudo-selector:
plate > *:only-child. You can also solve it with
plate :only-child, and we weren’t sure which one is better.
Finally, last-child pseudo-selector:
Nice tip from the diner:
Pro Tip → In cases where there is only one element, that element counts as the first-child, only-child and last-child!
Nth child pseudo-selector:
:nth-child(). This one is a bit more complicated,
since it takes a parameter.
Nth last child pseudo-selector:
:nth-last-child(). This one is the same as
:nth-child(), but counts from the end.
Something we both failed to understand is why
work in this case, but
The reason is that the children selectors are type-agnostic.
Something cool about
nth is that you can use interesting “formulas” to select
elements. For example,
even and \( A \times n + B \) :
More pseudo-selectors for more edge cases:
 syntax is used for attribute selectors. For example,
will select all elements with
type="radio". Seems like class and ID selectors
are just a special case of attribute selectors. For example,
#fancy can be
Attribute starts with! That’s new to me as well! 🆕
Yay! We finished the diner! 🎉 Seems like we rock at CSS.
Never stop learning! Even though I know CSS, I still learned a few new things:
- Adjacent sibling selector
- General sibling selector
- Thinking about CSS selectors in terms of logical AND and OR
Also, thanks Aviv! It was fun. 🍱🥢