Snork S
Snork S

Reputation: 142

CSS List Hover SubItems

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.

Upvotes: 1

Views: 2790

Answers (4)

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

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

Upvotes: 0

Ian Oxley
Ian Oxley

Reputation: 11056

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/

Upvotes: 1

lupz
lupz

Reputation: 3638

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;
}

Upvotes: 0

Ted
Ted

Reputation: 14927

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

Upvotes: 0

Related Questions