Easily Turn Your Images Into Polaroids with CSS3

wrote this on in . 74 reactions

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. }
  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. }
  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. }
  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. }
  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. }
  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 »

Swing and a Miss
You're Design Thinking Too Much
Design pot
Design or Get Off the Pot

It has 71 comments.

Kevin Holesh (ZURB) 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 (ZURB) 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 (ZURB) 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 (ZURB) 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 (ZURB) 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!

elliot condon (ZURB) says

Wicked tutorial!

Gotta love css3! When is IE going to get on the bandwagon?

Nick Toye (ZURB) says

Not looking so hot in Safari my friend, when you hover over some of the images, the white border vanishes, so it loses it's effect.

Emma (ZURB) says

This looks great, is there a way to get it to automatically update from flickr?

beard (ZURB) says

-webkit-transform -moz-transform

Too bad these aren't an official CSS3 spec. Not looking forward to duplicating this every time.

Spencer (ZURB) says

To add to Nick's comment, the #container's overflow of hidden is cutting the images off. This also causes the #tweetmeme_button to disappear. Looks great though!

Rob (ZURB) says

This is awesome. Was looking for a cool gallery effect for a website i am building. Shame about IE support but oh well... their loss. My only query is whether there is a better "default" font to use if the Felt Marker isn't installed?

On a mac with font smoothing etc it looks cool, but on windows it looks pants without the Felt Marker font. Any ideas? Arial/Georgia is ok but when rotated the text looks messy.

Vanessa (ZURB) says

Really cool ! CSS 3 can do great things !!! :) But it doesn't work on IE 7 & IE 8 :-\


It's really cool. I like it. I am hoping all can work well in all browser in the future. :)

Appreciate for your great post.

ronald (ZURB) says

This looks great, another way to display your images . . .

Mohammed Morsi (ZURB) says

that's pretty cool I really like it but there is one comment on that I think that the main

that carries the images should take overflow : visible because some images at the corners are cut because the hidden property.

Levi Figueira (ZURB) says

<rant> So, why not use tables to display those images? </rant>

Glad to see you guys moved on… ;) Great tutorial! Gotta love CSS3! :D

James (ZURB) says

Thanks for this but I have a small problem, for some reason the hover effect only works on the first image, the rest don't work.. any ideas why this might be? As far as I can tell my code is the same as your example..

James (ZURB) says

Thanks for this but I have a small problem, for some reason the hover effect only works on the first image, the rest don't work.. any ideas why this might be? As far as I can tell my code is the same as your example..

If I change it to img:hover instead of a:hover, it works on all images but obviously the surrounding elements aren't scaled.. I'm stumped!

James (ZURB) says

Fixed the above problem by changing ul.polaroids a:hover to ul.polaroids li a:hover :)

redspell (ZURB) says

Guys, this is a great bit of script, hallelujah for CSS3. This effect is just what we were after for our new ecommerce site. It's a shame that IE don't get their act together though for cross browser uniformity. Anyway, Thanks for sharing.

Jae Xavier (ZURB) says

Very well presented tutorial. I would like to implement these types of effects and more but the market I serve is predominantly Internet Exploder users.

Its sad that Internet Exploder has to hold up the party and be annoyingly late (as always).

Dave (ZURB) says

Great stuff, but for today absolutely unuseful :( Doesn't work in IE 7 and Opera 10 so it can't be implemented for client. Anyway thanx for sharing the code. The possibilities are amazing.

sivaranjan (ZURB) says

Thats one fine example of what CSS3 can do ! I am so impressed. But its too bad IE is yet to catch up on the CSS3 and half of the world is still grabbing on to IE. I am adding this tutorial to my CSS aggregator site. Hope you dont mind.

Benjy (ZURB) says

Nice effect, I want to add "washing line" to my homepage with photos pegged to it, this should help out nicely.

Multyshades (ZURB) says

very useful tip with a very simple way to follow, this article will help me to learn more about css3, thanks for share

Nora (ZURB) says

The enlargement animation now works in Firefox too. Yay!!

Peter Holme (ZURB) says

Hi! Thanks for a great demo! Tried to implement it on my site - and I ran into one small problem that I can't seem to solve.. when hovering over an image, the images below are "pushed" away - not like on your demo, where all the images stay in place. Would you (or anyone) mind having a look and see what I have done wrong...?

Example: http://holme.se/bilder/comment-page-1/album/72157623906353233/holmenkollstafetten.html

Oscar (ZURB) says

Really cool effect, very impressive!

Somone (ZURB) says

I eventually got it working. I need to add an additional line of CSS:

ul.polaroids li {display:inline;}

And the fix suggested by somebody else:

ul.polaroids li a:hover {.. instead of just ul.polaroids a:hover {

Feel free to see my post

Thanks for opening my eyes to the possibilities of CSS.

neel (ZURB) says

excellent gallery i added to my list.


thanks for the great work

e11world (ZURB) says

Beautifully done!! Totally love it!

ed (ZURB) says

your demo looks great Unfortunately my implementation does not. Had the same problem as james, that the first picture hovered and the rest did not. Also, they actually look nothing like a polaroid: just a bunch of pictures with a link text onder it and sometimes next to it.

Also still the annoying bullit as a remnant of the use of 'ul' tag.

Pictures have a blue line around it coz they are links.

works in FF3 not in IE8

Now no doubt this can be fixed by some further coding, but obviously you certainly fantastic code is not really that transportable. A lot of tinkering still needs to be done individually.

Nevertheless great code

Dirty Henry (ZURB) says

Hi, thanks for the awesome tutorial. I've adapted your work with the Compass tool to make it more flexible (cf. the french post in my blog - i'll try to translate it later this week- http://www.mickaelflochlay.com/spip/Effet-Polaroid-en-CSS-et-Fluid).

And I've used the result of this in this other website post : http://www.deadrooster.org/Compile-MP3-du-NET-01 So... thanks a lot :)

Beben (ZURB) says

i'll post about this web... heres a lot greats article for web/blog thanks a lot ^^

Gerlach Firm (ZURB) says

Interesting, i might have to try this on a future project to see the reaction it gets. Thank you for the article.

hp (ZURB) says

Awesome tutorial! Cheers! :)

Cesar (ZURB) says

You guys are awesome! Thanks for sharing this. I will use it in my next project.

Harley (ZURB) says

Thought I'd drop a link and show you what you helped me put together..!


Thanks again :)

Carlo Zottmann (ZURB) says

Hi James,

the change from ul.polaroids a:hover to ul.polaroids li a:hover did the trick, thanks. But you should change the demo page as well, methinks.

Cheers from Germany,

syxt (ZURB) says

you are the web is very good ! I love's

wordpress developer (ZURB) says

Nice article cheers

Chris Raymond (ZURB) says

I'm curious to know for those viewing in IE 7 and IE8--do you just see an unordered list of images? I ask because I have no problem that some browsers won't see the rotation or nth child selectors working, so long as they can still see the images. I work on a Mac so I can't see what this looks like in IE.

Harley (ZURB) says

Chris, the images are still visible. They look similar to a Polaroid photo still, too. Just without rotation, and the padding seems larger.

employee training and development (ZURB) says

That's cool! You really made a good displaying of details that can help some people. Thank you for this post.

Mathijs (ZURB) says

Is it possible to do this with divs so i can place text instead of images ?

Rdomingue (ZURB) says

Hey Great job. My question is about another thing. How the hell you style your code. It is really clean, nice and perfectly what i'm looking for. (the colored code with the black background) I've take a look and it seem's it's all made by hand. It's surprise me if it's really the case. Thanks for your answer.

Ogy (ZURB) says

Hey, great script! I have a question - if the title is longer than the size of the image, the title text doesn't break so that it fits into the width of the box. Is it possible to automatically break the text into couple of lines if it is longer?

Thank you very!

Vale (ZURB) says

Thanks Yames, you fix for the hover effect worked fine for me!