Wed, 2005-04-13 06:50
See also, IE White Space Bug.
There are cases in which IE treats the white
space "\n" between and the next
<ul> <li>list item</li> <li>list item</li> <li>list item</li> <li>list item</li> </ul>which should give you this,
list item
list item
list item
list item,
instead gives this,
list item
list item
list item
list item.
The common fix has been to remove the offending white space;
<ul> <li>list item</li><li> list item</li><li> list item</li><li> list item</li></ul> <ul> <li>list item</li>< li>list item</li>< li>list item</li>< li>list item</li>< /ul> <ul> <li>list item</li><li>list item</li><li>list item</li><li>list item</li></ul>
That works, but is ugly. In the case of non-trivial lists, the formatting can
make the list code all but unreadable. Plus, jiggering the html
formatting to control display is just wrong.
After proclaiming I had found the secret to the IE white space bug in
lists, I found there were 'issues'. A bulleted list had screwy
placement of the bullets. As long as you don't need the bullets, all
is well. I don't think that little caveat makes for a good cure. So
the search was restarted.
I thought I had discovered the trigger to be whether the list item was
dimensioned, eg. the width set. From that I figured MSIE's hasLayout()
was involved. There was another clue, and I glommed onto the wrong
one. The trigger is actually a link with {display: block;}[1]. You
may see this in the following test cases;
(1)
<ul id="plain"> <li>list item</li> <li>list item</li> <li>list item</li> <li>list item</li> </ul>
(2)
<ul id="inline-links"> <li><a href="#" rel="nofollow">some inline link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> </ul>
(3)
#block-links a { display: block; } --------- <ul id="block-links"> <li><a href="#" rel="nofollow">some block link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> </ul>
Only #3 will exhibit the white space bug. So an undimensioned li is not
the prime mover. Will setting a dimension do away with the extra
space? Yes. That only reinforces my feeling this is a hasLayout()
related 'feature'.
/* Hide this from IE-Mac \*/ * html #hacked-li li { height: 1px; } /* End the hiding */ ---------- <ul id="hacked-li"> <li><a href="#" rel="nofollow">some block link</a> hacked li</li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> </ul>
You'll notice the bullets. They go to the bottom of the li. They're
too low on a single line, and opposite the last line on multi-line
list items. I used the Holly hack to trigger hasLayout(), but all
methods do the same or worse.
Properties and corresponding values that, if set, cause an element to
have layout.[2]
-
CSS property: Value
--------------------
display: inline-block
height: any value
float: left or right
position: absolute
width: any value
writing-mode: tb-rl
zoom: any value
The hasLayout() property applied to the li fixes the white space bug
but causes its own set of problems. MS says hasLayout() applies to
anchors, too. Since the anchor caused the problem, can it fix it?
/* \*/ * html #hacked-link a { height: 1px; } /* */ ---------------- <ul id="hacked-link"> <li><a href="#" rel="nofollow">some block link</a> hacked link</li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> <li><a href="#" rel="nofollow">some link</a></li> </ul>
Why yes. Yes, it does, and without the shifted bullets. I think I
can now declare a general fix for the IE white space bug. Cause the
anchor element to have hasLayout()=true. The full test case[5] should
bear me out.
All that, and I did run into another fairly unknown fix[3]. Give the
li a bottom border! How simple is that? It has limitations on where
it can be used, but when it can ….
And yet another fix is found[4]. This has already been mentioned, {display: inline-block;}, as setting hasLayout=true. What is new is that we can use that as a trigger, then go to {display: block;} without un-setting hasLayout. So, doing
a { display: inline-block; } a { display: block; }will set hasLayout, but {display: block;} will apply as overruling the earlier display value.
cheers,
gary
**************************************
[1] Hicks Design
[2]
hasLayout property
[3] css-discuss
[4] Thanks to C, aka SuzyUK, a mod/guru at WebmasterWorld Forums, and aka cssangel in these forums.