Arman Momeni
Arman Momeni

Reputation: 680

Hide pseudo after element when hovering this element

My menu is placed vertically on the left side of the page and between the <li> I have an :after that is a separator. What I want to have is to hide the after element when I hover the element itself (if it's the first element) or the above and the bottom one when it's the middle one and if it's the last child just the :after element of the previous <li>. This may sound confusing but here is my code:

.menu {
  float: left;
  color: white;
}
.menu > ul {
  list-style: none;
  text-align: center;
  padding: 0;
  margin: 0;
}
.menu > ul > li {
  display: block;
  position: relative;
  padding: 60% 5px;
  background-color: #048990;
  cursor: pointer;
  transition: all 0.5s;
}
.menu > ul > li:hover {
  background-color: #444;
  color: white;
}
.menu > ul > li:hover .menu > ul > li::after {
  opacity: 0;
}
.menu > ul > li:active {
  background-color: #444;
}
.menu >ul >li:after {
  content: "";
  background: #FFF;
  position: absolute;
  bottom: 0;
  left: 7%;
  height: 1px;
  width: 86%;
}
.menu > ul > li:last-child:after {
  display: none;
}
<div class="menu">
  <ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
  </ul>
</div>

JSFiddle

Now all I want to do is something like this:

.menu > ul > li:hover + .menu > ul > li::after
{
    opacity: 0;
}

But it's not working. Any help would be appreciated.

Upvotes: 4

Views: 4218

Answers (1)

Harry
Harry

Reputation: 89750

The below selector would not work because the full selector should not be repeated when using + adjacent sibling combinator. This would try to select the li::after that is under .menu > ul which is in-turn the adjacent sibling of the li that is being hovered on.

.menu > ul > li:hover + .menu > ul > li::after {
    opacity: 0;
}

It should instead be written as .menu > ul > li:hover::after if you want to select the ::after of the li that is being hovered on (or) as .menu > ul > li:hover + li::after if you want to select the ::after element of the li that is the adjacent sibling of the li which is being hovered on.


The other problem with the approach that you are using currently is that CSS selectors can be used only to select the children, descendants or the siblings that appear after the current element in DOM. They cannot be used to target the previous siblings and so if the ::after of each element is used to create the separator then the separator on top can never be hidden.

Instead, we can use the ::before elements (on all but the first-child) to create the separator. In this scenario we can use CSS selectors to hide both the the current element's ::before and the next element's ::before on hover.

.menu {
  float: left;
  color: white;
}
.menu > ul {
  list-style: none;
  text-align: center;
  padding: 0;
  margin: 0;
}
.menu > ul > li {
  display: block;
  position: relative;
  padding: 60% 5px;
  background-color: #048990;
  cursor: pointer;
  transition: all 0.5s;
}
.menu > ul > li:hover {
  background-color: #444;
  color: white;
}
.menu > ul > li:hover + li::before,
.menu > ul > li:hover::before {
  opacity: 0;
}
.menu > ul > li:active {
  background-color: #444;
}
.menu >ul >li:not(:first-child)::before {
  content: "";
  background: #FFF;
  position: absolute;
  top: 0;
  left: 7%;
  height: 1px;
  width: 86%;
}
<div class="menu">
  <ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
  </ul>
</div>

Upvotes: 3

Related Questions