Dynamically darken or lighten a color in CSS

Today I learned that you can now easily darken or lighten a color natively in CSS with the new color-mix function. Here’s a use case I run into a lot where you have a primary brand color and you need to darken it on hover: :root { --brand-color-dark: color-mix(in oklab, var(--brand-color), black 30%); --brand-color-light: color-mix(in oklab, var(--brand-color), white 30%); } .button:hover { background-color: var(--brand-color-dark) } This works by mixing the color with some amount of black or white. I also chose the oklab color space since it’s the most likely to produce what I’m expecting for this use case. ...

Smooth scrolling

Today I learned that you can now implement smooth scrolling purely with CSS in modern browsers. By adding the following CSS: /* Smooth scrolling IF user doesn't have a preference due to motion sensitivities */ @media screen and (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } } the browser will scroll smoothly whenever scrolling is triggered either by Javascript (with something like document.documentElement.scrollTop = 0) or by linking to elements with an internal anchor link. It’s considered best practice to use the prefers-reduced-motion media query to only enable things like animations to be mindful of users with motion sensitivities. In my testing, however, the browser won’t ever smooth scroll if the user has prefers-reduced-motion enabled. ...

Flow spacing and the lobotomized owl

This is another #til by proxy. A teammate asked about a CSS selector I used which has come to be referred to as the “lobotomized owl” (* + *): .flow > * + * { margin-top: var(--flow-space, 1em); } What this does is select every child element of the .flow class except the first one. You can also use newer CSS selectors to do the same thing in a way that might be more obvious: .flow > *:where(:not(:first-child)) { margin-top: var(--flow-space, 1em); } The above snippet is probably my favorite CSS utility called flow spacing. ...

`lh` and `rlh` units

Today I learned that there are new line height units in CSS. The lh unit is “equal to the computed value of line-height”. If nothing else this will be nice for a small annoyance I’ve run into before of vertically centering icons:

CSS Nesting

Today I learned that as of last month all modern browsers support css nesting! So instead of having to define styles like this: .header { background-color: blue; } .header p { font-size: 16px; } .header p span:hover{ color: green } you can instead do: .header { background-color: blue; p { font-size: 16px; span { &:hover { color: green } } } } This was the last feature of Sass that I used regularly that was missing from native CSS (CSS variables being the first big one that caused me to drop pulling sass into projects). ...

CSS accent-color property

Today I learned that browsers now support an accent-color property on some form inputs for customizing their color. This is especially nice for checkboxes and radio buttons because now I no longer need any workarounds I’ve used in the past to make a decent-looking checkbox. It will also ensure that it’s accessible by automatically adjusting the color of the check to an appropriate contrast: <input type="checkbox" class="yellow" checked /> <input type="checkbox" class="purple" checked /> <style> input { display: block; width: 30px; height: 30px; } input.purple { accent-color: rebeccapurple; } input.yellow { accent-color: yellow; } </style> ...

Stacking context affects z-index

In CSS, the stacking context can impact which elements display on top of each in addition to the z-index. So if you end up in a situation where cranking up the z-index doesn’t seem to work, the stacking context is likely the issue. I technically learned this a while ago but completely forgot about it until I was just reminded about it by a coworker dealing with this issue. Josh Comeau explains it well in his post on stacking contexts. ...