CSS Only COVID-19 Dashboard Dial
Matt Kreiling
Posted on May 21, 2020
In Washington State where I live, the governor's office is making decisions about reopening on a number of metrics. These metrics are grouped together in a dial dashboard where each dial represents the risk level for a particular set of metrics.
I decided to make one with CSS only.
I was kind of surprised how quickly I made this. Apparently 10 years of loving CSS has paid off. Here are some observations about the process.
Semantic HTML and accessibility first
I am proud that without thinking, I immediately sought out an appropriate semantic element for the dial - the meter
element.
Because of the many problems with styling it, I opted to hide it using a tool that should be in every web dev's toolbox, the CSS clip, screen-reader only hack. This code will hide an element from sighted users, but keep it available for assistive technology.
.sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
In this case, I used it to hide the meter and to hide a more sensical label.
I also used aria-hidden
to hide the less helpful "Low Risk High Risk" text.
Even though this was just a fun CSS exercise, it feels good to care!
Knowing when to add HTML to help with styling
This is a particular virtue that I have came upon lately. In the past, I tried to use as few HTML elements as possible, keeping the DOM tree flat. I was a hypochondriac and avoid "divitis" like the plague. The separation of content and presentation was a holy command.
Over the years, I have spent countless hours and used pseudo-elements to do all sorts of obscene things rather than add an empty div to the page.
Now, I still reach for those pseudo-elements, but when things become fragile, I will add a div
or two.
Don't get me wrong, meaningless div
s aren't great, but neither is inscrutable CSS.
The CSS triangle hack
The pointer on the dial is made of two transparent pseudo-elements with fat borders that are also transparent on two sides. As with most of these kinds of hacks, I used a tool to generate some CSS and tweaked the values until they were correct.
Gradient tools
I have use old school Colorzilla's gradient generator for years, but I discovered a slightly slicker generator at css-gradient.io.
Attribute, sibling selectors, and calc
, and CSS variables1 to sync presentation with content
This is probably the fanciest thing I did. In order to rotate the dial in sync with the value of the meter
element, I used this combination of awesome CSS features.
In the dial css, I added a rotateZ
transform with a calc
function that uses a the value of a CSS variable to compute the rotation. Turn is a great unit to use with with rotate transforms.
transform: rotateZ(calc(var(--turn) * .05turn - .25turn));
The CSS variables are set in rules that target the value
attribute of the meter. Cool thing about
meter[value="1"] ~ .dashboard-meter__container { --turn: 1 }
meter[value="2"] ~ .dashboard-meter__container { --turn: 2 }
meter[value="3"] ~ .dashboard-meter__container { --turn: 3 }
meter[value="4"] ~ .dashboard-meter__container { --turn: 4 }
meter[value="5"] ~ .dashboard-meter__container { --turn: 5 }
meter[value="6"] ~ .dashboard-meter__container { --turn: 6 }
meter[value="7"] ~ .dashboard-meter__container { --turn: 7 }
meter[value="8"] ~ .dashboard-meter__container { --turn: 8 }
meter[value="9"] ~ .dashboard-meter__container { --turn: 9 }
Google-Fu
My google-fu is so strong I just used google to spell google-fu. Really, it is usually duck-duck-go-fu, which sounds delicious.
Bad jokes aside, going to the docs or the countless web development blogs and getting the answers is a cybernetic enhancement that may be more valuable than any other skill. I look up things I know that I don't want to have to remember
The code
1. I know they are called custom properties, but I'm not going to do that anymore; just because they are declared the same way that other properties are set, it isn't worth the cognitive load and confusion it causes learners.
Posted on May 21, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.