Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS - on hover affect full width of element, without removing padding

Tags:

html

css

I have a series of nested ul and li elements, to create a sidebar nav system. When the user hovers over one of the li elements I want the entire width of the background to change (shown right), not just the inside of the container (shown left).

Different hover styles

The problem I'm having is that in order to make the entire width change, I need to remove the ul padding-left which then removes the indentation and 'nested' look of the list elements.

An example below shows the behaviour currently present, where the background-color does not change for the entire width. Preferably I wouldn't have to manually add in indentation for each element, as the nested padding works quite nicely as is, but am open to suggestions :D

* {
  box-sizing: border-box;
}

nav {
  width: 100px;
  background-color: lightgrey;
}

li {
  list-style: none;
}

ul {
  padding-left: 10px;
}

a {
  color: black;
  text-decoration: none;
  padding: 5px;
  display: inline-block;
  width: 100%;
}

a:hover {
  background-color: grey;
  color: white;
}
<nav>
  <ul>
    <li><a href='#'>Home</a></li>
    <li><a href='#'>Work</a></li>
    <ul>
      <li><a href='#'>Piece 1</a></li>
      <li><a href='#'>Piece 2</a></li>
    </ul>
    <li><a href='#'>Contact</a></li>
  </ul>
 </nav>

My questions:

  1. How can I make the background of the entire width of the li update on hover, without removing the indentation for the nested list items.

  2. Why are the width: 100% li elements not overflowing outside the nav bar? Since I thought width: 100% meant their width was the same as their parent's widths, which surely as they are indented would mean they would extend beyond.

Thanks!

Post Answer Edit The accepted answer is definitely good, but the solution i ended up with was dynamically generating the navbar elements with JavaScript according to an object.

like image 931
dantechguy Avatar asked Sep 01 '25 04:09

dantechguy


1 Answers

This solution works for any number of nested levels.

The trick is using CSS counter to pad levels.

* {
  box-sizing: border-box;
}

nav {
  display: inline-block;
  background-color: lightgrey;
}

ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}


li {
  counter-increment: section;
  counter-reset: section;
}

a:before {
  content: counters(section, '');
  opacity: 0
}

a {
  color: black;
  text-decoration: none;
  padding: 5px;
  display: block;
}

a:hover {
  background-color: grey;
  color: white;
}
<nav>
  <ul>
    <li><a href='#'>Home</a></li>
    <li><a href='#'>Work</a>
      <ul>
        <li><a href='#'>Piece 1</a></li>
        <li><a href='#'>Piece 2</a>
          <ul>
            <li><a href='#'>Piece 2.1</a></li>
            <li><a href='#'>Piece 2.2</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href='#'>Contact</a></li>
  </ul>
</nav>
like image 100
Kosh Avatar answered Sep 02 '25 18:09

Kosh