Search code examples
htmlcsspseudo-element

How to select an element without selecting its pseudo-elements


I am trying to create a pure CSS-based hamburger menu toggle. This is the HTML, and CSS, that I'm using:

body{
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  gap: 3rem;
}

.menu-toggle-label span,
.menu-toggle-label span::before,
.menu-toggle-label span::after{
  width: 50px;
  height: 6px;
  position: relative;
  background-color: black; 
  display: block;
  transition: all 400ms ease-in-out;
}

.menu-toggle-label span::before,
.menu-toggle-label span::after {
  content: '';
  position: absolute;
}

.menu-toggle-label span::before {
  transform: translateY(-16px);
}

.menu-toggle-label span::after {
  transform: translateY(16px);
}

.menu-toggle:checked~.menu-toggle-label>span {
  transform: translateX(-50px);
  opacity: 0;
}
.menu-toggle:checked~.menu-toggle-label>span::before {
  transform: rotate(45deg) translate(35px, -35px);
}

.menu-toggle:checked~.menu-toggle-label>span::after {
  transform: rotate(-45deg) translate(35px, 35px);
}
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<nav></nav>
<label class="menu-toggle-label" for="menu-toggle">
<span></span>
</label>

When checkbox gets checked, I want to hide the main span element and transform its pseudo-element into a cross.

However, the style below selects its pseudo-elements instead of selecting only the main span element. So all of them get hidden.

.menu-toggle:checked ~ .menu-toggle-label > span {
  transform: translateX(-50px);
  opacity: 0;
}

Solution

  • change the background-color of the main span to match the background of its container when checked.

    .menu-toggle:checked ~ .menu-toggle-label > span {
      background-color: transparent; /* or whatever the container's background color is */
    }
    .menu-toggle:checked ~ .menu-toggle-label > span::before {
      top: 0;
      transform: rotate(45deg);
    }
    .menu-toggle:checked ~ .menu-toggle-label > span::after {
      bottom: 0;
      transform: rotate(-45deg);
    }
    

    Hopefully this should do the trick for you.