Joshua's Docs - CSS and General Styling - Cheatsheet, Common Issues, Etc.


UI Inspiration

Different frameworks and tools


CSS Transitions


div {
	transition: <property> <duration> <timing-function> <delay>;


div {
	transition: all 2s ease 1s;

CSS Transitions - Multiple Properties Shorthand

To declare transitions for multiple properties, with shorthand, you have two main options:

1 - Comma separate shorthand declarations:

.myClass {
	transition: width .5s linear, color .5s ease-in-out;

2 - Overrides

.myClass {
	/* Unlike the above method, this requires all props to share common base settings  */
	transition: all .5s linear;
	/* This overrides the `all` from above */
	transition-property: width, color;

I found this out, thanks to this S/O answer

CSS Transitions - Common Things to Remember

  • You can target transform as a property to transition

    • You can use this to build a scaling transition, for example

Extracting CSS

Kind of weird that this isn't baked into browsers, although it looks like it was supposed to be at some point. There are browser extensions though, like Snappy Snippet.

Globals, variables, and theming

Can I use: Browser Support. Note that IE 11 has no support. You can use something like webpack to transform the dynamic variables refs into static. See this. Or you can simply define the CSS value twice, first with a non-variable value that will be the fallback, and then with the variable. On older browsers it should just use the non-variable fallback.

CSS variables (more accurately custom properties) are notated with a double-dash prefix. You can declare them at multiple levels, and are inherited from parents (scoped).


.vendorWidget {
	--primaryColor: red;
	--secondaryColor: blue;
.vendorButton {
	background-color: var(--primaryColor);


<div class="vendorWidget">
	<button class="vendorButton">Click Me!</button>

To emulate theming, a common approach is to declare global variables at the highest level. In CSS, there is a trick you can use instead of guessing the element with the highest specificity: just target :root. (MDN).

:root {
	--loosePaddingPx: 14px;
	--tightPaddingPx: 4px;
	--primaryColor-light: #BEFFFF;
	/* You can mix vars and non-vars */
	background-color: red;

CSS Variable Fallbacks:

You can define a fallback in case a variable is undefined:

.myButton {
	background-color: var(--myVar,red);

If you want to try a few different vars, and keep falling back if undefined, you can nest them:

.myButton {
	background-color: var(--myVar,var(--secondaryVar,red));

Note that fallbacks are not the same as polyfilling or providing defaults for if a browser does not support custom properties. You can use a polyfill library to do that, or repeat each property twice, first with a default fallback, and then with the variable, like so:

.myButton {
	background-color: red;
	background-color: var(--myVar,var(--secondaryVar,red));

Using CSS Variables in RGBA Color Properties

The easiest way (currently) to define CSS variables in a way that supports using them with rbga(), so you can easily tweak alpha, is to declare them like so:

.selector {
	--cta: #1a83d6;
	/** This is the RGB of the above HEX value */
	--ctaRGB: 26, 131, 214;

By declaring a separate version of the variable that has the RGB values as comma separated integers, you can easily pull it into places with RGBA:

.selector button {
	/** Use cta color, with half opacity */
	background-color: rgba(var(--ctaRGB), 0.5);

📄 For a more detailed look into this approach, check out this blog post

Creating Derived Colors From CSS Variables

CSS lacks built-in functions to manipulate color objects (like darken() in SASS), but with some creative variable declaration, you can get around this. By splitting up your color value into its separate parts (either H-S-L or R-G-B), you can later combine them and manipulate them with ease.

:root {
	--primary: #e1e0ff;

Or, if you wanted to be able to manipulate this color in any way you want:

:root {
	/** It is a good idea to still have the full HEX as a value */
	--primary: #e1e0ff;
	/** RGB */
	--primary-r: 225;
	--primary-g: 224;
	--primary-b: 255;
	/** HSL */
	--primary-h: 242;
	--primary-s: 100%;
	--primary-l: 94%;

Now, coming up with some derived colors is much easier:

  • Equivalent to SASS's darken($primary, 20%)

    • --primary-dark-20: hsl(var(--primary-h), var(--primary-s), calc(var(--primary-l) - 20%));
  • Equivalent to SASS's lighten($primary, 5%)

    • --primary-light-20: hsl(var(--primary-h), var(--primary-s), calc(var(--primary-l) + 5%));
  • Changing opacity on the fly (example: half opacity)

    • --primary-opaque-50: rgba(var(--primary-r), var(--primary-g), var(--primary-b), 0.5);
    • See above section too:

Here are some great resources on using CSS properties in this way (and more advanced) ways:

Theme Switching

There are a bunch of ways to accomplish this. I've written up a comprehensive exploration of options at

Accessing CSS Variables with JavaScript:

 * === Setting Values ===

// This will target :root variables
document.querySelector(':root').style.setProperty('--myColor', newColor);
// Or, same thing...'--myColor', newColor);

 * === Reading Values
// Or, for computed values


Targeting the first element of something

First child, regardless of type

Use the :first-child pseudo class / selector.

.parent div:first-child {
	border-top: 1px solid black;
.parent div {
	border-bottom: 1px solid black;

The above code is nice because it gives both top and bottom borders to only the first element, and then bottom borders to the rest. If I added top and bottom to all children, then elements after the first would end up with double borders (the tops and bottoms would combine).

Note: this requires that the targeted element is a direct child of the parent selector

First child of certain element type

If we have a bunch of mixed element types, first-child would both not make sense, and might not work too. Consider this kind of setup:

<div class="root">
	<div class="abcd">
		<div>I'm the first child of abcd</div>
		<!-- Element below is my actual target -->
		<span class="target">Hello</span>
	<span class="target">World.</span>
	<span class="target">How are you?</span>
.target {
	background-color: blue;

Let's say I wanted to make the first <span> have a red background, but all the rest have blue. I can't use first-child, because it is not the first child of div.abcd. I could use the nth-child() rule, like .abcd .target:nth-child(2) { background-color: red; }, but that would require that the order always stay the same. What if I add another div in front of it?

A better option is the newer :first-of-type pseudo selector:

.abcd span:first-of-type {
	background-color: red;

Note that by type, the rule is referring to the type of element, not a selector. If you try to do something like abcd .target:first-of-type, it won't work, because .target is a class selector, not a type of element.

Unusual / Fun selectors to remember

Code What Notes
div[data-ref*="23"] Attribute Selector See "Attribute Selector Cheatsheet" below
:not(___) Negation pseudo-class selector Use to select those elements not matching selector

You can use multiple comma separated selectors, just like normal

Cannot nest other pseudo-selectors

Attribute Selector Cheatsheet

Full list and details on MDN.

Short Practical Example What
{elem}[attr] or [attr] script[async] Matches any input that has attribute of id, regardless of value
[attr="value"] script[src=""] Attribute must exactly match value
[attr*="value"] script[src*="analytics"] Attribute must contain value
[attr~="value"] [data-color-scheme~="red"] Attribute must be a string of whitespace separated words, and the value must exactly match one of them.
[attr^="value" script[src^=""] Attribute must start with exact value
[attr$="value"] script[src$="analytics.js"] Attribute must end with exact value
[attr|="value"] script[src|=""] A little odd. Attribute must either exactly match, or start with value and be immediately followed by hyphen (-)

Note: You can add i before the closing brackets to force a case insensitive match. Like: script[src*="gOOgle"i]

Note: You can target by any attribute, including value. This has led to a notable CSS-only hack (HN) that can listen for specific characters and report back to an external server (bad for password fields!). Note, this only works if JS is updating the value attribute as the user types. In an "uncontrolled" field, this doesn't work.

Question: [attr~="val"] vs [attr*="val"]

Since the description for [attr~="val"] can be a little confusing, here is a very simple demonstration of its difference and the value it brings - a table of matches:

DOM [animals*="cat"] [animals~="cat"]
<div animals="dog cattle bird"> Yes No
<div animals="dog cat bird"> Yes Yes

Grid Layout

Some tools:

Flexbox Layout

Flexbox Tools

These are tools that help with building, debugging, and understanding flex based layouts.

Flexbox Use Cases

These are collections of use-cases showing how Flexbox can be used to solve common design problems

Aligning Items in Flex Layouts

Aligning single items in a flex layout can be a little confusing, especially since there is no justify-self property. However, this StackOverflow response is one of the best summaries of different axis alignment scenarios and how to implement them.

Flexbox Frameworks

  • Flexbox Grid

    • Micro-framework, based on Flexbox, which provides handy 12-column system

Boilerplate CSS

Common Breakpoints

A lot of frameworks share (roughly) the same set of breakpoints. These will probably change as displays get larger and have higher-resolution, but for now, this is a decent starting point. You'll notice that max-width is not used to cap the higher end of the range; this is because you often want a class to kick in at a minimum width, but stick unless overridden by another (for example, using something like class="xs4 sm2" for columns).

/* Extra Small (xs) */
/* < 600px */

/* Small (sm) */
@media (min-width: 600px) {

/* Medium (md) */
@media (min-width: 960px) {

/* Large (lg) */
@media (min-width: 1280px) {

/* Extra Large (xl) */
@media (min-width: 1920px) {


Smooth Scroll with CSS Only

/** Smooth Scroll - CSS Only! */
html {
	scroll-behavior: smooth;
@media screen and (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
Markdown Source Last Updated:
Sun Jan 17 2021 18:11:57 GMT+0000 (Coordinated Universal Time)
Markdown Source Created:
Mon Aug 19 2019 17:06:24 GMT+0000 (Coordinated Universal Time)
© 2021 Joshua Tzucker, Built with Gatsby