homepage Welcome to WebmasterWorld Guest from 54.242.18.232
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / CSS
Forum Library, Charter, Moderator: open

CSS Forum

    
:hover - ghosts, gaps and peekaboo in IE7
hmmm.. I smell bug reports!
SuzyUK




msg:3146639
 5:27 pm on Nov 5, 2006 (gmt 0)

there was a thread this week in supporters where someone was reporting seeing ghosts!

more specifically that a DHTML/CSS drop menu was leaving "ghosts" behind after the hover was moved off in IE7.

Yesterday being Saturday was a play day, so I was playing with some of the tried and tested "if only" menus.. Like Eric Meyer's Pure CSS Drop menu and Stu Nicholls' cascade, rather trying to work my own thoughts into the code

I'm not sure that I can report, or even want to to try to, what I found.

But I do like to vocalise.. so here goes,

In the process of trying to make Eric Meyers Pure CSS Demo [meyerweb.com] compatible with IE7, I triggered all of the ghosts, gaps (whitespace on hover) and disappearing content (peekaboo) phenomena on especially the right side menu.

I can't provide sample on specific instances where each occurred as some of them were dependent on where the background color, or borders were :o and I was using background colors to see what was happening.

However as this is meant to be a more general view, report of the findings and I just want to write it here in a very rough form to remind myself and hopefully help some who may come across any or all of the symptoms, feel free to add your findings on the same issues..

(note: these symptoms can also occur in any content div/element with floated content and any :hover transition or italic text so you might like to keep reading it's not just hover menus)

As far as menus go.. one answer seems to be to keep layout off the <li> itself if you require it to have a width add it to the nested link, or the parent ul. In fact in most scenarios I've checked so far it's still desirable to force hasLayout onto the nested anchor, <a>, element, it always was in IE6 too so nothing much has changed, and it's as well to keep using it if it's already in the CSS.

This should be fine in general situations, however technically a <li> should have layout in order to take control of it's nested child <ul>, and what seems to fix a lot of cases is to apply layout to li:hover.

Actually what I had hoped was to be able to suggest that triggering hasLayout on any :hover was a wonder cure, it is wonderful for most general hover transitions e.g. simple in page stuff.. but complex menus are a different story!

If you do use code that applies layout to the <li> element then you need to be aware that the "pseudo" element itself may also need layout, e.g :div:hover {zoom: 1;} and if so it has to be a different property that you use to give the original element its layout, e.g. if your <li> has layout by means of a width you can't also give layout to the li:hover using width.

I also came across an instance where when positioning a 1st level child list to an h3 heading which had a hover trigger on it.. I also had to trigger hasLayout on the h3:hover or the positioning went out the window! I was going to give that example, but having just checked on it, it's now working eeekk.. however I think this is because of some background and bordering coloring I added to it for aesthetics, because lastly

the final thing which can fix or cause hasLayout to do weird things is the presence or lack thereof of a background or border property. So while the number of situations where any/all of these particular phenomena might occur are huge, what I would recommend is to firstly try to apply layout to <whateverelement>:hover, if using position: relative, try to apply layout to the element it's applied to as well, if that doesn't work apply it to its :hover instead.

In short these "new bugs" are not new, it's the new support of the pseudo classes which are exposing more permutations of the same old one..

Anyway forgive me for the muddled post but I'm just going out to the local Fireworks display and I wanted to write what was in my head, feel free to posts samples of code which display what what I'm trying to say, I will try to do the same when I figure out what I inadvertently added which fixed my original broken sample heh..

Suzy

[edited by: SuzyUK at 5:31 pm (utc) on Nov. 5, 2006]

 

KenB




msg:3146688
 6:46 pm on Nov 5, 2006 (gmt 0)

I'd like to follow up on SuzyUK's comments with the IE's hasLayout property and :hover bugs. I was the one who posted the problem in the supporters forum. I did this because I needed to provide a URL to a demonstration of the problem and I didn't think the URL would have been allowed to stay if I had posted my problem in this forum.

Upon Suzy telling me about the hasLayout issue I tried redesigning my menus to rely on DIV tags that were turned on and off (display:block, display:hidden) by the hover pseudo class instead of turning on and off the UL tag I then removed the width reference from all UL and LI tags. Unfortunately I ran into the exact same problem with the ghosts with the DIV tags.

It would appear that the problem doesn't have anything to do with the tags being used to create the menus but with the hasLayout property itself and complex menus.

As Suzy pointed out, with simple menus (e.g. a single level drop down) the hover pseudo class works just fine the problem comes with complex menus that employ several levels of sub-menus.

What is interesting is that if one relies on a JavaScript and the onmouseover/onmouseoff events to turn on and off menus (as must be done for IE5.5 and IE6) IE7 has no problems with ghost menus even when those menus also make use of the hover pseudo class.

Basically until MSFT fixes this IE bug related to the hover pseudo class and hasLayout property one should still rely upon some sort of JavaScript onmouseover/onmouseoff event to control the display of submenus in IE7 as is done for IE5.5 and IE6 even if the hover pseudo class is used for other browsers.

Hopefully the IE development team will fix this problem sooner rather than later as it would really suck to have to wait two years for the next version of IE to fix this problem, which would then force us to wait another four years after that before we could safely abandon the use of JavaScript events to control our DHTML menus.

Being able to abandon the use of JavaScript in dynamic menus and solely rely upon the hover pseudo class would greatly simplify dynamic menus and greatly reduce the amount of code required.

--edit--
Oh if it would be permissible to post the URL of the demonstration page I created and posted in my supporters' forum thread in this thread, I am perfectly fine with it being posted for others to see what we are talking about. I just didn't want to violate any linking policies.

[edited by: KenB at 6:49 pm (utc) on Nov. 5, 2006]

KenB




msg:3146993
 4:34 am on Nov 6, 2006 (gmt 0)

A correction for the post above. I accidentally typed "display:hidden" when I meant to type "display:none". Of course "display:hidden" does nothing as the property "hidden" belongs to the style "visibility."

SuzyUK




msg:3147254
 11:34 am on Nov 6, 2006 (gmt 0)

Ken, sorry no can do with demo link here.. I had your code stripped to a basic sample, which still showed the ghosts so I'll try to post it later. I wanted to test your solution of letting the js control it anyway.

I do now have some demo code below to show some of the problems with :hover, this demo is very plain, and doesn't show the ghosts or gaps i.e. has no nested links in the lists - It's simply to display that before you even get into more complications like layout on other/nested elements there is a need to be aware that position: relative; and hasLayout both have an effect as soon as a hover is invoked, even in the simplest scenario.

Summary:

  • 1. Doesn't Work - when position: relative and hasLayout is on the li, and there is no hasLayout on li:hover
  • 2. Works - when position: relative and hasLayout is on the li, and there is hasLayout on li:hover
  • 2a. Doesn't Work - same as #2, but the hasLayout trigger used on the li:hover was the same as the one on the li - a quirk! it has to be a different trigger or it also works by amending the value of the existing one.
  • 3. Works - when position: relative is on the li, but there is no "haslayout" involved on the li or the li:hover
  • 4 & 5 Works - when position: relative is on li:hover instead of the li, it doesn't matter whether the li or it's hover has layout or not.

So overall, triggering layout on the <element>:hover, should cure most simple cases, just be aware (see2a) it has to be a different layout trigger from any used on <element>

This doesn't demonstrate the gaps or ghosts problem yet, they come once block level links are introduced and I don't think the solution is always as general as above, however I'm trying to see if it can be demo'd.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /></meta>
<title>Untitled</title>
<style type="text/css" media="screen">
body {
font-family: sans-serif;
font-size: 100%;
margin: 0 200px;
padding-bottom: 50px;
}
* {
margin: 0;
padding: 0;
}
h3 {
font-size: 1.1em;
margin: 40px 0 20px 0;
}
p.text {margin-top: 60px;}
ul {width: 150px;}
li {
background: #ddd;
list-style-type: none;
}
li li {
background: #abc;
}
li:hover {
background: #ff0;
}
li ul {
position: absolute;
left: -150px;
top: 0;
}
li:hover ul {left: 150px;}
ul#nav1 li, ul#nav2 li, ul#nav2a li {width: 150px; position: relative;}
ul#nav2 li:hover {zoom: 1;}
ul#nav2 li:hover {width: 150px;}
ul#nav3 li {position: relative;}
ul#nav4 li:hover {position: relative;}
ul#nav5 li {width: 150px;}
ul#nav5 li:hover {position: relative;}
</style>
</head>
<body>
<h3>1. With position: relative and <em>hasLayout</em> on the li<br /> but without: <em>hasLayout</em> on li:hover</h3>
<ul id="nav1">
<li>1. Doesn't work
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
<h3>2. With: position: relative and hasLayout on the li - and "hasLayout" on li:hover</h3>
<ul id="nav2">
<li>2. Works
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
<p class="text"> The next one is the same as #2 above - <strong>but it has the same "hasLayout" trigger</strong> - width: 150px;, on li:hover as is on the li, to show a quirk. It must be either a different trigger or a different value</h3>
<ul id="nav2a">
<li>2a. Doesn't work
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
<h3>3. Nested list with position: relative, but no "haslayout" on the li, and without "hasLayout" on li:hover</h3>
<ul id="nav3">
<li>3. Works
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
<p class="text">The next two both work but are to demonstrate what happens when position relative is moved to the hover. the hasLayout status of the li, no longer affects the hover!
Although the demo code used here flips the nested list from side to side so relies on position relative being used, this part of the demo is the more usual application of hiding until hovered to display just to show that the easiest solution may be to move position: relative; - if you can!</p>
<h3>4. Nested list without "haslayout" on the li, and with position: relative; on li:hover</h3>
<ul id="nav4">
<li>4. Works
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
<h3>5. Nested list with "haslayout" on the li, and position: relative; on li:hover</h3>
<ul id="nav5">
<li>5. Works
<ul>
<li>SubItem 1</li>
<li>SubItem 2</li>
<li>SubItem 3</li>
</ul>
</li>
<li>Item 2</li>
</ul>
</body>
</html>

SuzyUK




msg:3147352
 1:51 pm on Nov 6, 2006 (gmt 0)

Here's KenB's summarised code, thanks for letting us use it, showing the "sticky ghosts"!

Ken I removed everything that was unnecessary to show the bug, even though that included your id's for the javascript, I also shortened a few properties padding, margin etc.. to make code as small as possible less, it's not as small as it could be, but I tried to leave it pretty much as you have it because the way the positioning is dealt with is triggering IE's positioning oddities too, let me know if you would like the (demo's) fix added.

It can be quite hard to trigger the ghosts sometimes, but I've found that if you first navigate the tree through all it's levels then move your mouse off and hover over the header, or first level list they usually appear!

<STYLE type=text/css media=all>
/*** topmenu.css ****/
DIV.TopMenu {
PADDING: 3PX 0 0 0;
MARGIN: 0px;
MAX-HEIGHT: 21px;
BORDER-BOTTOM: #7e2c04 1px solid;
HEIGHT: 21px;
BACKGROUND-COLOR: #d4c38e
}
DIV.TopMenu H3 {
CLEAR: none;
PADDING: 1px 0;
FONT-SIZE: 13px;
MARGIN: 0px;
TEXT-ALIGN: center;
WIDTH: 144px; /* LAYOUT */
}
DIV.TopMenu H3:hover {
BACKGROUND-COLOR: #fff3cc;
}
DIV.TopMenu A:link,
DIV.TopMenu A:visited {
CURSOR: pointer; TEXT-DECORATION: none
}
DIV.TopMenu DIV.MenuItem {
BORDER-TOP: #7e2c04 1px solid;
BORDER-RIGHT: #7e2c04 1px solid;
BORDER-BOTTOM: #ebdbab 1px solid;
BORDER-LEFT: #7e2c04 1px solid;
PADDING: 1px;
MARGIN: 0px 0px 0px 4px;
FONT-WEIGHT: 600;
FONT-SIZE: 12px;
FLOAT: left;
WIDTH: 144px;
CURSOR: default;
COLOR: #7e2c04;
BACKGROUND-COLOR: #ebdbab;
}
DIV.MenuItem UL {
BORDER-TOP: #7e2c04 1px solid;
BORDER-RIGHT: #7e2c04 2px solid;
BORDER-BOTTOM: #7e2c04 2px solid;
BORDER-LEFT: #7e2c04 1px solid;
PADDING: 0;
FONT-WEIGHT: normal;
COLOR: black;
BACKGROUND-COLOR: #d4c38e;
TEXT-ALIGN: left;
WIDTH: 145px; /* LAYOUT */
}
DIV.MenuItem UL.Level2 {
DISPLAY: none;
MARGIN: 1px 0px 0px -2px;
PADDING-TOP: 2px;
POSITION: fixed
}
DIV.MenuItem UL.Level3,
DIV.MenuItem UL.Level4 {
DISPLAY: none;
LEFT: 143px;
MARGIN: -15px 0px 0px 0px;
PADDING-TOP: 2px;
POSITION: absolute
}
DIV.MenuItem UL.Level2 {Z-INDEX: 2}
DIV.MenuItem UL.Level3 {Z-INDEX: 3}
DIV.MenuItem UL.Level4 {Z-INDEX: 4}
DIV.MenuItem UL LI {
LIST-STYLE-TYPE: none;
PADDING: 2px 1px;
MARGIN: 0px 0px 1px 3px;
CURSOR: default;
COLOR: black;
BACKGROUND-COLOR: #ebdbab;
WIDTH: 140px;
}
DIV.MenuItem UL LI:hover {BACKGROUND-COLOR: #fff3cc;}
DIV.MenuItem:hover UL.Level2,
DIV.MenuItem UL.Level2 LI:hover UL.Level3,
DIV.MenuItem UL.Level3 LI:hover UL.Level4
{
DISPLAY: block
}
</STYLE>
<!--[if IE 7]>
<style type="text/css" media="screen">
/*** ie7.css ****/
DIV.TopMenu UL.Level3,
DIV.TopMenu UL.Level4 {
MARGIN-TOP: -4px
}
</style>
<![ENDIF]-->
</HEAD>
<BODY>
<DIV class=TopMenu>
<DIV class=MenuItem>
<H3>Environmental Issues</H3>
<UL class=Level2>
<LI>>> Safety Concerns
<UL class=Level3>
<LI>>> Asbestos
<UL class=Level4>
<LI><A href="#">Asbestos</A></LI>
<LI><A href="#">Asbestos</A></LI>
<LI><A href="#">Asbestos</A></LI>
</UL>
</LI>
<LI>>> Dry-Cleaning Chemicals
<UL class=Level4>
<LI><A href="#">Looking Good..</A></LI>
<LI><A href="#">Are there Realistic Dry-Cleaning Alternatives to Perc?</A></LI>
</UL>
</LI>
<LI><A href="#">Teflon Coverup</A></LI>
<LI><A href="#">PCBs in the food you love</A></LI>
<LI>>> Seafood
<UL class=Level4>
<LI><A href="#">Mercury in Fish vs. the Benefits of Fish Oils</A></LI>
<LI><A href="#">Norwegian Farmed Salmon ..</A></LI>
</UL>
</LI>
</UL>
</LI>
<LI>>> Environmantal Disasters
<UL class=Level3>
<LI><A title="#">From Bhopal to Hazardous Waste Compliance</A> </LI>
</UL>
</LI>
</UL>
</DIV>
</DIV>

SuzyUK




msg:3148676
 2:20 pm on Nov 7, 2006 (gmt 0)

This time I have a demo which demonstrates all of the above symptoms a couple more - and in one of the tests, all in one go! I used the Cascade Demo from cssplay as a base so if you recognise the coloring that's where I acquired it from (thanks Stu) ;)

Situation: Unordered List containing block level anchors, with some toggle of child lists on hover - popular in navigation.

The demo instructions are in the conditional comment, couldn't think how else to do it text style while still keeping it as short as possible for in here. Each section, 6 in all, gives a different scenario and the CSS to demo each case involves uncommenting a small section, 1 or 2 lines, to save you scrolling back and forth.

Summary Points:

  • Starting point is an unordered list (UL) list using position: relative on the li elements so that positioning of the child lists can be established
    ** symptoms = whitespace in lists and child menu positions are incorrect

  • The recommended counter response to using position: relative on an element in IE is to also trigger hasLayout to true on it - but that doesn't help here, it makes things worse!

  • exception to the above is if the layout trigger being used is a width, in which case you can also float the li's which fixes everything. **2nd Solution - width and float

  • the solutions tried in the earlier post - to apply layout to the :hover pseudo class itself don't work here because of the presence of the block anchor

  • if a layout triggering property [webmasterworld.com] (e.g. width, min-height/width) is needed on the li can it be moved to the parent ul or nested <a> instead? - If so, do it, as the anchor usually needs layout anyway and that's the easiest way to avoid the display errors in the first place **best solution - keep layout off the <li> element

  • see demo #6 which shows how wild it can get or if you thought peekaboo was fixed :)

  • can anyone think of a situation where li might have a necessary layout triggering property on it? - I can't seem to get rid of the ghosts if it has to be there

Demo Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>Untitled</title>
<style type="text/css" media="screen">
html, body {margin: 0; border: 0; padding: 0;}
body {padding: 60px;}
#menu a {
display:block;
font-size: 12px;
color:#000;
line-height: 2;
text-decoration:none;
padding: 0 5px;
background:#b2ab9b;
border-width: 0 1px 1px 0;
border-style: solid;
border-color: #fff;
}
#menu, #menu ul {padding:0; margin:0; border: 0; list-style-type: none; width: 180px;}
#menu li {
position:relative;
}
#menu li:hover > a {background:#dfd7ca; color:#c00;}
#menu li ul { position:absolute; top:0; left: 100%; display: none; }
#menu li:hover > ul {display:block; }
</style>
<!--[if IE 7]>
<style type="text/css" media="screen">
/** position relative on the li element so that positioning of the child lists can be established
is the trigger.
symptoms = whitespace in lists and child menu positions are incorrect
**/

/** 1. although recommended behaviour is to also trigger layout on a relatively positioned elements
it's not the best advice in this case. It corrects the nested list positioning and hoverable
area of the anchor but not the whitespace in the list.
uncomment the next line to test that - comment it out again when finished.
**/

/* #menu li { zoom: 1; } */

/** 2. if you then carry on from that point above you might think that all you have to is
correct the whitespace in lists, so you could try and trigger layout on the anchor always
a usual suspect and indeed things will look better but that's where you get the bottom (smaller)
gaps and sticky ghosts on hover only
uncomment the next 2 lines to test that - comment it out again when finished.
*/

/*
#menu li { zoom: 1; }
#menu a { min-height: 1%; }
*/

/** 3. the above scenario can be corrected very easily _if_ the_layout_trigger_is_a_width_
you can simply correct the whitespace problem with a float and this fix also happens
to fix the hoverable area of the anchor.
thats fix two! (I know they're in the wrong order :) - only if a width is able to be used
uncomment the next line to test that - comment it out again when finished.
**/

/* #menu li { width: 180px; float: left;} */


/** 4. back at square one - if we forget about the li elements for a minute and go hover over the
links you will see that the whole link block is not active, and if you set layout on
the anchor (the IE6 cure) and take a look it's fixed everything!
that is fix one! - no layout involved on li put it on the block anchor instead
uncomment the next line to test that - comment it out again when finished.
**/

/* #menu a { min-height: 1%; } */

/** 5. ref: the simpler case fix of trying to set layout on the :hover as well as the li
(using a different property) -
this doesn't do anything different than if it's on the li itself
uncomment the next 2 lines to test that - comment it out again when finished.
**/

/*
#menu li { min-height: 1%;}
#menu li:hover { zoom: 1;}
*/

/** 6. When there's layout on just the li:hover and the anchor it produces even wilder results
- peekaboo, gaps - both whitespace in lists and the smaller bottom gap
uncomment the next 2 lines to test that - comment it out again when finished.
**/

/*
#menu li:hover { zoom: 1;}
#menu a { min-height: 1%; }
*/
</style>
<![endif]-->
<body>
<ul id="menu">
<li><a href="#">Top Level 1</a></li>
<li><a href="#">Top Level 2 &#187;</a>
<ul>
<li><a href="#">Sub Level 1a</a></li>
<li><a href="#">Sub Level 1b &#187;</a>
<ul>
<li><a href="#">Sub Level 2a</a></li>
<li><a href="#">Sub Level 2b</a></li>
<li><a href="#">Sub Level 2c</a></li>
</ul>
</li>
<li><a href="#">Sub Level 1c</a></li>
</ul>
</li>
<li><a href="#">Top Level 3</a></li>
</ul>
</body>
</html>

Suzy

[edited by: SuzyUK at 2:24 pm (utc) on Nov. 7, 2006]

KenB




msg:3149441
 11:00 pm on Nov 7, 2006 (gmt 0)

What I found was that applying width instructions to the LI tag can be very desirable and maybe even necessary. For instance I noticed that with some browsers (e.g. IE5.5) if the width is not defined the LI "box" collapses to the width of the width of the text the LI tag encapsulates. This can be a very undesirable side effect.

SuzyUK




msg:3582979
 6:55 pm on Feb 23, 2008 (gmt 0)

long time update.. but it's coming

I have just about narrowed all Sticky, Ghostly, non-display possibilities with both horizontal and vertical versions of drop menus

Important Update
** the main change I would make to any drop menu which displays IE weirdness, ghosts, sticky drops, whitespace, is DO NOT use the display: none/block method of toggling the display

use visibility or negative absolute co-ordinate triggers, the difference is subtle and while I've been trying to prepare a solid base for building from, obviously not all situations can be covered in test.

I am testing and *think* I have a barebones menu which allows us to "have layout" anywhere on <li> or <a>, allows various line-height combinations, without restriction *if* a couple of little (common) nuances are observed

Suckerfish menus in IE7 (without the script)
SF do use the negative absolute method of positioning, but they also have a hasLayout triggering property on the hidden lists (a width) - which triggers another IE problem - they are missing an
li:hover rule (which I would always recommend adding anyway **) - now they also don't use position relative and rely on "auto" value co-ordinates so to help IE further I suggest adding

#nav li:hover {position: relative; z-index: 1;}

** IE's display problems are closely linked to :hover and display, and even previously, before extended :hover support, you could not easily apply an a:hover span {} rule combined with a display change, before declaring an a:hover rule without some kind of mishap occuring ;)

IE just seemed to have difficulty extending the rule to children if a hover rule didn't precede an extended one - :hover support on more elements than before is exposing the same IE logic is still there :o

anyone have a "sticky" problem I can test this theory with?

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / CSS
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved