tags:

views:

1125

answers:

6

In the following HTML, I'd like the frame around the image to be snug -- not to stretch out and take up all the available width in the parent container. I know there are a couple of ways to do this (including horrible things like manually setting its width to a particular number of pixels), but what is the right way?

Edit: One answer suggests I turn off "display:block" -- but this causes the rendering to look malformed in every browser I've tested it in. Is there a way to get a nice-looking rendering with "display:block" off?

Edit: If I add "float: left" to the pictureframe and "clear:both" to the P tag, it looks great. But I don't always want these frames floated to the left. Is there a more direct way to accomplish whatever "float" is doing?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head><title>foo</title>

<style type="text/css">

.pictureframe {
 display: block;
 margin: 5px;
 padding: 5px;
 border: solid brown 2px;
 background-color: #ffeecc;
}

</style>

</head>

<body>

 <div style="border: solid blue 2px; float: left;">

  <span class="pictureframe">
   <img alt='' style="display: block;"
    src="http://stackoverflow.com/favicon.ico" />
  </span>

  <p>
    Why is the beige rectangle so wide?
  </p>

 </div>

</body>
</html>
+1  A: 

The beige rectangle is so wide because you have display: block on the span, turning an inline element into a block element. A block element is supposed to take up all available width, an inline element does not. Try removing the display: block from the css.

neouser99
If I do that, then the image doesn't sit inside the frame -- did you actually try this, and does it look good in your browser?
raldi
+3  A: 

The right way is to use:

.pictureframe {
    display: inline-block;
}

However, Firefox 2.x doesn't support this, so you may need to use a workaround, such as using display: table instead for that browser:

.pictureframe {
    display: table;
    display: inline-block;
}

Setting it to be a table has some drawbacks, depending on your situation, table-cell may be more appropriate.

Edit: Floating the element also produces the same effect, this is because floating elements use the same shrink-to-fit algorithm for determining the width.

Jim
Ugly, but out of the answers so far that actually work, this feels the least hacky to me.
raldi
A: 

The only way I've been able to do picture frames reliably across browsers is to set the width dynamically. Here is an example using jQuery:

$(window).load(function(){
  $('img').wrap('<div class="pictureFrame"></div>');
  $('div.pictureFrame').each(function(i) {
    $(this).width($('*:first', this).width());
  });
});

This will work even if you don't know the image dimensions ahead of time, because it waits for the images to load (note we're using $(window).load rather than the more common $(document).ready) before adding the picture frame. It's a bit ugly, but it works.

Here is the pictureFrame CSS for this example:

.pictureFrame {
  background-color:#FFFFFF;
  border:1px solid #CCCCCC;
  line-height:0;
  padding:5px;
}

I'd love to see a reliable, cross-browser, CSS-only solution to this problem. This solution is something I came up with for a past project after much frustration trying to get it working with only CSS and HTML.

Keeth
A: 

Yes display:inline-block is your friend. Also have a look at: display:-moz-inline-block and display:-moz-inline-box

stucampbell
+1  A: 

Adding "float:left" to the span.pictureFrame selector fixes the problem as that's what "float:left" does :) Apart from everything else floating an element to the left will make it occupy only the space required by its contents. Any following block elements (the "p" for example) will float around the "floated" element. If you "clear" the float of the "p" it would follow the normal document flow thus going below span.pictureFrame. In fact you need "clear:left" as the element has been "float:left"-ed. For a more formal explanation you can check the CSS spec although it is beyond most people's comprehension.

korchev
A: 

You don't need any of the float junk. Changing your image to display as a block level element will allow it to take on the properties of a block level element. So just do this:

<img alt='' style="display: block; padding: 5px; border: 2px solid brown;" src="http://stackoverflow.com/favicon.ico" />
hal10001
That didn't work for me -- did you try it?
raldi
I did try it, and it did work. What browser are you using?
hal10001
raldi
Thats because you didn't remove the style from the pictureframe. Take the span out that is wrapping the image and it will work. Trust me, this is a better solution than dealing with floats.
hal10001