首页 > 解决方案 > 是否可以在另一个 z 索引元素中独立设置 z 索引?

问题描述

我在底部有一些带有小菜单的图像。它们是绝对定位的,因此它们可以相互重叠。我正在使用 z-index (由一些 javascript 代码操作)来确定用户首先显示哪个图像在第二个之上。

但是,我需要将菜单显示在前台,无论它们位于哪个 z 索引元素中。

简化的代码结构:

.parent {
  width: 600px;
  height: 600px;
  position: relative;
}

#child1 {
  position: absolute;
  z-index: 1;
}

#child2 {
  position: absolute;
  z-index: 2;
}

.menu {
  z-index: 9999;
}
<div class="parent">
  <div id="child1">
    <img src="source" alt="img" />
    <div class="menu"></div>
  </div>


  <div id="child2">
    <img src="source" alt="img" />
    <div class="menu"></div>
  </div>
</div>

当我将菜单元素的 z-index 设置得很高时,它仍然显示在 child2 图像后面。我使用这种 html 结构的原因是每个子元素都包装在可以拖放的可移动组件中。

关于如何实现这一目标的任何想法?

// 编辑

我正在使用 VueJS 和 Moveable组件,它们是使用循环返回的。

Moveable 组件具有基于depth变量的 zIndex,因此它具有显示在其他图像之上的能力。我想要做的是让菜单 div 具有尽可能高的 z-index,这样一旦显示(因为它默认隐藏 - 单击图像激活菜单),它就会显示在所有图像的前景中。

.menu {
    min-width: 170px;
    position: absolute;
    justify-content: center;
    background: #FFF;
    border: 1px solid #dedede;
    border-radius: 6px;
    bottom: -70px;
    left: 0;
    right: 0;
    z-index: 9999;
    padding: 0.625rem 0.875rem;
    box-shadow: 0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12);
    display: none;
}
<Moveable
    v-bind="moveable"
    class="moveable target"
    :style="`width:${image.width}px; height:${image.height}px; zIndex: ${image.depth}`"
    @click.native="handleClick"
    @drag="(transforms) => { handleDrag(transforms, image) }"
    @resize="(transforms) => { handleResize(transforms, image) }"
    @scale="(transforms) => { handleScale(transforms, image) }"
    @scaleEnd="(transforms) => { handleScaleEnd(transforms, image) }"
    @resizeEnd="(transforms) => { handleResizeEnd(transforms, image) }"
    @rotate="handleRotate"
    @warp="handleWarp"
    ref="moveable"
  >
    <img
      :src="image.src"
    >
    <div v-if="guideVisible" class="menu">
      <v-tooltip bottom>
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            elevation="3"
            class="menu-button"
            @click="handleFlipToFront"
            v-bind="attrs"
            v-on="on"
            icon
          >
            <v-icon>{{ flipFrontIcon }}</v-icon>
          </v-btn>

        </template>
        <span>Bring to front</span>
      </v-tooltip>
    </div>
  </Moveable>

标签: htmlcss

解决方案


查看 w3 中 z-index 的定义:https ://www.w3.org/TR/CSS2/visuren.html#z-index

渲染树被绘制到画布上的顺序是根据堆叠上下文来描述的。堆叠上下文可以包含更多的堆叠上下文。从其父堆栈上下文的角度来看,堆栈上下文是原子的;其他堆叠上下文中的盒子可能不会出现在它的任何盒子之间。

每当你给一个元素一个 z-index 时,它就会被视为拥有自己的 z-indexes 的容器。这意味着只要 child1 具有 z-index,child1 内的所有内容(在您的案例菜单中)只能影响是在 child1 内的任何其他视图之上还是之下。


在您的情况下解决此问题的一种方法是找到一种方法使其在没有子级 z-index 的情况下工作,这样您的菜单仍然可以使用 z-index 来渲染所有内容。一种方法是仅使用它在树中定义的顺序。

同样来自 w3:

在堆叠上下文中具有相同堆叠级别的框根据文档树顺序从后到前堆叠。

而且由于您使用的是 Vue,因此只需将焦点项目移动到列表的末尾并让 Vue 进行重新渲染。


推荐阅读