-
CSS3 animations demonstrated with snow
This winter we have had an unusually snowy time of things, as a matter of fact so has the whole of the UK. As a Clearleft christmas snowy surprise I wrote a CSS3 snow bookmarklet.
If you are running a WebKit based browser you can make it snow on anywhere on the internet by dragging the following bookmarklet into your toolbar, sending any site into a mini snowstorm!
I based the snow in part on the leaf example on the WebKit blog.
JavaScript is only just to add the snowflakes in their starting position (and naturally in order for it to be a bookmarklet) but all the animation and styles are done in pure CSS. So if you wanted to do this without any JavaScript at all you could just start with the snowflake elements directly in the source and it would work fine.
For the snowflakes themselves I had a lot of fun looking through the Unicode list of snowflakes, and asterisks trying to find the prettiest snowflakes ❆, ❅, ❄, ✳, they are in an array and the sizes are in another array. Every snowflake is an absolutely positioned div with a span inside, we will come to that later. When a snowflake is chosen a size and a character are chosen at random. the distribution of sizes is controlled by the proportion of the size class in the array:
var flakes = ['2746', '2745', '2744', '2733']; var sizes = ['tiny', 'tiny', 'tiny', 'small', 'small', 'small', 'small', 'medium', 'medium', 'medium', 'medium', 'medium', 'medium', 'large', 'massive'];When the snowflakes are positioned, a random side (left or right) and a percentage between 0 and 60 is chosen to set the position absolute values, this makes it work nicely when you resize the browser and means there is a higher concentration of snowflakes in the center 20% of the screen. They also needed an epic-ly large z-index because this is going to be used as a bookmarklet and you don't know what will be on the page it is used on.
Another consideration in the setup was that white snowflakes would not be seen on white pages so a text shadow was added to make it stand out, I used rgba for this to make it blend in better with any background color.
text-shadow: rgba(0, 0, 0, 0.7) 1px 1px 2px;There are two main animations for each snowflake, fading and dropping. The span inside the snowflake does the spinning. These animations are set up and given a reference-able name in the CSS file:
/* Hides a snowflake towards the very end of the animation */ @-webkit-keyframes fade { /* Show a snowflake while into or below 85 percent of the animation and hide it, otherwise */ 0% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; } } @-webkit-keyframes drop { /* Makes a snowflake fall from -50px to 650px pixels in the y-axis starting at -50 so as to appear to be falling from above the screen not starting at the top */ 0% { -webkit-transform: translate(0px, -50px); } 100% { -webkit-transform: translate(0px, 650px); } }The named animation group contains sub groups, rule blocks where the selector is one moment in the animation. When the animation runs it looks at the timeline of keyframes and smoothes the animation accordingly, for example in the fade animation above, the opacity stays at 1 until 85 percent through its animation (aka one drop) where it then begins a smooth fade to 0 over the last 15% of the time. If we had omitted that middle step and just had opacity set to 1 at 0% and to 0 at 100% then the fade would be a smooth fade over the duration of the whole animation.
You can also set the 'moment' of the keyframe using the keywords from and to, this is effectively the same as 0% and 100%. For simple animations this probably would suffice but I find using percentages gives you a greater degree of control over the pace of your animation.
-webkit-animation-name: 'fade, drop'Because we know we have two animations being applied to each snowflake div in JavaScript we can give the other animation properties two values and know that they apply to the two animations respectively.
-webkit-animation-iteration-count: infinite, 20;The
animation-iteration-countstates how many times an animation should run. We are not too fussed about the fade but we want to only have each snowflake fall from the sky 20 times before disappearing, just in case the bookmarklet is used and left open in a tab it shouldn't continue indefinitely.-webkit-animation-direction: normal, normal;Options for this are normal and alternate. Normal behaves exactly as you have specified in your keyframes, alternate behaves normally on odd iterations and reversed on even iterations
-webkit-animation-timing-function: linear, ease-in;There are quite a few options you can play with for this property
easelinearease-inease-outease-in-outand if you really know your animation maths you can go wild withcubic-bezier(X, X, X, X). Basically this describes the acceleration of the animation e.g.linearis all at the same speed,ease-inhas a little warm up first,ease-outwarms down andease-in-outdoes both. I wanted the snowflakes to ease gradually in before reaching a constant speed.-webkit-animation-durationWe are setting the animation-duration in Javascript because it needs to be randomised to avoid all the flakes falling at the same rate. This is being set at a random time between 5 and 11 seconds (trial and error got these magic numbers). Ideally I would have set the range based on the size of the snowflake which would have been cool, I could easily have made the larger ones fall faster than smaller ones, but I didn't think of that at the time.
-webkit-animation-delayHow long until the first snowflake starts falling? I have set this in Javascript to be instant for the first snowflake (remember it still has to fall 'into the screen' when it starts) and then a random amount of time between 4 and 8 seconds for the others. This was important with so few snowflakes because we need to spread them out so they don't all fall at the same time and look like a continuous snow storm
Naturally there is an animation shorthand property should you wish to specify everything at once.
With our snowflakes falling and fading nicely, all that remains is the spinning. in the JavaScript I set a random animation to the span inside the snowflake div that contains the snowflake character. The animation is then either clockwiseSpin or counterclockwiseSpin
@-webkit-keyframes clockwiseSpin { /* Rotates a snowflake from -50 to 50 degrees in 2D space */ 0% { -webkit-transform: rotate(-50deg); } 100% { -webkit-transform: rotate(50deg); } } @-webkit-keyframes counterclockwiseSpin { /* Rotates it from 50 to -50 degrees in 2D space */ 0% { -webkit-transform: rotate(50deg); } 100% { -webkit-transform: rotate(-50deg); } }We then set the properties explained above for the span.
-webkit-animation-iteration-count: infinite; -webkit-animation-direction: alternate; -webkit-animation-timing-function: ease-in-out; -webkit-transform-origin: 50% -100%;The spinning should be infinite and to add to randomness we need to use the 'alternate' value for direction and ease-in-out as the timing function, the offset transform origin plays with the rotation transform inside the spinning animation in order to make it seam like it is floating on a light snowy breeze.
To finish it off then the JavaScript is wrapped in a self executing function, the CSS is added to the head of the document from the main JavaScript file rather than having to bulk that into the bookmarklet. The JavaScript on is then splurted into the head of the document. The bookmarklet looks like this:
javascript:(function(){var%20s=document.createElement('script');s.src='http://j.mp/7ZZuRu';document.getElementsByTagName('head')[0].appendChild(s);})()All that remains is to just Let it Snow!
Further reading
These two articles on the WebKit blog have some good demo's on the use of animation. My 24ways article goes into a bit more detail on transforms and Tim Van Damme's great 24ways article has a supurb space animation demo which is worth looking at. The spec is available on the w3c site.
-
Going Nuts with CSS Transitions
Going Nuts with CSS Transitions — I Recently wrote an article published in last Christmas's 24ways advent calendar magazine. I show you how CSS 3 transforms and WebKit transitions can add zing to the way you present images on your site.
-
Dinky pocketbooks: the command-line reference edition
I have fulfilled my intention from to create a dinky pocket book as a reference for useful terminal commands (see below). I'll be printing a set of these out for my colleagues to find on their desks next week.
The printable pdf can be found here, but if you are running safari — or a recent gecko build as now it also uses
-moz-transform— you can print directly from the browser.The HTML for the reference booklet together with some minor updates to the original booklet css can be found on github.
I rarely use the terminal so these are commands that I will find useful as a reference and some of these I always end up having to look up. It is not designed to be an exhaustive list but if you have any suggestions I would love to hear them!

Navigate the file tree
changing directory to
dirnamecd dirnamemove up a directory in the tree—dont forget you can drag a folder in from the finder to get a path to that directory.
cd ..go back to the last directory I was in
cd -where am I? (present working directory)
pwdlist what's in this directory
lsnow give me more information in the listing
ls -lahssh to server
ssh user@domain.comFind & open
list all files recursively in subdomains
find .find all files with '
.css' in the namefind . | grep .cssfind the string '
prose' in the contents of all the files in this directorygrep -r "prose" .open a file as if you had double clicked it in the finder (mac only)
open filenameopen the current directory in the finder
open .make a directory called
dirnamemkdir dirnamecreate a file called
filenameif it doesnt exist or update last modified date if it doestouch filenameMove, remove & copy
move or rename a file or directory
mv oldname newnameremove a file
rm filenameremove a directory and all its contents. BE VERY CAREFUL! you could easily delete everything!
rm -rf dirnamecopy a file
cp oldfilename newfilenamecopy a directory and everything in it
cp -r olddirname newdirnamesecurely copy a file to / on a remote server — you can also copy a directory using
scp -rscp file user@domain.com:Subversion
check out a repository to the current directory
svn co http://domain.com/svn/ .update local directory from repository
svn upare there new or modified files?
svn statusadd new files to the repository
svn add filenameremove a file from subversion
svn remove filenamemark a previously conflicted file as resolved
svn resolved filenamewho changed what line number of this file
svn blame filenamecommit all changes in this directory
svn commit -m "commit msg"Subversion & download
is this directory checked out from svn? and where?
svn infoshow everything that has changed
svn diffshow what has changed in one file
svn diff filenameopen text editor in order to specify which files to ignore from svn
svn propedit svn:ignore .download a file to the current directory
wget URLshow the contents of a file in the terminal
curl URLHelp & information
run any command as root
sudo your-command-hereget help for any command, eg
svnsvn --helphow long has this computer been on?
uptimewhat is the size of the current directory and all the contents
du -hcancel the command you were currently typing
ctrl + cgo to the beginning of the line in the terminal
ctrl + ago to the end of the line in the terminal
ctrl + e -
Dinky pocketbooks with WebKit transforms
I'm a big fan of stuff written on paper. My computer is covered in useful post-it notes, and I do a lot of planning on paper at the start of every client-side build.
On my desk at work is a piece of paper written in felt tip that I pass around to my co-workers on occasion. It's a reference document for how we check projects out of subversion, upload to live and some basic terminal commands for people who are unfamiliar in that environment.
This was a great opportunity to break out my favourite paper folding technique, where an A4 page becomes an 8 page booklet. I first learnt about this from a Christmas card I received a few years ago from some very inventive friends.
Brian Suda happened to be in the office that day and pointed me to a cool Flash interface for creating these, pocketmod.com. He also suggested that it would be possible to build these using just HTML and CSS with CSS3 transforms, currently supported by Safari and WebKit.
Inspired, I did exactly that.
Here's the demo.html (no transforms, so I can easily preview the pages) - the transforms are applied by the print stylesheet, so hit "print preview" to see them. Alternatively, visit demo.html?print to preview the print stylesheet directly in your browser.
Just in case you aren't running Webkit or Safari, here's what the print output looks like:

Each "page" has a set width and height (241x370 px) and is absolutely positioned, but the real magic happens with the CSS3 transforms in the print stylesheet:
/* rotated left */ #page1, #page8, #page7, #page6 { -webkit-transform: translate(64.5px, -64.5px) rotate(-90deg); } /* rotated right */ #page2, #page3, #page4, #page5 { -webkit-transform: translate(-64.5px, -64.5px) rotate(90deg); }It's not enough just to rotate 90 or -90 degrees. This works fine if you are rotating something that is square because the rotation happens around the centre point. I wanted to rotate the rectangles around the corner to ensure they fitted snugly inside their parent container. The solution was to shift the position using a
translate()transform. I could have done this with position: relative, but I opted for a transform since I was already using-webkit-transformfor the rotation. 64.5px is worked out as (height - width) / 2.You can fill each page with whatever you like, but make sure it fits or it will be clipped by the
overflow: hiddenapplied to the page. The only required markup is as follows:<div id="book"> <div id="page1" class="page"></div> <div id="page2" class="page"></div> <div id="page3" class="page"></div> <div id="page4" class="page"></div> <div id="page5" class="page"></div> <div id="page6" class="page"></div> <div id="page7" class="page"></div> <div id="page8" class="page"></div> </div>I surround textual content with a
<div class="inner">to apply sensible padding without affecting the width of the page.There are currently two special page types. An empty page with lines (suitable for hand-written notes) is achieved by applying a class of
lines:<div id="page5" class="page lines"></div>The second special page uses the Google Static Maps API. The API takes a bunch of name value pairs, which I decided to represent using a definition list. On load, pages with the class
gmapare scanned for definition lists, which are then hidden and replaced by an image constructed from the definition terms.<div id="page4" class="page gmap"> <dl> <dt>center</dt> <dd>50.8197155,-0.1365716</dd> <dt>key</dt> <dd>insert your Google Maps API key here (get one here)</dd> <dt>zoom</dt> <dd>13</dd> </dl> </div>I use Simon's www.getlatlon.com to find the correct values.
Aside from these special pages, I've included styles for the HTML usual suspects - lists, tables, headings, pre etc. To make a todo list, simply apply a class of
todoto a<ul>or an<ol>. To make a blank todo list, just use blank list items.Once you've constructed and printed your dinky booklet masterpiece, you'll need to fold it. Here's a nifty video from pocketmod.com showing how:
I've published the code on GitHub, so please feel free try it out yourself or fork it and have a play. Let me know what you think.
4 items tagged "webkit"
Look at "webkit" on del.icio.us, Flickr or Technorati
