loading...

CSS Only COVID-19 Dashboard Dial

tinynow profile image Matt Kreiling ・3 min read

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.


A dial pointing at an arc that is labeled low risk and high risk

The original image.

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 divs 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.

Discussion

pic
Editor guide