Saturday, March 21, 2009

How To Make A Polaroid Photo Style Background For Your Images With CSS Without Using Background Images

I wanted to decorate the photos on my blog with a Polaroid-style look. If you Google for 'polaroid css', you'll get quite a few results. But I didn't quite find what I was looking for, especially without using a background image like in this post or this post. The problems with this method are
  • If the end user turns off images, the effect is lost
  • The client would have to download yet another image (however light)
  • The most importantly, this method will not scale! You'd have to either crop your images to fit the fixed size or have multiple sizes of the polaroid backgrounds for different sized pics.
  • If the background image is a PNG (which let you have gradiant transparency as opposed to GIFs which support transparency for any one colour), then you'll run into IE6's notorious lack of support

So the best way out is to use CSS. Here's what I've come up with. The CSS rules are:
.polaroid-container {
 position: relative;
 /* for being able to use absolute positioning for the 'tape' images, explained below */
 float: left;
 /* with a float we can a)embed the polaroid photo within text and have it wrap around and b) we don't need to specify a width/height */
 margin: 20px;
 /* we want to put some space between the polaroid photo and the surrounding content */
}

.polaroid-shadow {
 background-color: #CCCCCC;
 /* a light gray color, for the pretend shadow */
 text-align: center; /* aligns the text and image to the center */
}

.polaroid {
 background-color: #FDFDFD; /* a light gray background */
 border: 1px solid #999999; /* a thin border in darker gray */
 position: relative;
 /* this allows us to move the the polaroid div without removing it from the flow of the page i.e. we can offset it and show the 'shadow' from below */
 left: -3px; /* we move the polaroid to the left... */
 top: -3px; /* ...and up */
}

.polaroid-content-container {
 margin: 15px 15px 20px 15px;
 /* a little extra margin at the bottom */
}

.polaroid-pic {
 display: block;
 /* this prevents the caption from sliding in next to the image,
since both are inline elements by default */
 border: 1px solid #CCCCCC;
 /* give the image a thin, slightly gray border */
 border-top: 1px solid #999999;
 /* then we override the border for the top and right... */
 border-right: 1px solid #999999;
 /* ...for a very subtle film-embedded-in-the-paper effect */
 margin-bottom: 15px;
 /* we need some gap betwen the image and caption, which also serves to increase the bottom portion of the polaroid, adding to the effect */
}

.polaroid-caption {
 color: #777777; /* dark gray for the caption text... */
 font-size: 0.75em;
 /* ...which will be 75% of the enclosing container's font... */
 font-style: italic; /* ...and will be italicised */
}

The HTML for the image should be:

<div class="polaroid-container">
    <div class="polaroid-shadow">
        <div class="polaroid">
            <div class="polaroid-content-container">
                <img class="polaroid-pic" src="your-image.jpg" />
                <span class="polaroid-caption" />
            </div>
        </div>
    </div>
</div>


You should see something that looks like this:
Sample Screenshot Of Polaroid-style Background

BONUS! - Sticky tape to hold your polaroid in place


This is a pretty common effect on the web now, having sticky tape hold up your images, and it's fairly easy to incorporate into our existing code.

First, you need to make the images of the tape you're going to be sticking the photo with. This tutorial is the simplest and fastest way to get it done. You can also get the images I've made - for the top left corner and the top right corner.

Now, you could easily add the PNGs into the code but there is the problem of lack of support with IE6. So we need some hacks to get the transparency to work. This post links to different ways of getting it done. The (best) way I initially used was using the iepngfix.htc script. But this uses relative URLs and so requires access to your HTML/CSS/images directory in order to place a blank GIF for the transparency. This isn't going to work with Blogger. So I'm using the other method detailed on the post linked above, which works for IE6, Firefox and Chrome and Safari. It fails on Safari but luckily, doesn't break anything; your image will simply be missing the tape. If you have your own webserver hosting your blog or if you do have access to the aforementioned directories, go ahead and use the iepngfix; it'll work more efficiently and also works with Safari.

The changes to the HTML and CSS:
.tape {
 position: absolute;
 /* absolute positioning so that the images can be place at will. This works because the container class specifies relative positioning for the div */
}

.top-left {
 width: 80px; /* specify the width... */
 height: 87px; /* ...and height */
 top: -20px; /* place the image, offset it to top by 20px */
 left: -20px; /* and to the left by 20px */
 /* Only IE will use this filter */
 filter: progid : DXImageTransform.Microsoft.AlphaImageLoader ( enabled =
  true, sizingMethod = scale, src = 'tape-tl.png' );
}

/* similar rules for the other tape */
.top-right {
 width: 87px;
 height: 80px;
 top: -20px;
 right: -20px;
 /* Only IE will use this filter */
 filter: progid : DXImageTransform.Microsoft.AlphaImageLoader ( enabled =
  true, sizingMethod = scale, src = 'tape-tr.png' );
}

/* IE ignores styles with [attributes], so it will skip the following. */
.top-left[class] {
 background-image: url('tape-tl.png');
}

/* IE ignores styles with [attributes], so it will skip the following. */
.top-right[class] {
 background-image: url('tape-tr.png');
}

Add two spans to the HTML
<div class="polaroid-container">
    <div class="polaroid-shadow">
        <div class="polaroid">
            <div class="polaroid-content-container">
                <img class="polaroid-pic" src="your-image.jpg" />
                <span class="polaroid-caption" />
            </div>
        </div>
    </div>
    <span class="tape top-right">&nbsp;</span>
    <span class="tape top-left">&nbsp;</span>
</div>

Here's an image of what you should be seeing with this code:
Sample Screenshot Of Polaroid-style Background With Sticky Tape On Corners

Now, the problems with this method of polaroid-izing your shots:
  • It breaks for really wide images (about as wide as the monitor resolution) because of the 20px margin on the outermost div
  • Lengthy captions will cause the width of the 'polaroid' to increase, giving a lot of whitespace. The text doesn't wrap. The solution is to manually add line-breaks (<br />) to your text at appropriate points

But it still works and as of now, it's the best way I can think of. If you have any suggestions or improvements, do leave a comment!

 [UPDATE] 21 Mar 2009: Turns out that the PNG transparency hack does work with Safari.

1 comment:

Wolfestine said...

Finally used ur css. Thought u'd like to know that it works with Chrome too (not a surprise, since u already know that it works with Safari) Chrome too ignores the insane IE filters. Though it doesn't like the self closing tag u used in the caption-span. Also, I added a tiny JavaScript (PHP would have been cooler) to it to swap the images after every 5 seconds. to make a slide show out of it. Works gr8. Thanks.