CSS3 transitions and animations are very useful but they’re often too perfect!
Have you ever wondered why computer games look staggered at 25-30 frames per second but movies appear natural at the same rate? A typical video camera captures every frame over 0.04 of second; anything moving faster will appear slightly blurred. However, a game which perfectly creates every frame without motion blur can look a little strange.
Unfortunately, it’s not possible to create motion blur on HTML elements. The CSS3 Filter Effects draft specification may eventually help, but it only has experimental support and the blur effect is non-directional. Fortunately, we have two other standard CSS3 properties which can help: text-shadow
and box-shadow
.
View the CSS3 motion blur demonstration…
If an object is moving to the right, we can apply a text-shadow
which extends to the left using a similar color to the text. In the example above, the text starts and ends with no shadow. However, half-way through the animation — the fastest point — it’s set to:
text-shadow: -5px 0 5px rgba(255,255,255,1);
Image may be NSFW.
Clik here to view.
It’s subtle, but applying a heavier shadow wouldn’t necessarily look effective.
Similarly, we can also use a box-shadow
with a similar color to the text background. At the half-way point, it’s set to:
box-shadow: -15px 0 10px -5px rgba(200,0,0,0.5);
This defines:
- an x-offset of -15px
- a blur radius of 10px, and
- a spread distance of -5px.
The spread is important. Without it, the box-shadow
will be noticeably larger than the box itself. In my demonstration, I found a value of around half the blur radius worked well but you may need to adjust it depending on your element’s size and direction.
Image may be NSFW.
Clik here to view.
The full keyframes definition moves the element from left to right for the first 50% of the animation followed by right to left for the second half. Therefore, the maximum text-shadow
and box-shadow
settings are defined at 25% and 75% accordingly:
@keyframes motionblur { 0% { left: 0; text-shadow: 0 0 0 rgba(255,255,255,0); box-shadow: 0 0 0 rgba(200,0,0,0); } 5% { left: 0; transform-origin: 0 0; transform: scaleX(0.85); } 25% { text-shadow: -5px 0 5px rgba(255,255,255,1); box-shadow: -15px 0 10px -5px rgba(200,0,0,0.5); transform: scaleX(1.1) skewX(-4deg); } 50% { left: 300px; text-shadow: 0 0 0 rgba(255,255,255,0); box-shadow: 0 0 0 rgba(200,0,0,0); transform: scaleX(1) skewX(0deg); } 55% { left: 300px; transform-origin: 100% 0; transform: scaleX(0.85); } 75% { text-shadow: 5px 0 5px rgba(255,255,255,1); box-shadow: 15px 0 10px -5px rgba(200,0,0,0.5); transform: scaleX(1.1) skewX(4deg); } 100% { left: 0px; text-shadow: 0 0 0 rgba(255,255,255,0); box-shadow: 0 0 0 rgba(200,0,0,0); transform: scaleX(1) skewX(0deg); } }
A few 2D transformations were also added to enhance the animation effect. The box is:
- squeezed at the start so it looks as though it’s about to pounce
- elongated and skewed at the animation mid point to give the impression of acceleration, and
- returned to its normal dimensions at the end.
You should also note I used a fairly slow animation duration so you can see what’s happening.
View the CSS3 motion blur demonstration…
The effect works in all recent browsers:
- IE10
- Firefox
- Chrome, Safari and Opera 15 — although you will require -webkit prefixes for all
animation
andtransform
properties.
Opera 12 had a breakdown but, ahem, we’ll gloss over that…
The only slightly odd behavior crops up in IE10. The browser won’t show the shadows unless defaults are explicitly defined at the start and end, i.e.
text-shadow: 0 0 0 rgba(255,255,255,0); box-shadow: 0 0 0 rgba(200,0,0,0);
In other words, IE10 will not animate from box-shadow: none
to box-shadow: something
. I suspect it affects other CSS properties so it’s worth filing in your box of quirky browser issues.
Please send me your URLs if you use the technique elsewhere!