Description
Description of various methods to make block-level elements to be only as wide as their contents, i.e. "shrink wrap"
Date of the Tutorial
Sat Aug 22 14:47:10 2009
Description of various methods to make block-level elements to be only as wide as their contents, i.e. "shrink wrap"
Sat Aug 22 14:47:10 2009
In this tutorial I will first explain what is the "shrink-wrap" concept and will show you several examples of achieving this effect along with explanations of when each of them would be appropriate to use.
Unless mentioned otherwise, methods described in this tutorial are supported in all modern browsers as well as IE7.
There is a great page on Brunildo.org that you can use as a quick refference.
Default behaviour of block-level elements (or rather, elements with display
property set to block
, list-item
and possibly run-in
) is to expand width-wise as wide as they can; to take all available width. However, this behaviour may be not wanted in certain cases and instead you would prefer that the element would be just as wide as the content it contains. You could set width
to gain something along those lines, but what if content is dynamic or you want the same style to apply to several elements and setting different widths on each is not something you would enjoy doing? This is where "shrinkwrapping" comes into play.
Shrink-wrapping is more "officially" known as "shrink-to-fit" and describes a behaviour of the element where such element's width is defined by its content and it is smaller than the maximum available width if there is not enough content to expand it to such width; much like how height behaves by default.
There are several properties that make elements shrink-to-fit their content. Each of these has certain side-effects (nope, there is no shrink-to-fit: yes
) as well as varying browser support; for that reason, you need to know which properties would be the most appropriate to use in any given situation. Grab a glass of your favorite drink and let's go!
Shrink-to-fit using float
property is by far my favorite one. All sane browsers support it and the side effects are miniscule: all is needed sometimes is to either contain floats or use clear
property on the following element to force it to appear below our shrinkwrapped element. Let's take a look at the demo:
Ahhhh!! What a shrink!
<div> <p>Ahhhh!! What a shrink!</p> </div>
div { padding: 10px; overflow: hidden; display: inline-block; } div { display: block; } p { float:left; background: #A5A5A5; border: 1px solid #000; }
All we did to our ' element"><p>
element is apply float
set to value left
, although value right
works just as well with the exception that your element will be on the right. If you want your element centered, then you probably should use a different shrink-wrap method.
The overflow
set on the containing ' element"><div>
is for containing floats and the display
property toggle in two rulesets gives IE7 need for containing floats.
display: inline
Despite the fact that setting display
property to value inline
on the element and this seems to be a popular thing to recommend by beginners, this method has a ton of quirks most of those beginners are not aware about, and they get bitten more than required by it. Let's see what "limitations" you would acquire using this shrinkwrap method:
width
or height
padding
does not affect surrounding contentbackground
is not drawn between lines of text if the content wraps over several lines and sufficient line-height
is present; even if the gaps are not visible due to small enough line-height
, background-image
will not show up correctly as now we would be dealing with several line boxes instead of one block-box.<p>
element with {display: inline;}
will make them appear side-by-side.*phew* quite a "disability" list, huh? There are more side-effects for this method, however in some cases it could be just the thing to hit the spot - for once, you can apply text-align
on the ancestor element to affect the position of the shrink-wrapped element. Let's take a look at our demo:
Ahhhh!! What a shrink!
<div> <p>Ahhhh!! What a shrink!</p> </div>
div { padding: 10px; text-align: center; } p { display: inline; padding: 10px; background: #A5A5A5; border: 1px solid #000; }
Setting {display: inline}
on our ' element"><p>
element caused it to shrinkwrap around its content as can be seen by the border
and background
applied to it.
Also, notice that we have padding
set to 10px
on both, this is not related to the shrink-to-fit, however, notice that the vertical "gaps" between the border edges of our ' element"><p>
and its containing ' element"><div>
are far less than 10 pixels; this is one of the draw-backs of this method that I've mentioned earlier.
display: inline-block
Aside from a slight kick in the butt that IE needs for this method of shrinkwrapping, this method is quite decent as well. The only drawback I can think of is that the element will start behaving like it's inline-level - in other words, setting several consecutive elements to {display: inline-block;}
will cause them to stack up horizontally without causing "line break" and unlike the float method, there isn't much we can do. Let's take a look:
Ahhhh!! What a shrink!
<div> <p>Ahhhh!! What a shrink!</p> </div>
p { border: 1px solid #000; background: #ddd; height: 100px; display: inline-block; /* gives "layout" to IE */ } p { display: inline; } /* IE7 fix for inline-block */ /* Set display back for sane browsers */ html > /**/ body p { display: inline-block; }
What a hairy mess! Looks like I'm setting display
three times here. You can apply this fix with conditional comments as well to make things clearer. First of all, I've added padding
to the containing ' element"><div>
simple to show that the padding in my demo is not a side-effect of this method. Also, I have set height
on our ' element"><p>
simply to show that we still can set dimensions unlike the display: inline
method.
What makes the ' element"><p>
element shrinkwrap in sane browsers is just one line of code: {display: inline-block;}
. The reason I am setting display
three times is done for IE7. To acheive the {display: inline-block;}
behavior in IE7 we need to give our ' element"><p>
"layout" as well as set display
property to value inline
. To achieve that with conditional comments, we would simply put p { zoom: 1; display: inline; }
in IE7 targeted condcoms.
In my example I've put the fix in regular CSS code. First we set {display: inline-block;}
on the ' element"><p>
element. This will give the element "layout". In a later ruleset we will revert the display
value to inline
(this "display toggle" makes the "layout" "stick" in IE despite the fact that we are changing the display
later on). Now our IE is all set, however, sane browsers not so because we reset display
to inline
. What we are doing with the last ruleset in my example is settin display
back to inline-block
for sane browsers, and IE7 will ignore that specially crafted selector because IE7 has "Child Selector Comment Bug".
This method is probably the one you will use the least for the sake of shrinkwrap. Reason for that being that elements with {position: absolute;}
, despite getting shrinkwrapped, are taken out of normal flow, which may or may not be what you had in mind for your task.
Note: while this method works in IE7, if an element inside your shrinkwrapped element has "layout", the shrinkwrap will fail.
Ahhhh!! What a shrink!
<div> <p>Ahhhh!! What a shrink!</p> </div>
p { border: 1px solid #000; background: #ddd; position: absolute; top: 5px; left: 5px; }
The only thing that makes our ' element"><p>
element shrinkwrap is position
property set to value absolute
(fixed
shrinkwraps too, but I won't be covering that). However, you can see that I have a couple of extra things set as well. First of all {position: relative;}
set on our ' element"><div>
is done to make top
and left
on our ' element"><p>
to relate to our ' element"><div>
. Most importantly, you can see that I've set height
on our ' element"><div>
; the reason for that is that {position: absolute;}
takes the element out of the flow, without that height
our ' element"><div>
would have zero height because ' element"><p>
is now out of normal flow and therefore does not give any "support" to ' element"><div>
s height.
display: table
Lastly, I will talk about shrinkwrapping with display: table
. This method of shrinkwrap is quite good as far as draw-backs go (can't really think of anything substantial), however, this method is not supported in IE7. Let's have a look:
Ahhhh!! What a shrink!
<div> <p>Ahhhh!! What a shrink!</p> </div>
p { border: 1px solid #000; background: #ddd; display: table; margin: 5px auto; }
Aside from IE7 support, we have quite sweet deal. Not only {display: table;}
shrinkwraps our ' element"><p>
, we do not need anything special on the container and check this out: left and right margin
s set to value auto
center or ' element"><p>
as if width
was set on it!
In conclusion, I would like to note that there are a few other properties that cause element to shrinkwrap. I will not cover them in this tutorial as I believe they are very rarely used. However, using the knowledge you have gained in this tutorial, you will have absolutely no trouble applying those extra properties should the need arise.