DaveJays Blog

Flickr

Twitter

G56ogle - Google Search with Style - 4 themes!

Dynamically Resizing CSS Picture Frame on Any Background

I've always hated the lack of interesting frames or borders on images on the web. Most picture frames on images have either had to have a fixed width (custom made for a particular image size) or they're simply part of the image being displayed. So I came up with a way of getting a dynamically sized border onto an image that works well on any background. All you have to worry about is the presentational markup required for it to work. So I put some JavaScript to Add Extra Markup Around a Tag together, to handle the presentation markup required, adding a layer of separation between the content and the presentation. The frame I'm using is made up of transparent PNGs to improve its look, but it could easily work with GIFs if designed appropriately.

Example of background variations

image

Example of Varying Sizes

This effect doesn't work in IE6, so if you're using that browser you'll just see 3 images with no frames on them.

image image image

How it's built

The first part is getting the html in place. It should look something like this:

  1. <div class="frameName">
  2. <img src="somegraphic.jpg" alt="graphic" width="300" height="300" />
  3. <div class="upper_left"><div>
  4. <div class="upper_right"><div>
  5. <div class="lower_left"><div>
  6. <div class="lower_right"><div>
  7. </div>
  8. </div>

Now all that's required is to style it up. The containing element needs to be positioned "relative" so that it's child elements can be positioned "absolute" relative to it. It also needs to be floated in some direction so that it will naturally scale itself to the size of the image within it.

Normal Div

image

Div Floated Left

Sample Image
Floating the div left makes it act like shrink-wrap around it's child elements, rather than expanding.

Now that the width of the container is set and its position is "relative", the four corner elements can base their position and widths off of this element.

Positioning the corners

So now all that's left to do is position the corners onto the image. We can set the width or height to 100% and it will be as wide or high as the image and not any wider. The frame uses a total of four corner graphics positioned absolutely to their respective corners with CSS. The width and height of each of the corners determines how large of an image they will work on, so if you're going to have an image 800 pixels wide, pe prepared to have your corner graphic at least that wide.

Picture Frame Corner Positions

To set the upper left corner for example we simply set it's position to absolute, make it 0px from the top and left side and set the background-image to the appropriate url as seen below.

  1. div.frame_scrapbook div.upper_left {
  2. width: 100%;
  3. height: 100%;
  4. position: absolute;
  5. top: 0px;
  6. left: 0px;
  7. background: transparent url('layout/scrapbook2/frame_upper_left.png');
  8. background-repeat: no-repeat;
  9. background-position: top left;
  10. }

Adjusting for the transparency

Positioning all the corners that way seems well and good, except each corner piece has a large amount of it that is transparent. As can be seen below, it causes problems if it's not adjusted properly.

Corner with No transparency adjustment

To fix this we need to make some adjustments in the margin to account for the change. Since the upper left corner is bleeding into the upper right corner, we'll just scoot the entire corner element to the left. We can do this by setting margin-left: -38px

Corner with margin adjustment

This fixed the right corner, but now the left corner is messed up. But it's easy enought to fix that, just set background-position-x: 38px. This simply offsets the background image 38px from the right.

Corner with margin and background adjustment

So now we know how to fix one corner, just apply the same principle to all remaining corners and you should end up with CSS that looks something like this.

  1. div.frame_scrapbook {
  2. position: relative;
  3. float: left;
  4. }
  5.  
  6. div.frame_scrapbook div.upper_left {
  7. width: 100%;
  8. height: 100%;
  9. position: absolute;
  10. top: 0px;
  11. left: 0px;
  12. background: transparent url('frame_upper_left.png') no-repeat 38px 38px;
  13. margin-left: -38px;
  14. margin-top: -38px;
  15. }
  16.  
  17.  
  18. div.frame_scrapbook div.upper_right {
  19. width: 41px;
  20. height: 100%;
  21. position: absolute;
  22. top: 0px;
  23. right: 0px;
  24. background: transparent url('frame_upper_right.png')no-repeat right 38px;
  25. margin-top: -38px;
  26. }
  27.  
  28.  
  29. div.frame_scrapbook div.lower_left {
  30. width: 100%;
  31. height: 42px;
  32. position: absolute;
  33. bottom: 0px;
  34. left: 0px;
  35. background: transparent url('frame_lower_left.png') no-repeat 38px 0px;
  36. margin-left: -38px;
  37. }
  38.  
  39.  
  40. div.frame_scrapbook div.lower_right {
  41. width: 42px;
  42. height: 42px;
  43. position: absolute;
  44. bottom: 0px;
  45. right: 0px;
  46. background: transparent url('frame_lower_right.png') no-repeat top right;
  47. }
  48.  

Weaknesses

There area few weaknesses to this approach:

  • It doesn't work in Internet Explorer 6

    Mostly because the CSS required for this just doesn't work right in IE6, but also because the frame is made up of PNGs with alpha-transparency - and IE6 doesn't do well with those
  • The Image has to be floated

    Depending on how this technique is implemented in a particular situation, this could be a problem, but for most cases it can be adjusted for with some cleverly placed clearings.
  • The non-semantic markup required

    This is probably the biggest drawback to this technique. If the markup is inserted directly into the HTML it's cluttered and harder to use casually. If the code is inserted dynamically with javascript on selected elements, the frame isn't seen until the page is completely and totally loaded. This can be annoying if the page gets hung up loading one final element, but most of the content is already rendered.

Example

So that's how it's done. If you'd like you can view a sample of all the elements (including the javascript) working together. Feel free to play with it all you want. You can also download a zipped package of everything you need to get it working. If you use it, I'd love to take a look at it. Feel free to use the frame I designed as well. I'm hoping to make available some more in the near future.

posted in: CSS | Design | Development |

Ira • Feb 16th 2008 • 8:44 pm

I love the border you've created. I'm wondering though, is it not possible to have the image be a link as well?

I've tried something like this below:

<div class="frame_scrapbook">
<a href="#"> <img src="vancouver.jpg"></a>
<div class="upper_left">
<div class="upper_right">
<div class="lower_left">
<div class="lower_right">
</div>

The border appears, but I cannot click on the image.

Any advice would be appreciated.
Thanks,
-ira
ihgold@comcast.net

Ira • Feb 16th 2008 • 8:45 pm

Oops, the whole html lines didn't appear. I guess because of the tags. Basically, I included an href before the image tag.

Dave Joyce • Feb 17th 2008 • 5:42 pm

Hi Ira,

Sorry my comment system doesn't support code better than it does. I fixed your comment above so things looked right.

I believe the reason it doesn't work is because the corner divs are are above the image/anchor tag. So you have to literally look through them to see the image beneath. So when you click on the image, you're actually clicking on the frames above the image.

If you put the anchor tag around the entire "frame_scrapbook" div it should work. The anchor tag is a block level element like the div, so it should validate just fine.

janx • Mar 21st 2008 • 1:21 am

hello, your website is messed up on ie6. I know that png's aren't supported in ie6 but I think you're right on what you've said that "websites are for all: people, browsers, etc.". so would you still prefer on using png? thanx. i just need an advice.

Dave Joyce • Mar 21st 2008 • 9:13 am

@janx - I'm aware the PNG at the top doesn't work in IE6 and the menu is downgraded as well. I probably wouldn't take such an approach with a client, but for my blog and the audience I think it will be reaching. I made the decision to be more liberal in the design - and it may have the added result of showing my contempt for Internet Explorer. But as far as working with client's go. I would still recommend supporting IE6 as it still has a very large audience.

Zach • Mar 27th 2008 • 10:03 pm

Hey Dave -

I am using your method to build a photo frame around my images in my photoblog, but I am encountering the float problem you alluded to. Would you mind taking a look here:

http://www.itinerantangler.com/photoblog

Ordinarily the image is centered and the footer materials are also centered; I think you can see how it is broken. Any ideas on how to fix it up? (I also need to touch up the PNGs - they are just placeholders for now, and will probably eventually drop *behind* the images.

Thanks!
Zach

Zach • Mar 27th 2008 • 10:11 pm

I am going to switch back over to the other design for the time being because your method was breaking the site, but I am very interested in making this work. Please email me at ZachMatthews at Gmail.com if you don't mind having a look.

Thanks,
Zach

Dave Joyce • Mar 27th 2008 • 10:37 pm

@Zach, Yeah I had a look. I liked the frame you were using.

I originally wrote this really desperate for it to work, but I think it's clear that it's too cumbersome to be reliably used. I'm looking into a good way to reliably implement the core principles behind the frame, probably something using jQuery. I'll let you know if I have an update.

Billy • Sep 1st 2008 • 12:48 pm

When I view your sample in IE6 I see the bottom frames. Is there a way to exclude this for IE6?

Dotan Cohen • Nov 15th 2008 • 12:57 pm

I have incorporated your frame technique in my Photo Album:
http://dotancohen.com/eng/pictures/index.html

It still needs some work (I need to make the images larger, and it messes up on wide displays) but it is usable. Thanks!

Dave Joyce • Nov 15th 2008 • 1:02 pm

@Dotan Cohen

Thanks, I'm glad it's working (for the most part) for you. I really need to refine the concept here, I think it *could* be really a lot more useful than it is.

joe • Mar 25th 2009 • 9:55 am

I'm using this for a photo album. It's working great, except that my photos are tall (800px) and the upper_right and upper_left images don't seem to be tall enough. Do you have larger images available for the border?

thanks!

Mike • Apr 14th 2009 • 12:44 pm

Hey, I wanted to know how I would make a site with the same idea with a frame around it but I wanted to use a picture of a TV with the screen being the inside of the picture frame? Should I use the same process?

Dave Joyce • Apr 14th 2009 • 12:53 pm

@Mike - A TV frame would be much more complicated. I think using a fixed width frame would probably be a better choice in this instance. You could just create the TV frame with a transparent screen and overlay it on the image with CSS using absolute positioning.

yogi • Sep 4th 2009 • 10:49 am

Hi.

Im trying to use this method to frame pictures on my site.

The site is actually to sell photo frames.

The problem im having is that some of my frames have an uneven pattern and therefore when it comes to the corners, there is overlapping or 'cutting' of the pattern.

I thought maybe to absolute postion new corner images inside the divs (upper_left, upper-right etc) but with these divs having a background image, this wouldnt work!!

Any ideas?

Much appreciated

yogi • Sep 4th 2009 • 11:28 am

your form seems to have duplicated my comment!!

Dave Joyce • Sep 4th 2009 • 11:42 am

@Yogi - Yeah, that's one of the disadvantages of this method = / Not sure I have a solution to it.

Weird about the duplicate commenting. Not sure why it did that.

Commenting has been disabled for this entry


Blog | About | Contact

Copyright © 2008 Exit 42 Design