TODO: set up a page header

My web development stream of conciousness

This page contains practical demos of web development techniques that I enjoy using, but regularly forget. The order is not (entirely) arbitrary, it's the order I encountered the concepts as i was construction this site. Tres meta, no.

The term HTML5 is essentially a buzzword that refers to a set of modern web technologies mdn web docs

By using the right semantic elements in my HTML I get more maintainable code, and a cleaner Accessibility tree. In this page I am using the following structure.

<html>
<body>
    <main>
        <!-- summary content -->
        <article>
            <!-- article content -->
        </article>
        <article>
            <section>
                <!-- section content -->
            </section>
            <!-- repeat as needed -->
        </article>
        <!-- repeat as needed -->
    </main>
</body>
</html>

In the same way there should only be one <h1> on a page there should also only be one <main>. On the other hand <article> and <section> repeat as needed. In some cases (like this one you are reading) an article isn't large enough to need to be broken down any further.

In each article or section I use the following:

An of course the classics (<p>, <a>, <ul><li>, <em>, <strong>, etc.), for article introductory text and for section content.

Colours

Picking Colours

Let's be honest, picking colours is hard and subjective. I could use colour theory, I could pick colours directly from my site images, I could scry the hex codes using tealeaves in a dainty china cup. Whatever approach I took, someone wouldn't like the end result (probably me).

To distract myself from the above I often start with the basics: black and white. Easy right? There are even named CSS colours for them. But they can be a bit harsh, and sometimes difficult are harsh so I use these instead:

  • hsl(0 72% 7%) a tiny bit softer than a true black; and
  • hsl(240 100% 99%) a.k.a Ghost White
Ghost White is your go-to for a hint of coolness, like a gentle whisper compared to the shout of pure whiteAlternative colors for pure white in UI/UX design

From there I move on to (other peoples) brand colours. These can be easy; someone, somewhere has already put in the effort of picking the colours and (usually) deciding on the light and dark variants. For example on this page there are two brand logos:

  • The HTML5 logo by W3C, they use hsl(12 77% 52%) and hsl(18 87% 55%) in their logo.
  • a CSS logo by the CSS-Next Community Group, they use rebeccapurple in honour of the daughter of Eric A. Meyer

So... having sufficiently distracted myself with black, white and other peoples colours and spent longer than either I meant to or was reasonable researching colour psychology, I picked purple because I like it and pink because it's fun.

  • hsl(279 63% 50%) the base "hero" colour used for headings, link hover states, and the background for <blockquotes>.
  • hsl(330 100% 50%) the accent colour used for un-hovered link text, asides and other accenting

That's it, done! Now onto the next subject, right? Right...?

Colour contrast

Not so fast. Colours are all well and good, but contrast is key to making a site readable, what looks good to me might be hard to read for someone with a vision impairment; what looks awesome on a 40" 5K monitor in indirect morning light might be unreadable on a 5.5" phone with harsh sun on it.

Following the WGAC contrast guidelines I aim for a AAA contrast ratio of 7:1 or better. While this is not technically necessary for larger text (which can be as low as 4.5:1), I find the higher ratios visually pleasing.

Although brightness isn't the only factor in contrast, I find it easiest to start my thinking there, which is why I use the hsl() colour space. Then to check the contrast ratio of any given colour pair, I use the contrast ratio checkeroriginally created by Lea Verou. It works with multiple colour spaces and supports using the up and down arrows to adjust individual values.

Honoring user preference

I like dark mode, I use it on all my devices, I develop and preview in dark mode, but I don't want to impose that preference on the visitors to å site. To do this I:

  • Setting color-scheme: dark light; on the html element so that the browser adjusts the default colors of scrollbars and other interaction UI, and the default colors of form controls.
  • Using the light-dark() function to adjust my site colours.
  • TODO: Provide a switcher to toggle between light and dark mode

Modifying base colours

Once I've picked my base colours it's time to apply the necessary modifications to meet the contrast goals, honour the user preference, and apply my custom colours. I start with custom properties for my base colours.

:root {
    --hero-base: hsl(279 63% 50%);
    --accent-base: hsl(330 100% 50%);
}

I don't often use these directly, but they are the anchor for everything else. Next I meed to modify these base colours making each brighter for the dark theme and darker for the light theme.

Thankfully CSS has a way to build new colours from existing ones: color(from ...) allows us to clone and modify colours by specifying which properties we want to keep and which we want to change or add.

For the light theme I darken my two colours by reducing their lightness value, for the dark theme i lighten them in the same way. I leave the hue and saturation alone by using the placeholder letters h and s.

Light theme:

  • hsl(from var(--hero-base) h s 35%) from to
  • hsl(from var(--accent-base) h s 33%) from to

Dark theme:

  • hsl(from var(--hero-base) h s 75%) from to
  • hsl(from var(--accent-base) h s 69%) from to

Not huge changes, but enough to make them more readable on their respective backgrounds.

Bringing it all together

First up I apply my "not quite" black and white to the background and text of the whole page (I use custom properties to make it easier to change them later if I need to)

:root {
    /* almost black */
    --black: hsl(0 72% 7%);
    /* not quite black */
    --white: hsl(240 100% 99%);
    /* hero colours */
    --hero-base: hsl(279 63% 50%);
    --hero-dark: hsl(from var(--hero-base) h s 35%);
    --hero-light: hsl(from var(--hero-base) h s 75%);
    --hero-colour: light-dark(var(--hero-dark), var(--hero-light));
    /* accent colours */
    --accent-base: hsl(330 100% 50%);
    --accent-dark: hsl(330 100% 33%);
    --accent-light: hsl(330 100% 69%);
    --accent-colour: light-dark(var(--accent-dark), var(--accent-light));
}

html {
    /* honour the user preference */
    color-scheme: dark light;
}

body {
    /* soften the default black and white */
    background-color:light-dark(var(--white)), var(--black);
    color: light-dark(var(--black), var(--white));
}

h1,h2 {
    /* use the hero colour for headings */
    color: var(--hero-colour);
}

a {
    /* use the accent colour for links */
    color: var(--accent-colour);
    /* use the hero colour for link underlines */
    text-decoration-color: var(--link-hover-colour);
    
    &:hover,
    &:focus-visible {
        /* to give a visual change on hover */
        color: var(--link-hover-colour);
    }
}

/* ... */

References