使用位置绝对元素防止阴影出血?

Prevent shadow bleeding with position absolute element?

我正在开发一个下拉菜单,但我遇到了一个问题,因为我希望当您将鼠标悬停在它上面时,它会出现一个绝对定位的项目容器,但问题是这个阴影会渗入实际下拉菜单本身。这是一个复制品:

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

.dropdown {
  position: relative;
  width: 200px;
  height: 40px;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #efefef;
}

.items {
  display: none;
  position: absolute;
  overflow: hidden;
  overflow-y: auto;
  width: 100%;
  height: 100px;
  top: 100%;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #f7f7f7;
}

.dropdown:hover .items {
  display: block;
}

.item {
  padding: 5px 10px;
}
<div class="dropdown">
  <div class="items">
    <div class="item">a</div>
    <div class="item">b</div>
    <div class="item">c</div>
    <div class="item">d</div>
  </div>
</div>
<div>hello</div>

如您所见,当您将鼠标悬停在下拉菜单上时,.items 容器的阴影的顶部可见。这是我所指的图片:

最明显的解决方案是让框阴影仅应用于 下拉列表,但问题是由于 items 容器是绝对位置,它没有收到盒子阴影。

有什么解决办法吗?

您可以在 .dropdown 上添加一个 :before 元素,其高度小于他的项目。像这样:

.dropdown:hover:before {
    position: absolute;
    content: "";
    width: 100%;
    height: 98px;
    box-shadow: rgb(0 0 0 / 24%) 0px 6px 8px;
    background: red;
    bottom: -100px;
    z-index: 0;
}

此外,删除 .items 元素的阴影。

我认为 Jackson 使用伪元素的想法是正确的。

尽管我的方法如下:

.dropdown:hover::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #efefef;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

.dropdown {
  position: relative;
  width: 200px;
  height: 40px;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #efefef;
}

.items {
  display: none;
  position: absolute;
  overflow: hidden;
  overflow-y: auto;
  width: 100%;
  height: 100px;
  top: 100%;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #f7f7f7;
}

.dropdown:hover .items {
  display: block;
}
.dropdown:hover::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #efefef;
}

.item {
  padding: 5px 10px;
}
<div class="dropdown">
  <div class="items">
    <div class="item">a</div>
    <div class="item">b</div>
    <div class="item">c</div>
    <div class="item">d</div>
  </div>
</div>
<div>hello</div>

第二种方法可能是在悬停时增加 .dropdown 的高度,并将项目列表设置到与 .dropdown 的高度无关的位置:

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

.dropdown {
  position: relative;
  width: 200px;
  height: 40px;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #efefef;
}

.items {
  display: none;
  position: absolute;
  overflow: hidden;
  overflow-y: auto;
  width: 100%;
  height: 100px;
  top: 40px;
  box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  background-color: #f7f7f7;
}

.dropdown:hover .items {
  display: block;
}
.dropdown:hover {
  height: 140px;
}

.item {
  padding: 5px 10px;
}
<div class="dropdown">
  <div class="items">
    <div class="item">a</div>
    <div class="item">b</div>
    <div class="item">c</div>
    <div class="item">d</div>
  </div>
</div>
<div>hello</div>