kota's memex

global

In general it's best to build up complex layouts with small components (rather than using inheritance), but not all styles should be strictly component based.

:root {
  /* Now almost all elements display a sans-serif font */
  font-family: sans-serif;
}
* {
  /* Now literally all elements display a sans-serif font */
  font-family: sans-serif;
}

Element selectors are more specific, as they only target the elements they name, but they are still "global" because they can reach those elements wherever they are situated.

p {
  /* Wherever you put a paragraph it'll be sans-serif */
  font-family: sans-serif;
}

These element selectors help build up a comprehensive design system which could be produced by static site generators or WYSIWYG editors.

utility classes

While not needed for simpler sites these can be useful at times. Take for example a site like this:

h2 {
  font-size: 2.25rem;
}

h3 {
  font-size: 1.75rem;
}

.sidebar h2 {
  font-size: 1.75rem;
}

We don't want to make nonsense of the document structure by switching the sidebar <h2> to an <h3>, so we instead add a more specific selector. We've solved the problem for this specific element, in a specific context, but we may in the future prefer to be able locally decrease the font-size on other elements:

/* Backslash to escape the colon */
.font-size:\biggish {
  font-size: 1.75rem;
}

Use these with moderation however as it's easy to add too many and bloat the page size (with unused rules) and make the html complex and ugly with loads of classes (such as you see with utility class libraries like tailwind). You don't really want to be simply writing your styles into the html directly.

We can make our new custom properties globally available by attaching them to the root element as variables instead:

:root {
  --font-size-base: 1rem;
  --font-size-biggish: 1.75rem;
  --font-size-big: 2.25rem;
}

/* elements */

h3 {
  font-size: var(--font-size-biggish);
}
h2 {
  font-size: var(--font-size-big);
}

/* utilities */

.font-size\:base {
  font-size: var(--font-size-base) !important;
}

.font-size\:biggish {
  font-size: var(--font-size-biggish) !important;
}

.font-size\:big {
  font-size: var(--font-size-big) !important;
}

Each class has !important to max out it's specificity. Utility classes are only for final adjustments and should not be able to be overridden.

One approach to avoiding utility class bloat is keeping a helpers.css file in your repo, but not ever sending it to the client. You can store all your favorite utility classes inside it and if you find yourself trying to use one and it not working simply copy it from helpers.css to your live css file for usage!