[wip] CSS for JS developers
Tags: css
Published: 2022-11-26 16:02:18

Well, I took the leap and bought [Josh Comeau's CSS for JS developers course](https://css-for-js.dev/). 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](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) 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](https://codepen.io/petrussola/pen/XWYYjJe)

- 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](https://codepen.io/petrussola/pen/GRGGjzo)

- 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).

[Codepen](https://codepen.io/petrussola/pen/rNKKWBq)

- Colors. 4 representations of color: name, hexadecimal, `rgb` (red, green, blue) and `hsl` (hue, saturation, lightness). He recommends `hsl`, 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`)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1kq7pjjl0ile9y38aol.png) 

[Codepen](https://codepen.io/petrussola/pen/VwddbqP)

- Units: `px`, `em` and `rem` (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 the `html` tag.

[Codepen](https://codepen.io/petrussola/pen/bGKKWyj)

- Typography. `font-weight` can be `bold` or a value between `0` and `1000`. `line-height` value is unitless (i.e. `15`, NOT `15px` or `15em`). As per accessibility guidelines, it should be at least `1.5`. This number is multiplied by the `font-size` of the element.

[Codepen](https://codepen.io/petrussola/pen/VwddqdN)

####Module 1 - Rendering logic

- Inheritance. Some properties inherit and other not, an attempt to a list can be found [here](https://www.sitepoint.com/css-inheritance-introduction/#list-css-properties-inherit). The ones that inherit are mostly typography related. You can inherit in properties that do not by explicitly inheriting a property.

[Codepen](https://codepen.io/petrussola/pen/rNKrGWZ)

- Cascade. It's like spread syntax in JS:

```
const appliedStyles = {
  ...inheritedStyles,
  ...tagStyles,
  ...classStyles,
  ...idStyles,
  ...inlineStyles,
  ...importantStyles
}
```

That's a pretty damn good analogy :clap:

- Block and inline directions. Block like Lego blocks, stack vertically. Inline, like people queuing in line, horizontally. [Logical properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_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) and `margin` (personal space). By default `box-sizing` is `content-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;
}
```

[Codepen](https://codepen.io/petrussola/pen/LYrJpNG)

- Padding vs outline. `padding` affects the layout. `outline` does not, it's a decorative layer on top of the element. `outline` follows the curve of `border-radius` except in Safari. It also has an `outline-offset` to add space between the outline and the element.

[Codepen](https://codepen.io/petrussola/pen/mdKGeXq)

- 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 as `0px`. 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.

[Codepen](https://codepen.io/petrussola/pen/QWxVjBY)

- Flow layout. Default layout mode. 2 type of elements: `Block elements` (list [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements)) and `Inline elements` (list [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements)). We can toggle the mode with the `display` 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.

[Codepen](https://codepen.io/petrussola/pen/LYrgOZP)

- 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 - like `width: auto`. 

[Codepen](https://codepen.io/petrussola/pen/ZERmbOR)

- Height algorithms. `height` will shrink to the height of its content, like `min-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 to `100%` 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. 

[Codepen](https://codepen.io/petrussola/pen/QWxJqrE)

- 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.

[Codepen](https://codepen.io/petrussola/pen/VwdVgVg)

####Module 2 - Rendering logic II

- `Positioned layout`, the second layout mode we are looking at. The default value for `position` is `static` or `initial`.

- `Relative positioning`. Setting `position: relative` and adjusting with `top`, `right`, `bottom`, `left` moves the element without impacting the layout of the rest of the elements of the page. This is the difference from the `Flow layout` and its `negative margin`. A block element that, without width, would take the available space and gets reduced when margin is applied, it would not change width with `relative` positioning.

[Codepen](https://codepen.io/petrussola/pen/poKYvba)

- `Absolute positioning`. Positioned based on their container, not their in-flow position (that was `relative`). 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` makes `display` 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](https://codepen.io/petrussola/pen/gOKEbKW)
[Codepen 2 - centering trick with position: absolute and margin: auto](https://codepen.io/petrussola/pen/NWBxvOv)

- `Containing blocks` - in `flow layout` the containing block is its parent. In `positioned` elements, its containing block is the closest parent that uses `positioned layout`. And `padding` doesn't count. Exercise 2 video in the lesson contains an interesting explanation for using `rem` and not `%` for the border-radius.

[Codepen](https://codepen.io/petrussola/pen/MWBKvRq)
[Exercise 1 Codepen](https://codepen.io/petrussola/pen/LYBNJwK)
[Exercise 2 Codepen](https://codepen.io/petrussola/pen/eYjZPNL)

- `Stacking contexts`. In `Flow 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). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdllmx9sp53ctprnwac6.png)

`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`. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ays9uwa7pktoydjlqqif.png)

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](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context). 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.

[Codepen](https://codepen.io/petrussola/pen/MWByPvz)

- `isolation: isolate` will create a stacking context - no need to position + z-index.

[Codepen](https://codepen.io/petrussola/pen/PoBNyXO)

- `fixed positioning`. Same as `absolute` but they can only be contained by the view-port and they are immune to scrolling. When not anchored (this is, no `top`, `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, mostly `transform` and related ones. The lesson has a lot of info on how to deal with this.

[Codepen](https://codepen.io/petrussola/pen/ExpgGag)
[Bonus Codepen](https://codepen.io/petrussola/pen/RwBGEKB?editors=1100)

- `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 for `overflow-x` and `overflow-y`. Windows and Mac have different defaults for scrollbars: Mac vertical, Windows vertical and horizontal, but Mac w mouse shows horizontal as well.

[Codepen](https://codepen.io/petrussola/pen/abjJNaq)

####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](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/resources/html.css)

#####Module 1

- https://courses.joshwcomeau.com/css-for-js/treasure-trove/008-pixel-measurement

- https://wattenberger.com/blog/css-cascade

#####Module 2

- https://github.com/andreadev-it/stacking-contexts-inspector
- https://courses.joshwcomeau.com/css-for-js/treasure-trove/012-component-libraries