I've been thinking quite a bit about CSS architecture these days.
One thing in particular that has crossed my mind is how to handle certain situations. For example, we want to hide content on the page and then reveal it (or vice versa). In JavaScript, this is relatively straightforward: get an element, and apply a class or remove a class to change the state of the element. The CSS for that might look something like this:
div { display:block; }
div.hidden { display:none; }
In this case, I've used display:none to hide the content visually and from screenreaders, too.
Adding a visual effect
Now, if I want to add a visual effect, I might use JavaScript to alter a style property from value A to value B (eg. style.opacity) The script would run through the animation and apply the hidden class at the end of the animation.
What if we wanted to offset the visual effects over to CSS3 Animations?
@keyframes fade-out {
0% { opacity: 1; }
100% { opacity: 0; }
}
div { display:block; }
div.hidden { display:none; animation: fade-out .5s 1; }
Nice and easy! Or is it? For those that have actually tried this code might be surprised to discover that this doesn't work. It's because once the hidden class is applied to an element, it's immediately hidden with display: none;.
The next thing you might think to do is apply display:block in the keyframes like so:
@keyframes fade-out {
0% { display:block; opacity: 1; }
100% { display:none; opacity: 0; }
}
The problem with this is that non-transitionable properties like display are ignored and have no effect.
A Proposition
I propose that the CSS3 Animation specification be changed to allow for this. Keyframes should act like classes being applied to an element. Therefore, the example above is display:block at 0% and becomes display:none at 100%. As a result, the page works as expected for this scenario.
Transitioning properties
I woke up this morning thinking about this further—and I'll readily admit that this next idea complicates things a little bit. I additionally propose that an animation-transition-property property be added. This specifies which of the keyframe properties should actually transition.
@keyframes fade-out {
0% { opacity: 1; }
100% { opacity: 0; position: absolute; left: -999px; }
}
div.hidden {
animation: fade-out .5s 1;
animation-transition-property: opacity;
}
By setting the animation-transition-property, only the opacity will transition. At the end of the transition, the element is then placed offscreen using position and left properties. The default setting for animation-transition-property would be all which would allow keyframes to behave exactly as they do today. There would also be a value of none that would allow for no property to transition. This would allow for stepped animations to be created.
Reversing animations
My last proposal for CSS3 animations is the ability to reverse an animation. Right now, the spec has an alternate property that allows every odd iteration to animate in reverse but that's not quite what we want. Again, allow me to demonstrate with an example:
@keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
div {
animation: fade .5s 1;
}
div.hidden {
animation-direction: reverse;
}
In this example, I have a fade animation applied to the div. By default, it'll fade to 100%. When the hidden class is applied, the direction of the animation is changed and the fade goes from 100% to 0%. This allows animations to be quickly and easily re-used.
Standards Process
Writing a specification is hard and I don't envy those that have to work through these things. It's a balance between making something powerful and making something complicated. I hope that my ideas fall more in the former category than the latter.