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.
Top comments (0)