An Innovative Idea for Holding State in CSS
Jane Ori
Posted on January 15, 2022
When it comes to CSS and HTML, application state falls into these categories:
cascade state: classes/checkbox state/other dom
pseudo state: based on current user interaction
animation state: pre-determined series, triggered by cascade and/or pseudo state
transition state: easing between the cascade and/or pseudo states when they change
These are the building blocks for all UX that can be combined in an infinite number of ways[1]. These are all intertwined of course, and we can split hairs on how I've referred to them, but ultimately though; Either our state is static - derived from the current DOM, or it's temporary - derived from the user's current interaction.
[1] except that animation state cannot be combined with animation state due to animation-tainting
"But wait, there's more!"
- @rockstarwind, probably
The new static state, stored in CSS (not DOM!)
Earlier this week, @rockstarwind posted an idea on their twitter that demonstrates a new technique for remembering temporary interactions without DOM needing to be the source of that memory (like it is with the :checked state of a checkbox).
They go on to show a reduced example in a codepen with excellent comments to learn from:
Neat!
Let's break down the idea and play with it a bit.
Register the one-bit memory cell
Following their work, this is what we have to do first:
@keyframes memory {
0% { --cell: initial }
1%, 100% { --cell: ; }
}
Using this memory
animation sets the custom property --cell
as a Space Toggle which has two states, off 'initial' and on ' '.
You can concatenate CSS custom properties like so: If you concatenate a space: If you concatenate initial: So in effect, a space toggle is is a one bit variable we can use to derive two completely different states from reading it with The TL;DR of Space Toggles
.demo {
--val1: 2px solid;
--val2: red;
--result: var(--val1) var(--val2);
}
--result
is effectively 2px solid red
.demo {
--toggle: ;
--value: green;
--result: var(--toggle) var(--value);
}
--result
is effectively just green
.demo {
--toggle: initial;
--value: green;
--result: var(--toggle) var(--value);
color: var(--result, cyan);
}
--result
is invalidated and var(--result, fallback) will use the fallback instead. (color is set to cyan in this example)var()
wherever and as often as we want.
Note: Animating custom properties is part of the Houdini spec, so this may not work in firefox for a while.
Initialize the memory
All we have to do here is apply the keyframes to an element:
.demo {
animation-name: memory; /* keyframes reference */
animation-duration: .1s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-play-state: paused; /* must be paused at first */
}
Using the shorthand animation property, that looks more like this:
.demo {
animation: memory 1ms linear 1 forwards paused;
}
Now .demo
elements have a --cell
property explicitly set to initial
.
Set up properties to use the space toggle
.demo {
--bg-if-cell-is-on: var(--cell) rebeccapurple;
background: var(--bg-if-cell-is-on, hotpink);
--color-on: var(--cell) white;
color: var(--color-on, black);
}
In English, if the cell is off, the background is hotpink
and color is black
. If the cell is on, the background is rebeccapurple
and color is white
.
Flipping the bit
Next, they use the :active
pseudo state from a button
to un-pause the animation. Theoretically we could use any pseudo state, like :hover.
Let's test
click 'rerun' in the bottom right corner if needed!
Great! If the user's pointer enters the document, CSS flips state and the background becomes rebeccapurple.
Un-flipping the bit
To return to the initial state, the easiest way is what they've shown, set animation: none;
on our element when a selector matches.
This changes --cell
back to initial
implicitly because when a custom property is not set (nor registered with a specific syntax), it is initial.
The rest of the owl
We can use this technique to do something fun like 100% CSS etch-a-sketch:
Delightful!
"Remembering is so much more a psychotic activity than forgetting"
I've only been friends with RockStarwind for a couple years but they are continually sharing innovative ideas and awesome demos in the CSS space. Definitely give them a follow on Twitter so you don't have to remember to check manually. ;)
If you enjoyed my first article, please consider following me here and on twitter as well!
š
Prior art!
After tweeting, I learned about someone already using this idea in a really really interesting way! Check it out!
and her demo:
HOW COOL IS THAT?!
Posted on January 15, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.