IE8 Hover Confusion with nested ul in list item

Ok after reworking the code to escape some performance issues with IE8 in my other thread I have gotten rid of that problem. I have set display:inline-block; on the parent list items and now a new glitch has come up in IE8.

Here is The Page

If you come in from the right side of the menu with your cursor real slow and hover over the last menu item (About ) IE8 will display the hover values on the very first menu item on the far left (Home). You can actually hold the “Home” hover open by resting in the right spot to the right of “About”.

Now, the cause of this seems to be the nested ul on that last list item.
Using This Test Case there are no nested uls and IE8 has no problem with it. Both those examples are using a negative margin on the main list items to kill the whitespace and then it is recovered on the sublist.

[B]#nav li[/B] {
    height:24px;/*optional*/
    display: -moz-inline-box;/* for FF2 (inline-box must be used for shrink wrapping)*/
    display:inline-block;/* for modern browsers */
    [COLOR=Blue]margin:0 -2px;/*kill whitespace without altering html*/[/COLOR]
    position:relative; 
    color:#FFF;
}
[B]#nav li li[/B] {
    display: block;
    height:auto;
    [COLOR=Blue]margin:0;/*reset from #nav li (reclaim the -2px whitespace kill)*/[/COLOR]
    text-align: left;
}

I thought it might have something to do with the negative margin on the main list items but it makes no difference to IE8, if I set the margins to zero instead of -2px it still highlights the first list item when you hover near the last link.

This seems to be about the nested ul on that last list item. Any thoughts on why IE8 is behaving this way?

Well I seem to have found a fix for it, strange that IE8 is the only one that needs this though. It worked fine in IE6/7 and every other browser I test in.

I already had a class on that last list item for dropdown styling so I just used it to pull an additional negative 2px to the right.

#nav li#last {margin:0 [COLOR=Blue]-4px[/COLOR] 0 -2px;}/* IE8 needs an extra 2px on the right margin */

The overall menu centering is off by 2px but it is hardly noticeable. The example has been updated so you will not be able to see the original problem in IE8 now without removing that ruleset.



EDIT:

I have set up a Test Case of the issues I originally explained. There are no negative margins in it, it is just a bare bones set up that works fine in all other browser yet shows strange behavior in IE8. Feel free to explain it to me if you know why IE8 is doing this. :slight_smile:

Actually Ray that doesn’t fix it. If you hover down a bit more near the bottom you will see it still happens. I can’t find what exactly the problem is ;-(.

Mine does the same thing so I will work just as hard on this.

After looking into this a little further I have found that the problem is not confined to just having a nested UL on the last list item. However it is related to a nested UL on any list item.

Updated Test Case

Actually Ray that doesn’t fix it. If you hover down a bit more near the bottom you will see it still happens.
Ryan it didn’t actually fix the problem, in my case it just hid the problem. In the example from my first post I don’t see the the problem you describe. Perhaps the top and bottom paddings on my anchor are set up differently from yours. I set up the isolated test case without any negative margins as an attempt to get to the root of the problem.

Ray,

Thanks for getting in contact with me again. I tried replying to your email but got a 554 delivery error.

I can reproduce this issue, and at this stage, I’d suggest that this is an undocumented bug. I’ll try and take a look at this later on tonight, if not, early next week.

James

I have the answer.

The problem is the white space in the HTML. Take this code from my example

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Updated Suckerfish</title>

<style type="text/css">
*{margin:0;padding:0;}/*Resets margins and paddings on the page. Easier to work with*/
#nav
{
  list-style:none;/*No bullets*/
  text-align:center;/*Allows horizontal centtering of the list items*/
  background:blue;/*Visual*/
}
#nav li:hover{background:green;}
#nav li
{
  display:-moz-inline-box;/*FF2 support*/
  display:inline-block;/*Lay it out inline, but retain block qualities. I can still center

it via text-align*/background:red;
  position:relative;/*New stacking context for the submenu which is AP'd*/
}
#nav li a
{
  text-decoration:none;/*Remove the underline*/
  color:#000;/*Color black*/
  padding:5px 10px;/*Visual*/
  line-height:30px;/*Vertical text centering*/
  height:30px;/*Vertical text centering*/
  border:1px solid blue;/*Border to seperate the items*/
}
#nav li li a
{
  background:red;/*Different background to distinguish it is a submenu. Visual*/
}
#nav li li a:hover
{
  background:purple;/*Just show hover state.*/
}
#nav li ul
{
  position:absolute;/*Allow for the dropdown to work and work with it easily*/
  top:100&#37;;/*Move it vertically 100% of the <li>. Stable method*/
  left:0;/*Set a left coordinate instead of relying on auto positioning.*/
  margin-left:-999em;/*Move it off the screen with a huge negative left margin. Very

stable*/
}
#nav li li
{
  float:none;/*Unfloat it so it doesnt go in a line*/
  list-style:none;/*Remove bullets*/
}
#nav li:hover
{
  visibility:visible;/*Fix an IE7 sticky bug*/
}
#nav li:hover ul, #nav li.over ul
{
  margin-left:0;/*Set the left margin to 0 on hover, and the JS hover.*/
}

</style>
<!--[if lt IE 8]>
<style type="text/css">
#nav li
{
  display:inline;/*Setting it up to support inline-block;*/
}
</style>
<![endif]-->
<!--if lt IE 7]>
<script type="text/javascript">
startList = function() {
	if (document.all&&document.getElementById) {
		navRoot = document.getElementById("nav");
		for (i=0; i<navRoot.childNodes.length; i++) {
			node = navRoot.childNodes[i];
			if (node.nodeName=="li") {
				node.onmouseover=function() {
					this.className+=" over";
				}
				node.onmouseout=function() {
					this.className=this.className.replace(" over", "");
				}
			}
		}
	}
}
window.onload=startList;
</script>
<![endif]-->
</head>
<body>
<ul id="nav"><li><a href="#">Home</a></li><li><a href="#">About</a><ul><li><a

href="#">Sublink1</a></li><li><a href="#">Sublink2</a></li>
<li><a href="#">Sublink3</a></li><li><a href="#">Sublink4</a></li></ul></li><li><a

href="#">Contact</a></li><li><a href="#">Articles</a><ul><li><a

href="#">Sublink1</a></li><li><a href="#">Sublink2</a></li><li><a

href="#">Sublink3</a></li><li><a href="#">Sublink4</a></li></ul></li><li><a

href="#">Random</a></li></ul>
</body>
</html>

I removed the white space and look! Nothing is wrong. And inline-block wasn’t the cause. inline-table caused tihs example too.

You have the fix now :). Gosh that was hard lol.

Time to update my example

Edit:

If the posting screws it up, remove ALL the whitespace in the HTML

I have the answer.
The problem is the white space in the HTML.

Ryan, that does not explain why IE8 behaves differently than all other browsers. That is the point of the thread. On top of that, would you really want to set up a complex suckerfish like that. That would be an unorganized nightmare. :slight_smile:

Thanks for looking into this James. I didn’t want to cry wolf and call it a bug too soon but I could not find any reason it should be doing this. It is obviously some sort of white space error when a nested UL is involved.

Sorry about the 554 email error, my ISP has a history of that.

Actually Ray I commented out the nested list and nothing happened. I don’t think it is connected in anyway.

No worries; it’s better for authors who find issues (whether they turn out to be issues or not) let others know about them, and it’s good of you to take the time to create a test case too.

RyanReese is correct when he said this issue relates to whitespace. Moreover, IE8 isn’t ignoring the whitespace text node inserted after the last child element in the DOM, which is generally the accepted behaviour when rendering HTML.

Take the example below:-


    <div id="test"> 
      <span>Test</span>
      <span>Test</span>
    </div>

The DOM spec says that there are five child nodes of #test; /n, <span>, /n, <span> & /n.

It is generally accepted that for HTML when dealing with inline-level elements, the only whitespace node that will be rendered will appear between the two SPANs, and the others will therefore be ignored. However, IE8 is rendering the last whitespace node in that series (which appears after the last SPAN element).

I’ve created a reduced test case which demonstrates this behaviour further.

Although I don’t have any official documentation to hand that describes the expected behaviour, it’s still something I deem important enough to submit a ticket about. Kudos again for spotting it!

EDIT Although my answer goes some way to explaining the issue, it doesn’t explain why :hover is behaving the way it does in your example. I’ll try and take a look at this aspect later

The nested UL has everything to do with it as the problem does not show up in This Example.

Ryan, the problem shows up in your example too when you set hover styles on the parent list items. By simply adding hover styles as shown below to your code the problem shows up.

#nav li a
{
  text-decoration:none;/*Remove the underline*/
  color:#000;/*Color black*/
  padding:5px 10px;/*Visual*/
  background:green;/*Visual*/
  line-height:30px;/*Vertical text centering*/
  height:30px;/*Vertical text centering*/
  border:1px solid blue;/*Border to seperate the items*/
}
[B]#nav li:hover a {
    color:#7FFF00; 
    background:#000;[/B]
} 

As far as a fix is concerned I would much rather set a negative right margin on the last list item to hide the problem rather than than destroying the nested list structure in the html.

Ok, Now I see where the nested UL is not really the culprit (sorry about that Ryan :)) I did agree that it was a white space error in post#8.
Your reduced test case explains things better for me, that’s why I called you in to the crime scene. :wink:

Lol I was like…why so harsh on me? Yea it’s the white space but I think I will ocrrect this by placing comments to connect them…thus keeping sttructure. I have no clue why this happens though.

LoL Ryan, I was not being harsh on you. I just said “everything to do with it”, there is nothing harsh about that.:slight_smile:
I think we can safely say we know what the root of the problem is but the hover issue is still a mystery at this point.

I have no clue why this happens though.
Nor does anyone else, that is why I made the thread.:wink:

Guess I just interpreted it that way, sorry lol.
I don’t try to understand why bugs happen (double float). Buggy behavior with display:inline-block. Guess all versions have something.

Hi James,
I took your reduced test case and set it up as a simple UL and set the pseudo hover on the li rather than the a.

ul#test [B]li:hover[/B]{
background:blue;
color:white;
}

That seems to be what triggers the hover mystery on the inline list items, in relation to the unexpected white-space after last child element.

Do we have two bugs working together here?

In my working example there were no hovers applied to the li, the hovers were set on the anchors.

Here is your test case as a simple UL with inline list items but with the :hover on the li rather than the a. This works in IE7 but shows the unexplained behavior in IE8. Although I did notice that IE7 sets the two visible nodes inside the first two list items and at the end. FF3 is rendering this code as I would expect it to.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test</title>
<style type="text/css">

ul#test{
 border:1px solid black;
 text-align:center;
 background:red;
 font-size:4em;
 margin:0;
 padding:0;
}
ul#test li{
display:inline;
list-style:none;
background:lime;
}
ul#test [COLOR=Blue]li:hover[/COLOR]{
background:blue;
color:white;
}
</style>

</head>
<body>

<h1>Unexpected white-space child text node inserted after last child element</h1>

<ul id="test"> 
    <li>Test</li>
    <li>Test</li>
    <li>Test</li>
</ul>

</body>
</html>

This has gotten even more interesting. :smiley:
Further testing shows even more conditions. The only time a:hover is exempt from this set up is when it is wrapped in a UL.

http://www.css-lab.com/misc-test/ie8-last-child-node.html

The various tests are commented in that link.

Just tried to reply to your email, but got another 554; perhaps you could provide me with another address.

I must admit after some further testing last night, that I’m getting some fairly mixed, and often bizarre results too.

Further testing shows even more conditions

The test case you’ve provided looks promising, and I’ll certainly check it out when I get back from work tonight.

I think you’ve found two bugs here; the issue with the rendering of the last child whitespace text node, which itself is a condition for the strange issue of the first child :hover state being applied to this node. The latter issue is odd since in the DOM, the relationship between the whitespace node and element itself is that of a sibling bond; there is no logical (even in a broken implementation, which this is) explanation as to why this is happening.

I’ve just taken a quick look at your latest post. You specifically mention that the use of the UL element is a condition to trigger this bug - the UL element itself in fact, wouldn’t be. When addressing CSS bugs like these, instead of mentioning certain elements themselves, we need to determine why that particular element is a trigger (i.e specifying the formatting context, etc), as all CSS bugs are element-independant.

I’ll post back when I’ve done some more investigation and analysed your latest test case further.

James

Good lord. Has anyone found a *+html for IE8 yet? Because now that the release candidate is out, MS is quite reluctant to fix it (I think because they can’t guarantee that everyone gets the fix, or because it sounds like bad press when it’s a small bug).

Ryan, in case you were wondering, you can cheat like this most of the time (if you have to, or for testing whitespace errors without losing the ability to read your code):
<ul>
<li><a href=“#”>Item1</a></li
><li><a href=“#”>Item2</a></li’
><li><a href=“#”>Item3</a></li
><li><a href=“#”>Item4</a></li
><li><a href=“#”>Item5</a></li
></ul>

Whitespace within a tag is, as far as I know (oooooh) ignored. It’s space between tags that are nodes (I hope that’s still correct in newer browsers).

I’ve used this for display: inline-block menus, but as Gary has said, you shouldn’t have to mutilate your HTML just to get around whitespace. However so far that’s been most stable for me.

O.o this is interesting, and Stomme didn’t think about that, I’ll go and try and find an IE8 only trigger…