CSS带边框的箭头添加盒子阴影

15

我有一个带箭头和箭头边框的提示框,但是我需要箭头也能够获得提示框的盒子阴影效果,我该如何做到这一点?

我需要一个跨浏览器的解决方案。我不能使用CSS filter。

.tooltip {
  position: absolute;
}

.arrow_box {
  position: relative;
  background-color: #fff;
  border: 1px solid lightgrey;
  border-radius: 2px;
  padding: 12px;
  box-shadow: 1px 1.5px 4px 0px rgba(170, 174, 181, 0.45);
  -webkit-transform: translateX(6px);
          transform: translateX(6px);
}

.arrow_box:after, .arrow_box:before {
  right: 100%;
  top: 50%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}

.arrow_box:after {
  border-color: rgba(255, 255, 255, 0);
  border-right-color: #fff;
  border-width: 6px;
  margin-top: -6px;
}

.arrow_box:before {
  border-color: rgba(211, 211, 211, 0);
  border-right-color: #d3d3d3;
  border-width: 7px;
  margin-top: -7px;
}
<div class="tooltip">
 <div class="arrow_box">
  <p>tooltip</p>
 </div>
</div>


你尝试过这个解决方案吗:https://codepen.io/ryanmcnz/pen/JDLhu - besciualex
不要用边框(三角形)制作箭头。只需制作一个普通的矩形,旋转并应用阴影,并保持其 z-index 较低。 - Sahil Dhir
请问您能举个例子并给出一个答案吗? - ng2user
3个回答

17
您的问题的解决方案可以像这里发布的那个一样得到解决:https://codepen.io/ryanmcnz/pen/JDLhu 基本上: 1. 创建一个正方形( ::after),旋转它并添加框阴影。 2. 创建第二个正方形(::before),它重叠在球内部投射的框阴影上方。

body {
  background-color: #fff;
}

.triangle {
  position: relative;
  margin: 3em;
  padding: 1em;
  box-sizing: border-box;
  background: #fff;
  border: 1px solid #fafafa;
  box-shadow: 0px 3px 3px 0 rgba(0, 0, 0, 0.4);
}
.triangle::after{
    z-index: -10;
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    margin-left: 0;
    bottom: 0;
    top: calc(50% - 5px);
    left:0;
    box-sizing: border-box;
    
    border: 5px solid #fff;
    border-color: transparent transparent #fff #fff;
    
    transform-origin: 0 0;
    transform: rotate(45deg);
    
    box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.4);
  }
.triangle::before{
    z-index: 10;
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    margin-left: 0;
    bottom: 0;
    top: calc(50% - 5px);
    left:0;
    box-sizing: border-box;
    
    border: 5px solid black;
    border-color: transparent transparent #fff #fff;
    
    transform-origin: 0 0;
    transform: rotate(45deg);
  }
<div class="triangle">This is a CSS3 triangle with a proper box-shadow!</div>


我看不到箭头的边框颜色。你能否请参考我的示例并进行修改? - ng2user
@ng2user 请看一下。你也可以在边框属性内声明边框颜色。例如:"border: 1px solid #fff;"。另外,如果你正在使用Chrome进行开发,请按F12并检查元素,并实时操作对象的属性。 - besciualex
@ng2user 现在好了吗?如果是的话,请花些时间理解它。这将比简单的复制粘贴有更大的帮助。另外,请不要忘记点赞。我会非常感激的。 - besciualex
1
这在纯白背景下看起来很不错,就像代码片段中一样,但是当您在工具提示下方有文本或其他元素时,负 z-index 会使箭头出现在它们下面。实际上,如果您要在 ::after 上放置负 z-index,则根本不需要 ::before 元素,这正是首先隐藏内部阴影的方法。 - AsGoodAsItGets
1
@besciualex 我最终采用了这个解决方案,它需要一个额外的元素来实现箭头,而且不依赖于 z-index: https://codepen.io/weaintplastic/pen/YWOQXB - AsGoodAsItGets
显示剩余2条评论

7

我前几天偶然发现了这个,想着我会把它留在这里。我的解决方案只涉及一个元素,仅使用伪元素:before,并利用clip-path

:root {
  --shadowSize: 20px;
  --shadowColor: #f00;
}

.box {
  position: relative;
  width: 300px;
  padding: 20px;
  box-shadow: 0 0 var(--shadowSize) var(--shadowColor);
  background-color: #fff;
  border-radius: 4px;
}

.box:before {
  content: "";
  position: absolute;
  top: 50%;
  right: 0;
  width: 30px;
  height: 30px;
  background-color: #fff;
  box-shadow: 0 0 var(--shadowSize) var(--shadowColor);
  transform: translate(50%, -50%) rotate(45deg);
  clip-path: polygon(
    calc(var(--shadowSize) * -1) calc(var(--shadowSize) * -1), 
    calc(100% + var(--shadowSize)) calc(var(--shadowSize) * -1), 
    calc(100% + var(--shadowSize)) calc(100% + var(--shadowSize))
  );
}
<div class="box">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Officia excepturi et unde soluta accusamus dolorum. Architecto, a laborum. Unde impedit aliquam voluptatibus sed dignissimos mollitia nihil consectetur dolores accusamus recusandae?</div>

如果您想将箭头放在盒子的不同位置,需要调整:before元素的clip-path 或旋转。如果您想使用box-shadow偏移,CSS也需要进行调整,因为它目前只计算了其实际大小。
SCSS示例:https://codepen.io/MyXoToD/pen/gOMvYOx

你能否制作一个箭头在左侧的Codepen版本?我无法弄清楚如何修复剪辑路径。 - Garconis
1
@Garconis 我调整了链接的CodePen并添加了一个.box--left修饰符。只需旋转伪元素前面的内容,你就可以完成了。你可能想要在四周包裹一些padding来将箭头包含在与盒子本身相同的框内。 - MyXoToD

1
一个快速简单的解决方案是从.arrow_box中删除box-shadow:样式,并在您的CSS文件中单独添加以下内容:
:host{
    filter: drop-shadow(1px 1.5px 4px 0px rgba(170, 174, 181, 0.45));
} 

这会在整个元素上添加一个阴影。


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