修复带有重叠下拉菜单的 z-index

Fix z-index with overlapping dropdowns

我在使用 z-index 的项目中遇到问题。

我有几个组件,它们都有一个下拉菜单。我遇到的问题是第一个组件的下拉菜单位于第二个组件的下拉按钮下方,这使得内容部分隐藏。

我基本上需要第一个下拉菜单具有最高的 z-index。但由于我对它们进行了相同的样式设置,因此它们都具有相同的 z-index。

我想在没有 JavaScript 的情况下解决这个问题,我必须动态更改 z-index 或使用附加到代码片段的 flexbox 的解决方案。

const dropdowns = document.querySelectorAll('.app-item-dropdown');

dropdowns.forEach((item) => {
  item.querySelector('button').addEventListener('click', function() {
    this.nextElementSibling.parentNode.classList.toggle('expanded')
  })
})
:root {
  --z1: 1;
  --z2: 2;
  --z3: 3;
  --z4: 4;
  --z5: 5;
}

html {
  box-sizing: border-box; 
}
*, *:after, *:before {
  box-sizing: inherit;
}

body {
  background: lightgrey;
  text-align: center;
}

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

.container {
  max-width: 960px; margin: 0 auto; border: 1px solid red;
  padding: 24px;
}

.solution {
  display: flex;
  flex-direction: column-reverse;
}

.app-item {
  border: 1px solid yellow;
  min-height: 150px;
  background: grey;
  position: relative;
  margin: 24px;
}

.app-item-dropdown {
  
  position: absolute;
  width: 272px;
  top: 16px;
  right: 16px;
  background: white;
  z-index: var(--z2);
}

.app-item-dropdown ul {
  display: none;
  position:relative;
  z-index: var(--z4);
}

.app-item-dropdown ul li {
  padding: 4px 8px;
}

.app-item-dropdown.expanded ul{
  display: block;
}

.lightblue {
  background: lightblue;
}

.lightsalmon {
  background: lightsalmon; 
}
<div id="wrapper" class="container problem">
  <div class="app-item">
    <h2>1</h2>
    <div class="app-item-dropdown">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  
  <div class="app-item">
    <h2>2</h2>
    <div class="app-item-dropdown lightblue">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  <div class="app-item">
    <h2>3</h2>
    <div class="app-item-dropdown lightsalmon">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
</div>


<hr>
<h1>Solution</h1>
<h2>With <code>flex-direction: column-reverse</code> </h2>


<div id="wrapper2" class="container solution">
  <div class="app-item">
    <h2>1</h2>
    <div class="app-item-dropdown">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  
  <div class="app-item">
    <h2>2</h2>
    <div class="app-item-dropdown lightblue">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  <div class="app-item">
    <h2>3</h2>
    <div class="app-item-dropdown lightsalmon">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
</div>

将点击添加的 class 的 z-index 设置为高于现有元素的 z-index。

const dropdowns = document.querySelectorAll('.app-item-dropdown');

dropdowns.forEach((item) => {
  item.querySelector('button').addEventListener('click', function() {
    this.nextElementSibling.parentNode.classList.toggle('expanded')
  })
})
:root {
  --z1: 1;
  --z2: 2;
  --z3: 3;
  --z4: 4;
  --z5: 5;
}

html {
  box-sizing: border-box; 
}
*, *:after, *:before {
  box-sizing: inherit;
}

body {
  background: lightgrey;
  text-align: center;
}

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

.container {
  max-width: 960px; margin: 0 auto; border: 1px solid red;
  padding: 24px;
}

.solution {
  display: flex;
  flex-direction: column-reverse;
}

.app-item {
  border: 1px solid yellow;
  min-height: 150px;
  background: grey;
  position: relative;
  margin: 24px;
}

.app-item-dropdown {
  
  position: absolute;
  width: 272px;
  top: 16px;
  right: 16px;
  background: white;
  z-index: var(--z2);
}

.app-item-dropdown ul {
  display: none;
  position:relative;
  z-index: var(--z4);
}

.app-item-dropdown ul li {
  padding: 4px 8px;
}

.app-item-dropdown.expanded ul{
  display: block;
}

.lightblue {
  background: lightblue;
}

.lightsalmon {
  background: lightsalmon; 
}

.expanded {
    z-index: 5;
}
<div id="wrapper" class="container problem">
  <div class="app-item">
    <h2>1</h2>
    <div class="app-item-dropdown">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  
  <div class="app-item">
    <h2>2</h2>
    <div class="app-item-dropdown lightblue">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  <div class="app-item">
    <h2>3</h2>
    <div class="app-item-dropdown lightsalmon">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
</div>


<hr>
<h1>Solution</h1>
<h2>With <code>flex-direction: column-reverse</code> </h2>


<div id="wrapper2" class="container solution">
  <div class="app-item">
    <h2>1</h2>
    <div class="app-item-dropdown">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  
  <div class="app-item">
    <h2>2</h2>
    <div class="app-item-dropdown lightblue">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
  <div class="app-item">
    <h2>3</h2>
    <div class="app-item-dropdown lightsalmon">
      <button>click</button>
      <div class="box">
        <ul>
          <li>hello</li>
          <li>hello</li>
          <li>hellohello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hello</li>
          <li>hehellohellollo</li>
          <li>hello</li>
          <li>helhellolo</li>
          <li>hello</li>
        </ul>
      </div>
    </div>
  </div>
</div>