Link to home
Start Free TrialLog in
Avatar of GlennGilbert
GlennGilbert

asked on

Setting "shrink-to-fit" width on a non-floated element

I need a non-floated box to have a variable width according to the content.  This is the behaviour for a floated box.

Ultimately this is to create a 'tab' style on a heading (setting the left and right background images).  


<p style="margin:0; border:1px solid black; padding:5px; background:yellow;">A full-width box</p>

<p style="float:left; clear:left; margin:0; border:1px solid black; padding:5px; background:yellow;">A shrink-to-fit box</p>


(e.g. section 10.3.3 of CSS2.1 spec)

Any ideas?
Glenn
Avatar of GrandSchtroumpf
GrandSchtroumpf

> Ultimately this is to create a 'tab' style on a heading
On a heading?  then why do you use a <p>?

You can try using an inline element to set your right background image:
<h3 class="MyHeading"><strong>My Heading</strong></h3>

Then in your CSS:

h3.MyHeading {
  margin: 0;
  padding: 0;
  background: url("left.png") left top no-repeat;
}

h3.MyHeading strong {
  padding: .5em 1em;
  background: url("right.png") right top no-repeat;
}
Avatar of GlennGilbert

ASKER

Oops.  The <p> represents any box element.

With your code,  the box will extend to the full width of the 'page'.

I don't want to specify the width as I don't know the width.
The designer's specified a sort of 'tabbed' style on the heading (I meant to say heading,  but the principle remains for any box).  It's fairly straightforward to set the tabbed style (as in this site's tabs).  

The interesting point is being able to style both ends of the content area without floating the element (which sets the shrink-to-fit content area size).  As there's no way of setting float:center,  a float isn't the best solution.
Hmmm, i see what you mean... i got confused in my sliding doors technique...
I thought you could use the narrow background image on the <h3> and the wide background image on the <strong>... but then the small image would be covered by the wide image.

I guess you need to use inline elements only...
Either set "h3 { display:inline }", or use an additional inline element inside your <h3>.
It's an interesting one this!   I'd never really thought about it before.

Going back to the standards:
 http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins
Setting the element to use inline formatting does indeed set a shrink-to-fit width.

But... you can't set padding & margins on inline elements!

Lets have a fiddle....
> But... you can't set padding & margins on inline elements!
Yes you can.  Inline elements don't have width nor height, but they have margins and padding.
... although it's possible to set the left/right padding (doesn't work on IE5 - see formating of display:inline horizontal menus),  it's not possible to set the other styles,  hence you rely on line-height.

I wonder if it's possible to use one of the table display styles...
Just note that it's not excellent coding style because of the unnecessary html tags...  CSS3 draft defines multiple backgrounds for one single element, but we'll need to wait a little before browsers support that feature.
One answer is to use a placeholder and absolute positioning (a bit like another answer from a few days ago).

Yuck.
>  Inline elements don't have width nor height,

Unfortunately this means that it's not particularly useful as the box has been 'partally' taken out of the flow.

However,  it's possible to add any padding back by adding it to the surrounding elements:  vis:

<style type="text/css">
h1 { background:#ffc;
 margin:20px; /* add some margin to counteract the proceeding 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:0; padding:0; }

h2 { background:#fcf;
 display:inline;
 margin:0; border:0;
 padding:20px; /* place some padding on the element */ }

p { background:#cff;
 margin:20px; /* add some margin to counteract the preceeding 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:0; padding:0; }
</style>
</head>

<body>
<h1>Some text</h1>
<h2>Some more text that's longer</h2>
<p>Shorter text</p>



Now to add some sliding doors....
Here's the solution... a 'tabbed' wrapped around a H2 element that varies in width as the font is changed (<ctl>+<scrolly_rolly_mousewheel>).

However,  there's a modification to the sliding doors technique.  The big drawback of the 'classic' sliding doors technique is that it uses two (or more) images.  This means there's loads of superflous HTTP transactions,  making the page appear slowly.  You can use one image and change the background attachment.  This technique can also be used for the variable-width and variable-height cornered box problem - www.alistapart.com's method uses FIVE images!  You can use one image,  provided:
 1) the edges are solid and match the background
 2) the centre's transparent.

So,  the working code:


<style type="text/css">
body { font-family:Verdana, Arial, Helvetica, sans-serif; }

h1 { background:#ffc;
 margin:10px; /* add some margin to counteract the proceeding
 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:0; padding:0; }

h2 { background:#fcf url(../images/Border_Box_1800w_369.gif) top right no-repeat;
 display:inline;
 margin:0; border:0;
 padding:10px 30px 10px 0; /* place some padding on the element */ }

h2 strong { background: url(../images/Border_Box_1800w_369.gif) top left no-repeat;
 padding:10px 0 10px 30px; }

p {      background:#cff;
 margin:10px 0; /* add some margin to counteract the preceeding
 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:1px solid red;
 padding:10px; }
</style>
</head>

<body>
<h1>Some text</h1>
<h2><strong>Some more text that's longer</strong></h2>
<p>Lorum ipsum de blah blah...</p>
</body>

Tested on Firefox and works great.  Was testing it on IE,  but it's exploded and sulking,  so I'll have to reboot my PC then...
Now rebooted.  In the mean time I tested it against Safari/Mac,  Opera8.5/Mac,  and Firefox/Mac.

They all work.

**even** IE 5/Mac works - wow!

Needless to say it doesn't work on Internet Exploder/windoze...
OK,  this is silly.

Could someone spread some light on this - why is IE adding an extra 10 pixels between the h2 and the strong?

Could this be the expanding box problem?

The following code fails on IE6/win.  It works on all other platforms.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body { font-family:Verdana, Arial, Helvetica, sans-serif; }

h1 { background:#ffc;
 margin:10px; /* add some margin to counteract the proceeding
 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:0; padding:0; }

h2 { background:#fcf;
 display:inline;
 margin:0; border:1px solid red;
 padding:10px 30px 10px 0; /* place some padding on the element */ }

h2 strong { margin:0;
 border:1px solid green;
 padding:10px 0 10px 30px; }

p {      background:#cff;
 margin:10px 0; /* add some margin to counteract the preceeding
 'shrink-to-fit' element.  Take into account collapsed v.margins */
 border:1px solid red;
 padding:10px; }
</style>
</head>

<body>
<h1>Some text</h1>
<h2><strong>Some more text that's longer</strong></h2>
<p>Lorum ipsum de blah blah...</p>
</body>
</html>
ASKER CERTIFIED SOLUTION
Avatar of GrandSchtroumpf
GrandSchtroumpf

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
> The big drawback of the 'classic' sliding doors technique is that it uses two (or more) images.
Not a big deal IMHO.  If you use 2 images, that's just one more http request on the first page view... which is really nothing (for all subsequent pages, it's the cached image that will be used).
Having multiple backgrounds on one single image only has advantages when used for roll-over effects, so you don't need to preload your "hover" images.
Fantastic!!!

I've made a modification to let it work on IE7 (which won't support the Holly hack). I've not changed the image,  but on the live version I will use a single image and change the background attachment.

Thanks for that,
Glenn



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Title</title>
<style type="text/css">
h3 { text-align: center; }

h3.MyHeading strong {
  padding: .5em 0;
  background: url("http://www.alistapart.com/d/slidingdoors/v1/norm_right.gif") right top no-repeat;
}

h3.MyHeading span {
  padding: .5em 1em;
  background: url("http://www.alistapart.com/d/slidingdoors/v1/norm_left.gif") left top no-repeat;
}

</style>
<!--[if ie]>
 <style>
   /* insert all the fixes that will be required by IE */
   html h3.MyHeading strong { padding:0; display:inline-block; }

   html h3.MyHeading span { display: inline-block; }
 </style>
<![endif]-->
</head>
<body>
<h3 class="MyHeading"><strong><span>My Heading</span></strong></h3>
</body>
</html>
> If you use 2 images, that's just one more http request on the first page view...
There's little problem with one or two extra images. However, by creating a set of generic 'furniture' images,  it does speed up the site - even in this age of broadband (just look at how slowly an eBay page loads).

The other benefit is that you rely less on designers to produce different size images.
Just checked out the other browsers:
Working:
 Firefox/Win, Firefox/Mac
 IE6, IE5.5
 Safari/Mac

Broken:
 IE5 - doesn't expand the box (standard problem)
 IE5/Mac - pretty knackered, which is hardly a surprise!

Glenn
I also prefer using "<!--[if ie]>" for IE-only styles.
<:°)