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.
HTML
semantic elements
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.
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:
<h2> | <h3> for
article or section headings respectively. In most cases these are linked by their id to their parent via the aria-labelledby property of the parent, but in cases where they
contain icons I instead make them aria-hidden and use an aria-label on the parent
<blockquote> for quoting and attributing external sources
<aside> for whimsy and hints.
<pre><code> | <code> for code snippets. These
are styled using PRISM by Lea Verou.
<i> for Font
Awesome icons. This is a bit of a controversial one. <i> used to mean italic, but now I tend to use <em> for that. Strictly it now means Idiomatic
Text, but I (and a lot of other people) use it for icons.
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
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.
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);
}
}
/* ... */