CSS is Awesome
Ok. CSS is in an awesome place now. We have functionality, including CSS variables and functions like color-mix()
that make writing CSS so compact. Here's what I mean.
So, I was mocking up an idea I have for viewing and assessing people's competence for my urban search and rescue team on Codepen. The idea is a table of competencies across the page and people down the page (or vice versa), which buttons to show/set a person's rating on a specific competency (highly competent, competent, not yet competent, no trained). The rating buttons are coloured to make it easier to see and a glance what their current rating is.
I wiped up the HTML by making the first group of cells and doing a lot of copying and pasting. For the mockup, each button has data attributes to track the competency, user and rating.
HTML of a name row and start of a competency row
<tr class="name">
<th colspan="25"><div>Name 1</div></th>
</tr>
<tr>
<td>
<button data-person="1" data-level="hc" title="Highly competent" data-competency="1">HC</button>
</td>
<td>
<button data-person="1" data-level="c" title="Competent" data-competency="1">C</button>
</td>
<td>
<button data-person="1" data-level="nc" title="Not yet competent" data-competency="1">NYC</button>
</td>
<td>
<button data-person="1" data-level="nt" title="Not trained" data-competency="1">NT</button>
</td>
<td>
<input data-person="1" type="date" data-competency="1">
</td>
I wrapped the name in a div
element so that I could make the name stick on screen while scrolling across the table (position: sticky
CSS awesomeness #1!!)
CSS ruleset applying position: sticky
to the name div
element
.name div {
display: inline-block;
position: sticky;
left: 0;
}
I also made the thead
header row stick to the top for when scrolling down the page, with a little bit of padding in the cells using CSS nesting (CSS awesomeness #2!!!)
Nested CSS ruleset apply position: sticky
to the table header
thead {
background: white;
position: sticky;
top: 0;
z-index: 1;
th {
padding: 0.5rem 0;
}
}
I then came to the buttons. My initial thought was I was going to have to create a CSS selector and block for each button and a colour for each state, but then I thought hold on, we have a mixing function now (color-mix()
CSS awesomeness #3!!!) and CSS properties that can be declared in multiple places (CSS awesomeness #4!!!).
With our powers combined, we are Captain CSS!…. or something…
So, I could (reasonably) simply: define base colour properties for each button; then in button
ruleset define a --bg
property for the button colour; then use color-mix()
to style the buttons for :hover
and when the rating is selected [aria-selected=true]
, then set the --bg
property for each button rating level.
CSS rulesets for styling the rating buttons
:root {
--hc: #45c100;
--c: #f0f000;
--nyc: #f01600;
}
button {
border: none;
width: 6ch;
color: black;
cursor: pointer;
--bg: lightgrey;
background: color-mix(in srgb, var(--bg) 10%, transparent);
&[aria-selected='true'] {
background: color-mix(in srgb, var(--bg) 60%, transparent)
}
&:hover {
background: var(--bg);
}
}
button[data-level=hc] {
--bg: var(--hc);
}
button[data-level=c] {
--bg: var(--c);
}
button[data-level=nc] {
--bg: var(--nyc);
}
IMHO, that is some hot CSS stuff there. Far less code than it used to be. Awesome.