One element of the new Opus design that — IMHO, of course — adds some really cool-yet-subtle eye candy are the semi-transparent borders that appear on many of the images (an example would be the thumbnails in the “Recent Music Reviews” and “Recent Movie Reviews” widgets over there the right column).
I quickly came up with the idea in my Photoshop mockup without giving much thought as to how I might actually make it work when I got to the HTML/CSS stage. But once I got there, I found myself in a bit of a quandary. I had done something similar in an earlier iteration of Opus, using a transparent GIF image to add rounded corners to some of the images (this is similar to the approach Facebook uses to add rounded corners to the avatars on your “Wall”).
However, that approach assumes that you always know the size of your images, that your images are always the same size. Which is the case with 80% of the images on Opus, but there are plenty of images whose sizes are all over the place. I’d either have to create overlay graphics for every size, or make sure that I always used the same sizes of images in my entries time and again. Which aren’t bad ideas in and of themselves, but I was looking for a little more flexibility.
Ideally, I wanted something that could be applied to any image of any size, be it a photo, some artwork from a CD, a movie poster, etc. After about 30 minutes or so, I came up with the following method. It’s by no means original, and there are some drawbacks, but it works for my purposes — maybe it’ll work for yours.
Now, if you’re like me, and you learn better by seeing something in action and breaking it down, I’ve created a very basic demo that shows the technique in action. For the rest of you, though, read on.
The HTML and CSS
First, I wanted to get my HTML and CSS in place. Only then could I start looking at ways to make things dynamic. Here’s the basic HTML that I came up with:
And here’s the sample CSS:
Let me explain what’s going on. First, I’m wrapping the image within a span tag that has the class of “border” and I’m setting the width of the span equal to the width of the image using an inline style. Then I’m putting another span tag directly after the image; this span’s width and height are both set to be 10 pixels less than the image’s width and height, respectively.
In the CSS, I’m specifying the “border” span to be a block element with relative positioning and a margin. The image has been set to be a block element as well with no margin. And finally, the second span is also made a block element and is positioned absolutely above the image.
The second span is also given a 5 pixel white border, which is why its width and height were set to be 10 pixels less than the image’s width and height — the border accounts for 10 pixels of width and height, thus taking up the extra space. And finally, its opacity is set to “.5” to create the semi-transparency.
And finally, I use jQuery’s “after” function to inject the second span right after the image but before the “border” span’s closing tag. I create the second span’s inline style — which sets its width and height to be 10 pixels less than the image’s — using the “w” and “h” variables that I had created previously.
Also, if you want this technique to work in Internet Explorer, you’ll need to add some “special” CSS:
IE doesn’t support the “opacity” CSS attribute. Instead, you have to use IE’s proprietary filters to control an element’s opacity. You can find more information here. (I recommend putting the above CSS in a second, IE-specific stylsheet and including it via conditional comments in order to keep things nice and tidy.)
I’d be remiss if I didn’t mention a few caveats with regards to this technique:
- If you compare the above code snippets to the code I’m actually using on Opus, you’ll see some differences. This is because I have several different image classes to control image alignment. Nevertheless, what I use on Opus and what I’ve outlined above are essentially the same technique.
- Some people might take issue with the markup I’m using. For example, it requires setting inline elements to be block elements. It also requires inline styles. Normally I try to avoid these things, but in this case, I took a more pragmatic approach. However, if you’re an absolute stickler when it comes to this sort of thing, then this technique may not be for you.
- This technique has been tested in Safari 3 (Mac), Safari 4 (Mac), Firefox 2 (Mac/PC), Firefox 3 (Mac), IE6, and IE7. I’d love to hear what users of other browsers see.
- Finally, I’m not the first person to do this. Do a search for “image overlays CSS” or something similar and you’ll find plenty of other ways for accomplishing this look. But this is the technique that worked for me.
If you use this technique, let me know. I’d love to see it in action elsewhere on the Web. And of course, if you have any ideas for improving this technique, I’m all ears.