当父元素使用 position fixed 时,z-index 属性失效。

3

我正在做一个菜单,需要让它的子菜单有一个较大的z-index,以便在打开模态框时置于其顶部。 它完美地工作,但是当我将菜单设置为'position:fixed'并打开模态框时,子菜单被置于模态框后面。 这是代码,请忽略CSS的最后一部分,那只是动画效果。感谢您的帮助。

const btn = document.querySelector('.btn'),
      overlay = document.querySelector('.menu-overlay'),
      menu = document.querySelector('.responsive'),
      close = document.querySelector('.close'),
      barTop = document.querySelector('#bar-one'),
      barMiddle = document.querySelector('#bar-two'),
      barBottom = document.querySelector('#bar-three');


btn.addEventListener('click', function(){
    overlay.classList.toggle('active');
    menu.classList.toggle('menuActive');
    barTop.classList.toggle('barTop');
    barMiddle.classList.toggle('barMiddle');
    barBottom.classList.toggle('barBottom');
})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.menu-container {
  background: teal;
  padding: 10px 0;
  width: 100%;
  /* here is the issue i´m talking about */
  /* position: fixed; */
}

.menu {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 90%;
  margin: 0 auto;
}

.menu li {
  list-style: none;
  padding: 5px;
}

.menu li a {
  font-family: sans-serif;
  text-decoration: none;
  color: #fff;
}

.btn-container {
  z-index: 10000 !important;
}

.btn {
  text-decoration: none;
  display: flex;
  width: 22px;
  height: 18px;
  margin: 0 auto;
  flex-direction: column;
  justify-content: space-between;
}

.btn span {
  display: block;
  width: 100%;
  height: 2px;
  background: #fff;
  transition: all .3s;
}

.btn #bar-one.barTop {
  transform: translateY(8px) rotate(45deg);
}
.btn #bar-three.barBottom {
  transform: translateY(-8px) rotate(-45deg);
}
.btn #bar-two.barMiddle {
  opacity: 0;
}

.menu-overlay {
  position: fixed;
  width: 100%;
  top: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
  animation: fadeOverlay .3s linear;
  display: none;
  z-index: 99;
}
.menu-overlay.active {
  display: block;
}

@keyframes fadeOverlay {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 100%;
  }
}

.responsive {
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: -100%;
  z-index: 100;
  transition: left .2s ease-in-out;
}

.responsive ul {
  display: flex;
  flex-direction: column;
  background: #000;
  width: 87%;
  height: 100%;
  padding: 20px;
}

.responsive ul li {
  padding: 5px;
}

.responsive ul li a {
  text-decoration: none;
  color: #fff;
}

.responsive.menuActive {
  left: 0;
}

.close {
  text-decoration: none;
  display: block;
  color: #fff;
  width: 10%;
  position: absolute;
  top: 0;
  right: 0;
  font-size: 40px;
  text-align: center;
  margin-top: 5px;
}

.close.closeActive {
  animation: fadeClose .4s linear;
}

@keyframes fadeClose {
  0%, 90% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Menu Celular</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>

  <div class="menu-overlay"></div>
  <div class="menu-container">
    <ul class="menu">
      <li><a href="#">Home</a></li>
      <li class="btn-container">
        <a href="#" class="btn">
          <span id="bar-one"></span>
          <span id="bar-two"></span>
          <span id="bar-three"></span>
        </a>
      </li>
    </ul>
  </div>
  <div class="responsive">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">Exit</a></li>
  </ul>
  </div>



<script src="./js.js" charset="utf-8"></script>
</body>
</html>


我尝试了那篇文章的解决方案,但在这种情况下它并不起作用。我认为这是因为在那篇文章中有两个单独的div,而我正在处理父子关系。 - Santiago
1个回答

2
position:fixed会创建一个堆叠上下文,强制所有元素被绘制在内部。您的问题是现在覆盖层覆盖了菜单容器,包括其所有元素,并且设置内部元素的更高z-index将无效。在您的情况下,您不能再将按钮容器移动到该堆叠上下文之外。
您需要增加容器的z-index。 "最初的回答"

const btn = document.querySelector('.btn'),
      overlay = document.querySelector('.menu-overlay'),
      menu = document.querySelector('.responsive'),
      close = document.querySelector('.close'),
      barTop = document.querySelector('#bar-one'),
      barMiddle = document.querySelector('#bar-two'),
      barBottom = document.querySelector('#bar-three');


btn.addEventListener('click', function(){
    overlay.classList.toggle('active');
    menu.classList.toggle('menuActive');
    barTop.classList.toggle('barTop');
    barMiddle.classList.toggle('barMiddle');
    barBottom.classList.toggle('barBottom');
})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.menu-container {
  background: teal;
  padding: 10px 0;
  width: 100%;
  /* here is the issue i´m talking about */
  position: fixed; 
  z-index:1000;
}

.menu {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 90%;
  margin: 0 auto;
}

.menu li {
  list-style: none;
  padding: 5px;
}

.menu li a {
  font-family: sans-serif;
  text-decoration: none;
  color: #fff;
}

.btn-container {
  z-index: 10000 !important;
}

.btn {
  text-decoration: none;
  display: flex;
  width: 22px;
  height: 18px;
  margin: 0 auto;
  flex-direction: column;
  justify-content: space-between;
}

.btn span {
  display: block;
  width: 100%;
  height: 2px;
  background: #fff;
  transition: all .3s;
}

.btn #bar-one.barTop {
  transform: translateY(8px) rotate(45deg);
}
.btn #bar-three.barBottom {
  transform: translateY(-8px) rotate(-45deg);
}
.btn #bar-two.barMiddle {
  opacity: 0;
}

.menu-overlay {
  position: fixed;
  width: 100%;
  top: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
  animation: fadeOverlay .3s linear;
  display: none;
  z-index: 99;
}
.menu-overlay.active {
  display: block;
}

@keyframes fadeOverlay {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 100%;
  }
}

.responsive {
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: -100%;
  z-index: 100;
  transition: left .2s ease-in-out;
}

.responsive ul {
  display: flex;
  flex-direction: column;
  background: #000;
  width: 87%;
  height: 100%;
  padding: 20px;
}

.responsive ul li {
  padding: 5px;
}

.responsive ul li a {
  text-decoration: none;
  color: #fff;
}

.responsive.menuActive {
  left: 0;
}

.close {
  text-decoration: none;
  display: block;
  color: #fff;
  width: 10%;
  position: absolute;
  top: 0;
  right: 0;
  font-size: 40px;
  text-align: center;
  margin-top: 5px;
}

.close.closeActive {
  animation: fadeClose .4s linear;
}

@keyframes fadeClose {
  0%, 90% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Menu Celular</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>

  <div class="menu-overlay"></div>
  <div class="menu-container">
    <ul class="menu">
      <li><a href="#">Home</a></li>
      <li class="btn-container">
        <a href="#" class="btn">
          <span id="bar-one"></span>
          <span id="bar-two"></span>
          <span id="bar-three"></span>
        </a>
      </li>
    </ul>
  </div>
  <div class="responsive">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">Exit</a></li>
  </ul>
  </div>



<script src="./js.js" charset="utf-8"></script>
</body>
</html>

这样做会使所有容器都在遮罩层之上,这也不是所需的结果。

如果您希望遮罩层的行为与最初相同,您唯一的方法是将其放置在 position:fixed 元素内,并将 responsive 菜单移动到那里,这样您就可以使所有元素再次属于同一堆叠上下文,并且可以根据需要调整 z-index

原始答案: 最初的回答

const btn = document.querySelector('.btn'),
      overlay = document.querySelector('.menu-overlay'),
      menu = document.querySelector('.responsive'),
      close = document.querySelector('.close'),
      barTop = document.querySelector('#bar-one'),
      barMiddle = document.querySelector('#bar-two'),
      barBottom = document.querySelector('#bar-three');


btn.addEventListener('click', function(){
    overlay.classList.toggle('active');
    menu.classList.toggle('menuActive');
    barTop.classList.toggle('barTop');
    barMiddle.classList.toggle('barMiddle');
    barBottom.classList.toggle('barBottom');
})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.menu-container {
  background: teal;
  padding: 10px 0;
  width: 100%;
  /* here is the issue i´m talking about */
  position: fixed; 
}

.menu {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 90%;
  margin: 0 auto;
}

.menu li {
  list-style: none;
  padding: 5px;
}

.menu li a {
  font-family: sans-serif;
  text-decoration: none;
  color: #fff;
}

.btn-container {
  z-index: 10000 !important;
}

.btn {
  text-decoration: none;
  display: flex;
  width: 22px;
  height: 18px;
  margin: 0 auto;
  flex-direction: column;
  justify-content: space-between;
}

.btn span {
  display: block;
  width: 100%;
  height: 2px;
  background: #fff;
  transition: all .3s;
}

.btn #bar-one.barTop {
  transform: translateY(8px) rotate(45deg);
}
.btn #bar-three.barBottom {
  transform: translateY(-8px) rotate(-45deg);
}
.btn #bar-two.barMiddle {
  opacity: 0;
}

.menu-overlay {
  position: fixed;
  width: 100%;
  top: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
  animation: fadeOverlay .3s linear;
  display: none;
  z-index: 99;
}
.menu-overlay.active {
  display: block;
}

@keyframes fadeOverlay {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 100%;
  }
}

.responsive {
  width: 100%;
  height: 100vh;
  position: fixed;
  z-index:100;
  top: 0;
  left: -100%;
  z-index: 99;
  transition: left .2s ease-in-out;
}

.responsive ul {
  display: flex;
  flex-direction: column;
  background: #000;
  width: 87%;
  height: 100%;
  padding: 20px;
}

.responsive ul li {
  padding: 5px;
}

.responsive ul li a {
  text-decoration: none;
  color: #fff;
}

.responsive.menuActive {
  left: 0;
}

.close {
  text-decoration: none;
  display: block;
  color: #fff;
  width: 10%;
  position: absolute;
  top: 0;
  right: 0;
  font-size: 40px;
  text-align: center;
  margin-top: 5px;
}

.close.closeActive {
  animation: fadeClose .4s linear;
}

@keyframes fadeClose {
  0%, 90% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Menu Celular</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>

  <div class="menu-container">
  <div class="menu-overlay"></div>
    <ul class="menu">
      <li><a href="#">Home</a></li>
      <li class="btn-container">
        <a href="#" class="btn">
          <span id="bar-one"></span>
          <span id="bar-two"></span>
          <span id="bar-three"></span>
        </a>
      </li>
    </ul>
  <div class="responsive">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">Exit</a></li>
  </ul>
  </div>
  </div>



<script src="./js.js" charset="utf-8"></script>
</body>
</html>

如果您无法更改HTML,则没有机会获得您想要的内容。


有关堆叠上下文和绘画顺序的更多详细信息,请参阅以下相关问题:

为什么具有z-index的元素永远无法覆盖其子元素?

如何在CSS中对重新定位的div进行z-index?


这对我理解 z-index 的限制很有帮助。 - hajile78
把所有东西放在 div 里面,我就能做到了,谢谢! - Santiago

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接