Well, I took the leap and bought Josh Comeau's CSS for JS developers course. Marketing works. Also because I read raving reviews and a co-worker spoke highly of it. Here is the list of stuff that I wish to remember, for my future self.
Module 0 - Fundamentals
- pseudo-classes, they target state: There are many of them. For instance:
:hover
,:focus
,:checked
,:first-child
(it needs to be the first child within its parent.) /:last-child (it needs to be the last child within its parent.)
,:first-of-type
/:last-of-type
.
Example Codepen pseudo-classes
- pseudo-elements, they target sub elements. They target elements in the DOM that we haven't explicitly created with HTML:
::placeholder
,::before
/::after
(they are secret spans, syntactic sugar).
Example Codepen pseudo-elements
- Combinators (from "combines" multiple elements to create a
descendant selector
). It's about descendants, no matter how deep they are located: i.e.nav a
(space between selectors - targets any descendant),nav > a
(great than sign - targets only direct children).
- Colors. 4 representations of color: name, hexadecimal,
rgb
(red, green, blue) andhsl
(hue, saturation, lightness). He recommendshsl
, and it is clear why: it's very intuitive.hue
is the pigmentation, in a circle, defined by degrees from 0 to 360. Saturation is the x axis and lightness is the y axis, both represented by %s. You can pass a final value, separated with a/
for the opacity (between 0 [fully transparent] and 1 [fully opaque]). Like so:rgl(45deg 37% 45% / 0.75
)
- Units:
px
,em
andrem
(root em). We all know pixels.em
is relative the to font size of the current element.rem
is relative to the font size of thehtml
tag.
- Typography.
font-weight
can bebold
or a value between0
and1000
.line-height
value is unitless (i.e.15
, NOT15px
or15em
). As per accessibility guidelines, it should be at least1.5
. This number is multiplied by thefont-size
of the element.
Module 1 - Rendering logic
- Inheritance. Some properties inherit and other not, an attempt to a list can be found here. The ones that inherit are mostly typography related. You can inherit in properties that do not by explicitly inheriting a property.
- Cascade. It's like spread syntax in JS:
const appliedStyles = {
...inheritedStyles,
...tagStyles,
...classStyles,
...idStyles,
...inlineStyles,
...importantStyles
}
That's a pretty damn good analogy 👏
Block and inline directions. Block like Lego blocks, stack vertically. Inline, like people queuing in line, horizontally. Logical properties replace the usual top right bottom left because they offer support for non ltr languages.
Box model, like layers of clothes in winter:
content
(the person),padding
(the stuffing),border
(the material, which has a color, etc) andmargin
(personal space). By defaultbox-sizing
iscontent-box
, which means that if width is 100% of the parent, this only affects the content of the child. Border, padding and margin are added on top.border-box
includes content, padding, border and margin, see Codepen below.
This is a good CSS reset:
*,
*::before,
*::after {
box-sizing: border-box;
}
- Padding vs outline.
padding
affects the layout.outline
does not, it's a decorative layer on top of the element.outline
follows the curve ofborder-radius
except in Safari. It also has anoutline-offset
to add space between the outline and the element.
- Margins. They can be negative. You can use
auto
for horizontal margins, which seeks to fill the maximum amount of space available. For vertical margins, it is the same as0px
. And it only works if the element has an explicit width. Margin can also be negative - it will shift the rest of the content. Very cool trip on how to make an image in a blog expand to the edge even though the container has padding, check out the codepen below.
- Flow layout. Default layout mode. 2 type of elements:
Block elements
(list here) andInline elements
(list here). We can toggle the mode with thedisplay
property.Inline elements
can have margin left and right, but not vertical.inline-block
is a block element that can be inlined in terms of layout but internally acts much more like a block element.
- Width algorithms. Block elements have width
auto
by default. These elements will grow as much as they can.100%
take the parent width, but if you have margins they are added on top. Keyword values:min-content
(takes minimum content, the longest word. So the element is as narrow as it can be),max-content
(takes the max, the whole content. So it is as wide as it can be, doesn't care about the available space. If the content is short, it may be narrower than the available space),fit-content
fits whatever length, and if content is longer than the available space, it moves to next line - likewidth: auto
.
- Height algorithms.
height
will shrink to the height of its content, likemin-content
in width we saw before. Setting height as precise unit is not a good idea. If you want to take 100% of the screen, you need to set the element height to100%
but also the parent one, like so:
html, body {
height: 100%;
}
Otherwise, having an element being 100% of the parent, which also shrinks to fit the content, doesn't make sense. vh
is not recommended because of mobile devices.
- Margin collapse. Only vertical margins collapse. Only in Flow layout. Only adjacent elements. If margins are asymmetrical, the bigger one wins. Nesting doesn't prevent it. Margins only collapse when they are touching. They don't collapse when: there is a padding or border in between, there is a gap, or there is a scroll container. Margins can collapse in the same direction. More than 2 margins can collapse. Negative margins also collapse, with the same rule: the biggest wins i.e. in -40px vs -50px -50px wins.
Module 2 - Rendering logic II
Positioned layout
, the second layout mode we are looking at. The default value forposition
isstatic
orinitial
.Relative positioning
. Settingposition: relative
and adjusting withtop
,right
,bottom
,left
moves the element without impacting the layout of the rest of the elements of the page. This is the difference from theFlow layout
and itsnegative margin
. A block element that, without width, would take the available space and gets reduced when margin is applied, it would not change width withrelative
positioning.
-
Absolute positioning
. Positioned based on their container, not their in-flow position (that wasrelative
). In terms of layout, the elements doesn't exist anymore ("it's like a ghost, you can stick your hand through it"). So 3 absolute positioned elements in the same position will stack on top of each other. Default placement without top, left, etc. is the place where it would go if it were not positioned or if it was positioned relative.position: absolute
makesdisplay
property irrelevant. The size is the smallest as it can get. The max it will get is the view port, beyond that it will line wrap. If it can't line wrap, the container will comply but the content will overflow.
Codepen
Codepen 2 - centering trick with position: absolute and margin: auto
-
Containing blocks
- inflow layout
the containing block is its parent. Inpositioned
elements, its containing block is the closest parent that usespositioned layout
. Andpadding
doesn't count. Exercise 2 video in the lesson contains an interesting explanation for usingrem
and not%
for the border-radius.
Codepen
Exercise 1 Codepen
Exercise 2 Codepen
-
Stacking contexts
. InFlow layout
, the DOM order matters - whatever comes last, is on top. But the content is painted separately from border and background - the content will float on top. Positioned elements will always render on top of non-positioned ones, no matter the DOM order. If all elements are positioned, DOM order wins (last element on top).
z-index
overrides the default behaviour (default behaviour === last DOM element on top). It only works with positioned elements. z-index
won't work with the Flow layout
.
A stacking context
is created when an element is positioned and it has a z-index
value. A stacking context means that the z-index's are compared between the children of this stacking context, they are not global. There are more ways to do so, explained in the lesson and in mdn. If the parent has a stacking context and is below another element, there is nothing a child can do with z-index to override it. So if an element with a high z-index is still below another element, is probably because the element is inside a stacking context. You may want to remove that stacking context so the child can be compared at the same level as the other element.
-
isolation: isolate
will create a stacking context - no need to position + z-index.
-
fixed positioning
. Same asabsolute
but they can only be contained by the view-port and they are immune to scrolling. When not anchored (this is, notop
,left
, etc. positioning) it sits in its natural position, like absolute. But can't be scrolled ofc. Certain css in the parent components will mess with the fixed positioning, mostlytransform
and related ones. The lesson has a lot of info on how to deal with this.
-
overflow
. When content does not fit in the container.visible
by default,scroll
,auto
(recommended - adds a scroll when needed),hidden
(truncates everything that overflow).overflow
is a shorthand foroverflow-x
andoverflow-y
. Windows and Mac have different defaults for scrollbars: Mac vertical, Windows vertical and horizontal, but Mac w mouse shows horizontal as well.
Websites / Blog posts I learnt about along the way
Module 0
- https://a11y.coffee/
- https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/
- https://courses.joshwcomeau.com/css-for-js/treasure-trove/010-global-styles
- Default CSS in Chrome