0

I want to decorate a horizontal navigation with a div-element that "slides" below the navigation, depending on which <li> item is currently hovered.

Example:

li:nth-child(1):hover { transform: translateX(100px) };
li:nth-child(2):hover { transform: translateX(200px) };
li:nth-child(3):hover { transform: translateX(300px) };
li:nth-child(4):hover { transform: translateX(400px) };

Challenge: Until now I couldn't figure out which CSS-selector I have to use according to move the div. I have tried all solutions mentioned in this approach, but none of them has worked yet.


Example:

* { list-style-type: none; }

ul { display: flex }

a {
    display: block;
    padding: 1em;
    color: white;
    background-color: orange;
}

.red_circle {
    display: block;
    top: 100px;
  height: 50px;
  width: 50px;
    background-color: red;
}

li:nth-child(1):hover > .red_circle,
li:nth-child(1):hover + .red_circle,
li:nth-child(1):hover .red_circle,
li:nth-child(1):hover ~ .red_circle, {
    transform: translatex(400px);
}
<container>
    <ul>
            <li><a href="#">Test 1</a></li>
            <li><a href="#">Test 2</a></li>
            <li><a href="#">Test 3</a></li>
            <li><a href="#">Test 4</a></li>
    </ul>
    
    <div class="red_circle"</div>
    
</container>
Dave
  • 191
  • 6
  • Use javascript `mouseover` event listener – Ahmad Habib May 18 '21 at 16:09
  • @AhmadHabib: I would prefer pure CSS instead of messing around with JavaScript... :-) – Dave May 18 '21 at 16:10
  • 1
    You can't do exactly what you want with CSS. If you just want the same red div to slide across when any of the li elements is hovered over you could instead get sort of the same result by putting the hover on the ul and using the CSS sibling selector. But do you want different-looking elements to slide across depending on which li element is hovered over? If so you'll need to alter the HTML structure. – A Haworth May 18 '21 at 16:22

1 Answers1

1

There is currently no way to select the parent of an element in CSS.

If there was a way to do it, it would be in the current CSS selectors specs:

Selectors Level 3 Spec

But to achieve this you can modify your html to put your red circle indide your ul tag

* {
  list-style-type: none;
}

ul {
  display: flex
}

a {
  display: block;
  padding: 1em;
  color: white;
  background-color: orange;
}

.red_circle {
  position: absolute;
  display: block;
  top: 100px;
  height: 50px;
  width: 50px;
  background-color: red;
  transition: transform 300ms;
}

li:nth-child(1):hover~.red_circle {
  transform: translatex(400px);
}
<container>
  <ul>
    <li><a href="#">Test 1</a></li>
    <li><a href="#">Test 2</a></li>
    <li><a href="#">Test 3</a></li>
    <li><a href="#">Test 4</a></li>

    <div class="red_circle"> </div>
  </ul>

</container>

EDIT: After reading the HTML 5 standard

Zero or more li and script-supporting elements. So has i said in the comment you could use :beforepseudo element

* {
  list-style-type: none;
}

.list-container {
  padding-left: 40px;
}

ul {
  display: flex;
  padding: 0;
  width: max-content;
}

a {
  display: block;
  padding: 1em;
  color: white;
  background-color: orange;
}

ul:before {
  content: '';
  position: absolute;
  display: block;
  top: 100px;
  height: 50px;
  width: 50px;
  background-color: red;
  transition: transform 1s;
}

ul:hover:before {
  transform: translatex(400px);
}
<container>
  <div class="list-container">
    <ul>
      <li><a href="#">Test 1</a></li>
      <li><a href="#">Test 2</a></li>
      <li><a href="#">Test 3</a></li>
      <li><a href="#">Test 4</a></li>
    </ul>
  </div>

</container>
Charles Lavalard
  • 2,061
  • 6
  • 26
  • 1
    I think an unordered list element should have only li elements as children. – A Haworth May 18 '21 at 16:20
  • 1
    I agree on one part that in unorderd list you should have list item only but this approach does not add the circle in a `li` tag, you can also add it in a `:before` pseudo element – Charles Lavalard May 18 '21 at 16:22
  • Actually this answer is good, but it does not completely solve the initial question. :-) Originally it was aimed to move the ```
    ``` corresponding to which ```
  • ``` item is hovered... Hovering ```
  • ``` no. 1 should move 100 px, hovering no. 2 should move 200 px, and so on...
– Dave May 19 '21 at 01:27
  • Oh my bad, so i think the first answer is the most suitable for your issue :) – Charles Lavalard May 19 '21 at 07:01