Learning CSS #2: CSS Diner Writeup π±π₯’
Met up with Aviv Sarig to practice some CSS. I found CSS Diner and we went through it to hone our CSS selection skills.
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.
type selectors
Just the name of the element (e.g. “Input”).
π
plate
π±
bento
ID selectors
With a #
.
#fancy
Descendant selectors
With a space between the parent and descendant, A B
.
plate apple
#fancy pickle
Class selectors
With a .
.
.small
Combining selectors
This was very interesting to me: every #
, .
(and later on: :
and []
)
operator withing a selector is a logical AND. For example,
level 7’s solution is:
orange.small
Translates to, in logical notation:
$$ orange\space\land\space.small $$
bento orange.small
Comma combinator
And after the \(\land\) operator, we get the \(\lor\) (Logical OR) operator
with ,
.
plate, bento
* selector
*
matches any element.
*
plate *
Sibling selectors
Adjacent sibling - with a +
. This was the first new thing I learned so
far!
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
Child selectors
With A > B
. The difference from A B
is that >
only selects direct
children.
plate > apple
Children pseudo-selectors
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: :only-child
.
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: :last-child
.
.small:last-child
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.
plate:nth-child(3)
Nth last child pseudo-selector: :nth-last-child()
. This one is the same as
:nth-child()
, but counts from the end.
bento:nth-last-child(3)
Something we both failed to understand is why bento:nth-last-child(2)
doesn’t
work in this case, but bento:nth-last-child(3)
does.
The reason is that the children selectors are type-agnostic.
apple:first-of-type
Something cool about nth
is that you can use interesting “formulas” to select
elements. For example, even
and \( A \times n + B \) :
plate:nth-of-type(even)
plate:nth-of-type(2n+3)
More pseudo-selectors for more edge cases:
plate apple:only-of-type
apple:last-of-type, orange:last-of-type
bento:empty
apple:not(.small)
Attribute selectors
The []
syntax is used for attribute selectors. For example, [type="radio"]
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
written as [id="fancy"]
.
[for]
.
plate[for]
.
[for="Vitaly"]
Attribute starts with! That’s new to me as well! π
[for^="Sa"]
[for$="ato"]
[for*="obb"]
Yay! We finished the diner! π Seems like we rock at CSS.
Summary
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. π±π₯’