1

I have a fiddle here http://jsfiddle.net/13v2fcjf/ It has a basic html document with lists and sublists

<ul>
    <li>Item 1
        <ul>
            <li>Sub Item 1</li>
            <li>Sub Item 2</li>
            <li>Sub Item 3</li>
        </ul>
    </li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4
        <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li>Child 3</li>
        </ul>
    </li>
</ul>

And I'm using the following css -

li:hover {
    background: #f7f7f7;
}

When I hover on an li item with a subitem(s), all the subitems also get highlighted. This is not desirable. I want only the list item on which the user's hovering to be highlighted. How can I achieve this ?

Also, I tried using the :not selector but it doesn't work.

Snork S
  • 134
  • 2
  • 11
  • 1
    the solution depends on the exactly desired behaviour. This is a normal behaviours as such as you don't specify a background-color for nested li's which is then transparent, so you see the background-color of the parent. – Laurent S. Feb 11 '15 at 16:00
  • Why are you not using classes? instead of wrapping things in a or span tags i would define classes for child elements. Have a look to: http://stackoverflow.com/questions/8114657/how-to-style-the-parent-element-when-hovering-a-child-element and http://jsfiddle.net/k3Zdt/8/ – fortiZ Feb 11 '15 at 16:15

4 Answers4

1

I think you just need to set the background on the nested <ul> tag. Something like this:

li:hover > ul {
    background: #fff;
}

Edit: this is assuming you only want the parent <li> highlighted, which as @j08691 points out in the comments, might not be entirely what you're after. If you want each <li> to be highlighted, you might have to modify your HTML slightly to make this easier:

<ul>
    <li><a>Item 1</a>
        <ul>
            <li><a>Sub Item 1</a></li>
            <li><a>Sub Item 2</a></li>
            <li><a>Sub Item 3</a></li>
        </ul>
    </li>
    <li><a>Item 2</a></li>
    <li><a>Item 3</a></li>
    <li><a>Item 4</a>
        <ul>
            <li><a>Child 1</a></li>
            <li><a>Child 2</a></li>
            <li><a>Child 3</a></li>
        </ul>
    </li>
</ul>

By wrapping the items and sub-items in another tag - here I've just used an <a> tag for the sake of argument - you can target that tag to be highlighted on :hover without the nested tags being affected in the same way as in your original code:

a {
    display: inline-block;
    padding: 4px;
}
a:hover {
    background: #f7f7f7;
    cursor: pointer;
}

See http://jsfiddle.net/13v2fcjf/3/

Ian Oxley
  • 10,916
  • 6
  • 42
  • 49
  • This works, but it keeps the parent list item highlighted which I'm not sure the OP wants. – j08691 Feb 11 '15 at 15:58
  • yeah,it keeps the parent list item highlighted. I want only one list item to be highlighted at one time – Snork S Feb 11 '15 at 16:05
0

If Ian's option doesn't work for you, a second opotion is to wrap the <li> contents in a span and apply the hover to that, like this example fiddle:

HTML:

<ul>
    <li><span>Item 1</span>
        <ul>
            <li><span>Sub Item 1</span></li>
            <li><span>Sub Item 2</span></li>
            <li><span>Sub Item 3</span></li>
        </ul>
    </li>
    ....

CSS

li span:hover {
    background: #f7f7f7;
    cursor: pointer;
}

HTH, -Ted

Community
  • 1
  • 1
Ted
  • 14,757
  • 2
  • 41
  • 58
0

This effect is just natural because the sub items are inside of the main items.

There are two options that come to my mind:

1.) Resetting the background color of the sub lists with

li:hover > ul {
  background-color: white;
}

2.) Using the li items as a container:

<li><span class="highlighted">Item</span></li>

.highlighted:hover {
  background-color: red;
}
lupz
  • 3,620
  • 2
  • 27
  • 43
0

This was a challenge, but the following CSS works with your existing markup. It highlights only a hovered li, without highlighting its parent.

The main trick is to have the CSS create new content when hovering over a nested li. You can do this using the :before pseudo element:

li li:hover:before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;
  z-index: -1;
  background: white;
}

(If you're targeting CSS3 browsers only, you can use ::before instead of :before.)

This causes a nested li to cover up its parent li. The negative z-index prevents the background from covering up any text.

Parent li's need relative positioning with a z-index, and nested li's need static positioning for this to work:

li {
  position: relative;
  z-index: 0;
}

li li {
  position: static;
}

The other trick has been mentioned in other posts:

li:hover ul {
  background: white;
}

Full CSS:

li {
  line-height: 1.65em;
  cursor: pointer;
}

li {
  position: relative;
  z-index: 0;
}

li li {
  position: static;
}

li:hover {
  background: #def;
}

li:hover ul {
  background: white;
}

li li:hover:before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;
  z-index: -1;
  background: white;
}

Working fiddle

Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79