skip to Main Content

Is there a way to have display none on divs levelOne to levelFour when I hover one levelFive by just using CSS?
My Html Structure is below:

<div class="dropDownMenus levelOne"></div>
<div class="dropDownMenus levelTwo"></div>
<div class="dropDownMenus levelThree"></div>
<div class="dropDownMenus levelFour"></div>
<div class="dropDownMenus levelFive"></div>

My CSS looks like this:

.levelFour {
  &:has(+ .levelFive) {
    display: none;
  }
}

This effectively hides the levelFour div right above levelFive, but is there a way to do so on hover.

4

Answers


  1. Unfortunately, CSS alone does not provide a way to select and style preceding siblings. However, you can achieve the desired effect using a combination of JavaScript and CSS. Here’s a possible solution:

    HTML:

    <div class="dropDownMenus levelOne"></div>
    <div class="dropDownMenus levelTwo"></div>
    <div class="dropDownMenus levelThree"></div>
    <div class="dropDownMenus levelFour"></div>
    <div class="dropDownMenus levelFive" onmouseover="hidePrecedingSiblings(this)"></div>
    

    CSS:

    .dropDownMenus {
    /* Your styles for dropDownMenus class here */
    }
    

    JavaScript:

    function hidePrecedingSiblings(element) {
    const siblings = element.previousElementSibling;
    while (siblings) {
    if (siblings.classList.contains('dropDownMenus')) {
      siblings.style.display = 'none';
    }
    siblings = siblings.previousElementSibling;
    }}
    

    With this solution, when you hover over the levelFive element, the JavaScript function hidePrecedingSiblings() will be triggered, which will hide all preceding siblings with the class dropDownMenus. This gives you the desired effect of hiding the levelFour, levelThree, levelTwo, and levelOne divs when you hover over the levelFive div.

    Remember to adjust the CSS styles and class names according to your specific design requirements.

    Login or Signup to reply.
  2. This won’t work without the wrapper, but with the wrapper and the reasonable modern :has selector, you could easily use something like this:

    main:has(.levelFive:hover) *:not(.levelFive)
    

    Snippet:

    main .dropDownMenus {
      width: 100%;
      font-size: 3em;
      padding: .5em;
      background: red; 
      margin-bottom: 2px;
      color: white;
      transition: all .4s;
    }
    main .levelFive {
      cursor: pointer;
    }
    main:has(.levelFive:hover) *:not(.levelFive){
      opacity: .5;
    }
    <main>
      <div class="dropDownMenus levelFive">5</div>
      <div class="dropDownMenus levelOne">1</div>
      <div class="dropDownMenus levelTwo">2</div>
      <div class="dropDownMenus levelThree">3</div>
      <div class="dropDownMenus levelFour">4</div>
    </main>
    Login or Signup to reply.
  3. This matches any elements having in the next siblings any element with .levelFour class:

    .dropDownMenus:has(~.levelFive:hover){
      display:none;
    }
    
    .dropDownMenus{
      background: lightgray;
      width: 100px;
      padding: 3px 10px;
      cursor:pointer;
      margin: 2px;
    }
    .dropDownMenus:hover{
      background: #bbb;
    }
    <div class="dropDownMenus levelOne">1</div>
    <div class="dropDownMenus levelTwo">2</div>
    <div class="dropDownMenus levelThree">3</div>
    <div class="dropDownMenus levelFour">4</div>
    <div class="dropDownMenus levelFive">5</div>
    Login or Signup to reply.
  4. unfortunately with only css you will not be able to do it as :has is not yet support by all browser

    At the date of this message (07/2023) the near bad solution in pure css can be to hide with a blank square other top value

    .wrapper .levelFive:hover {
      position: absolute;
      top: 0;
      height: 120%;
      width: 100%;
      background: white;
      z-index: 9;
    }
    
    .wrapper {
      position: relative;
      width: fit-content;
    }
    <div class="wrapper">
      <div class="dropDownMenus levelOne">one</div>
      <div class="dropDownMenus levelTwo">two</div>
      <div class="dropDownMenus levelThree">three</div>
      <div class="dropDownMenus levelFour">four</div>
      <div class="dropDownMenus levelFive">five</div>
    </div>

    or if you want to guard 5 item at same place

    .wrapper .levelFive:hover {
      position:absolute;
      top: 0;
      height: 125%;
      width: 100%;
      background: white;
      display: flex;
      align-items: end;
    }
    
    .wrapper {
      position: relative;
      width: fit-content;
    }
    <div class="wrapper">
      <div class="dropDownMenus levelOne">one</div>
      <div class="dropDownMenus levelTwo">two</div>
      <div class="dropDownMenus levelThree">three</div>
      <div class="dropDownMenus levelFour">four</div>
      <div class="dropDownMenus levelFive">five</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search