Easily Turn Your Images Into Polaroids with CSS3 by Mark

Yesterday, Jon and I were going back and forth about what to blog about next. Love of CSS and doing something cool with it is kind of our thing and we quickly jumped on a brand new idea: polaroid style images with just CSS. Holy super awesome, Batman!

With our end goal in mind (polaroid style images), we needed to set a few ground rules:

  1. Has to work on a grid of linked images
  2. Images must be randomly rotated like a pile of images you're sifting through
  3. No actual text should be used on the images (only title and alt attributes)
  4. Has to be done with just CSS (no javascript)

After establishing those requirements, we got down to business. Here's a quick rundown of how we did it. (Not big on reading? Jump right to the demo.)

Starting with the Images

We get underway by first coding up our grid of images. We used an unordered list with each image linked to our Flickr account as the baseline for everything. This would allow us to echo the title text of the anchor while creating a clickable set of images.

Once we laid the groundwork, we moved on to getting the title attribute's content to show. That was difficult at first—we didn't realize the img element wasn't fully supported for this—but we quickly got it working with the anchor.

Using :after to Create Content

If you were to look at our demo, and then at the source code, you might be a little surprised. We're not showing any actual text in our HTML. Instead, we're using a CSS2.1 pseduo-selector, :after, to get the job done. Here's a look at the CSS:

  1. ul.polaroids a:after {
  2. content: attr(title);
  3. }

By using the :after, we can add a rule to our CSS that gets the anchor tag's title attribute and echoes the content immediately following the img. You'll note that despite the selector saying "after," it actually means "after the actual content of this element," thus showing the title text withing the anchor and after the image.

And now comes the fun part of rotating our images and applying some badass styles for impact and cool-factor.

Randomly Rotate the Images

With some help from our browser-specific CSS3 properties, we can "randomly" rotate our images. To do it, we first set a default angle at which to rotate our images. From there, we apply additional rules with the :nth-child pseudo-selector to give the feeling of random.

Here's the CSS to do it:

  1. /* By default, we tilt all our images -2 degrees */
  2. ul.polaroids a {
  3. -webkit-transform: rotate(-2deg);
  4. -moz-transform: rotate(-2deg);
  5. }
  6.  
  7. /* Rotate all even images 2 degrees */
  8. ul.polaroids li:nth-child(even) a {
  9. -webkit-transform: rotate(2deg);
  10. -moz-transform: rotate(2deg);
  11. }
  12.  
  13. /* Don't rotate every third image, but offset its position */
  14. ul.polaroids li:nth-child(3n) a {
  15. -webkit-transform: none;
  16. -moz-transform: none;
  17. position: relative;
  18. top: -5px;
  19. }
  20.  
  21. /* Rotate every fifth image by 5 degrees and offset it */
  22. ul.polaroids li:nth-child(5n) a {
  23. -webkit-transform: rotate(5deg);
  24. -moz-transform: rotate(5deg);
  25. position: relative;
  26. right: 5px;
  27. }
  28.  
  29. /* Keep default rotate for every eighth, but offset it */
  30. ul.polaroids li:nth-child(8n) a {
  31. position: relative;
  32. top: 8px;
  33. right: 5px;
  34. }
  35.  
  36. /* Keep default rotate for every eleventh, but offset it */
  37. ul.polaroids li:nth-child(11n) a {
  38. position: relative;
  39. top: 3px;
  40. left: -5px;
  41. }

In the above code, we rotate all our images 2 degrees and then go back through to programatically rotate more to add variety. Here's how it looks:

The rotating above breaks down like so:

  • Every image is rotated -2 degrees by default
  • All even images are rotated 2 degrees
  • Every fifth image is rotated 5 degrees and moved right 5px
  • Every eighth image keeps the default rotation (-2 degrees) and is offset 8px from the top, 5px from the right
  • And every eleventh image keeps the default rotation but is offset 3px from the top and -5px from the left

Now, in a group of 12 images, they appear to be randomly rotated and positioned. Pretty slick, huh? Now we move onto the final details of visual aesthetic.

Final Touches

With the rotating in place, we can focus on the sex appeal of our grid of images. In addition to the basic stylistic changes, we'll add in drop shadows and a Webkit transition to smooth things out in Safari (sorry, Firefox users, but there is no support for transitions yet).

And that's a wrap! With just a bit of love from CSS, we've created some freaking sweet polaroid style images with nothing more than a list of images.

View the Demo

Be sure to read through the demo for more explanation around the CSS we've used and where to find additional information. We also included a true "pile of images" farther down the page—check it out!

View Demo »

9 Comments

  • Kevin Holesh says:

    That demo looks stunning in Safari! I had no idea this was even possible with fairly simple CSS declarations. Thanks for enlightening me :-)

    I can't wait to use this on a gallery page or something similar. It would definitely add some "progressive enrichment" to my design.

  • Mark (ZURB) says:

    @Kevin: It's pretty slick, huh? Safari really shines here compared to Firefox, but only because of the smooth transitions in 4.x. Let us know how it goes if you use it on your next project! Making it degrade for older browsers (read: Internet Explore) shouldn't be hard to do either.

  • Paul Lloyd says:

    Yeah, it's alright, but could be better*. Your next challenge is to adapt this code so that each image exhibits edges with a dark subtle fading effect, just like on the real things! Think you can make that happen?

    • By the way, I'm totally digging this demo, but I'm trying to keep you guys grounded ;-)
  • Mark (ZURB) says:

    @Paul: Hah! We accept! I already have a few ideas up my sleeve. We'll update this post when we have something worthy of your true praise :D.

  • Lewis King says:

    This is really, really awesome. First time visiting the site, but you guys are awesome! Certainly keeping an eye on you. This is going to be perfect for a new project I'm working on. Thank you so much!

  • Rich Pollock says:

    Just a head's up: the CSS in the demo is fine (obviously, as it all looks very slick), but the nth-child selectors in the article all read "nth-child(even)" when they should read "nth-child(3n)", "nth-child(5n)", etc.

    Cheers, Rich

  • Mark (ZURB) says:

    @Lewis: Thanks for the kind words—glad you love it!

    @Rich: Thanks for the catch. Just fixed it here on the post.

  • Martin Korych says:

    What a wicked article, I'll surely look into implementing this into our "About us" page. Thank you so much!

  • Mark (ZURB) says:

    @Martin: Awesome, shoot us an email or a comment when you do!

Add your comment...

Required

Required, but not shared. Nerd's honor.

About the ZURBlog

The ZURBlog is where we discuss design interaction and strategy. We use design thinking to challenge businesses and designers to improve the products and services they create.

What's the ZURBword?

What's the ZURBword?

ZURBword.com is our thoughts on interaction design and strategy. What?

Latest Tweet

Patrick, our bud and client at Fuzebox, has a nice write up on Mashable. He gives 5 reasons for a virtual meeting: http://bit.ly/6FRfIT

Photos on Flickr

  • 4129436520_3fca0272c8_s
  • 4107270144_aab67434b7_s
  • 4107270114_ce09f939eb_s
  • 4106504507_8a022f5e2c_s
  • 4107270090_8d0b779444_s
  • 4107270064_f9000d0fab_s
  • 4106504405_d9977cec7f_s
  • 4095685165_0dd6f8d443_s
  • 4095577671_571f7328de_s

Videos on YouTube

Bookmarks on Delicious

Wanna talk? Call us at (408) 341-0600.

Hmm, not a big talker. Email us to .

Still here? Great, we're hiring.

We need people with chops to join our quest
for world domination. Want a job, nerd?

What's the ZURBword?

ZURBword.com is our thoughts on interaction design and strategy. What?

Subscribe to ZURBnews

Get our monthly newsletter, ZURBnews.
Check out last month's edition »