带箭头的气泡 [英] Speech bubble with arrow

查看:29
本文介绍了带箭头的气泡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目需要插入气泡/消息框.我想要达到的一般形状是这样的:

.bubble {高度:100px;宽度:200px;边框:3px纯灰色;背景:浅灰色;位置:相对;游标:指针;}.三角形 {宽度:0;边框顶部:20px纯黑色;border-left:20px 实心透明;border-right: 20px 实心透明;游标:指针;}

语音气泡

<div class="三角形">

这目前没有通过命中测试,因为透明边框也是可点击的.

目标

  • 点击框(可点击/可悬停区域)需要贴在形状的边界上(这里的透明边框也是可悬停的,使其无效).

  • 我需要在各种内容(图像、渐变、文本...)上显示形状,

问题

我在操作这个形状时遇到的主要问题是:

  • 能够根据其所指元素的位置(上/左/右/下侧)移动对话气泡周围的三角形
  • 在需要强调时在其周围添加边框或框阴影

有没有办法解决这些问题?

解决方案

为了实现这一点,您应该考虑更改您的标记以使您的 html 更有效率.这可以使用伪元素来实现.我将单独解决每一点,并在我的答案末尾将它们放在一起.

首先,

使用伪元素避免多余的元素

您可以使用伪元素删除额外的 .triangle div.这不仅减少了您的 div 数量,还有助于定位,因为您可以使用 top: left: right:bottom: css 属性,以便根据您的主要元素进行定位.这可以在下面看到:

.oneAndOnlyDiv {高度:100px;宽度:200px;边框:3px纯灰色;背景:浅灰色;位置:相对;}.oneAndOnlyDiv:before {内容: "";位置:绝对;顶部:100%;左:20px;宽度:0;边框顶部:20px纯黑色;border-left:20px 实心透明;border-right: 20px 实心透明;}

主div


命中测试

为了创建您的命中测试",您可能希望使用旋转元素而不是边框​​.

类似于:

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;}div:之前{内容: "";位置:绝对;顶部:100%;左:20px;高度:20px;宽度:20px;背景:黑色;变换:旋转(45度);变换原点:右上角;}

唯一元素

或使用倾斜的伪元素:

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;}div:之前{内容: "";位置:绝对;顶部:90%;左:20px;高度:30%;宽度:20px;背景:黑色;变换:倾斜(-45度);变换原点:左下角;z-索引:-1;}

唯一元素

仅当方形或主要元素悬停时才会显示指针.但是等一下,这搞乱了定位?你怎么处理?

对此有一些解决方案.其中之一是使用 calc CSS 属性.

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;}div:之前{内容: "";位置:绝对;顶部:-webkit-calc(100% - 10px);/*可能需要旧浏览器支持的前缀*/顶部:计算(100% - 10px);/*IE.高度的一半*/左:20px;高度:20px;宽度:20px;背景:灰色;变换:旋转(45度);}

唯一元素

添加边框

您现在可以很容易地添加边框,只需在主元素中添加边框声明,并设置伪代码的border-bottomborder-right继承

的元素

边框

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;边框:3px 双黑;}div:之前{内容: "";位置:绝对;顶部:-webkit-calc(100% - 10px);/*可能需要旧浏览器支持的前缀*/顶部:计算(100% - 10px);/*IE.高度的一半*/左:20px;高度:20px;宽度:20px;背景:灰色;变换:旋转(45度);边框底部:继承;边界权:继承;框阴影:继承;}

唯一元素

盒子阴影:

为了有一个框阴影,我使用了 :after 伪元素来隐藏另一个伪元素上的框阴影,使元素看起来像一个单独的元素.>

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;框阴影:5px 5px 10px 2px 黑色;}div:之前,div:之后{内容: "";位置:绝对;顶部:-webkit-calc(100% - 10px);/*可能需要旧浏览器支持的前缀*/顶部:计算(100% - 10px);/*IE.高度的一半*/左:20px;高度:20px;宽度:20px;背景:灰色;变换:旋转(45度);z-索引:-1;框阴影:继承;}div:之后{框阴影:无;z-索引:8;}

唯一元素

综合起来

您还可以再次使用 border-radius 属性为消息框或对话气泡添加边框半径:

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;边框:3px 双黑;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:-webkit-calc(100% - 10px);/*可能需要旧浏览器支持的前缀*/顶部:计算(100% - 10px);/*IE.高度的一半*/左:20px;高度:20px;宽度:20px;背景:灰色;变换:旋转(45度);边框底部:继承;边界权:继承;框阴影:继承;}

唯一元素

这甚至可以让您不仅创建一个三角形,还可以创建一个圆形?

div {高度:100px;宽度:200px;背景:灰色;位置:相对;游标:指针;边框:3px 双黑;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:-webkit-calc(100% - 13px);/*可能需要旧浏览器支持的前缀*/顶部:计算(100% - 13px);/*IE.高度的一半+边框*/左:20px;高度:20px;宽度:20px;背景:灰色;变换:旋转(45度);边框:3px 双透明;边框底部:继承;边界权:继承;框阴影:继承;边界半径:50%;}

唯一元素

如果您遇到内容溢出并隐藏"在这个伪元素后面的问题,并且您不担心有边框,您可以使用负 z-index 来解决这个问题.

不喜欢使用幻数"?

如果您不喜欢使用 calc 值的想法,其中我的答案中的定位当前正在使用(在工作时),您可能希望使用 transform:translate(50%)

这将是一个更好的方法,因为:

  • 你不需要知道边框的大小,也不需要知道一半的宽度
  • 您将使您的消息框/气泡在其定位上更具动态性,并支持进一步调整大小.

div {高度:100px;宽度:200px;背景:灰色;位置:相对;光标:指针;边框:3px双黑;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:100%;左:30px;高度:20px;宽度:20px;背景:灰色;box-sizing:border-box;变换:旋转(45度)平移(-50%);边框底部:继承;边界权:继承;box-shadow:继承;}

唯一元素

想要移动它吗?你可以!

div {高度:100px;宽度:200px;背景:灰色;位置:相对;光标:指针;边框:3px双黑;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:100%;左:10%;高度:20px;宽度:20px;背景:灰色;box-sizing: 边框框;变换:旋转(45度)平移(-50%);边框底部:继承;边界权:继承;box-shadow:继承;过渡:全0.8s;}div:悬停:之前{左:90%;}

唯一元素

想要一个合适的吗?

div {高度:100px;宽度:200px;背景:灰色;位置:相对;光标:指针;边框:3px双黑;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:15%;左:100%;高度:20px;宽度:20px;背景:灰色;box-sizing:border-box;变换:旋转(45度)平移(-50%);边界顶部:继承;边界权:继承;box-shadow:继承;过渡:全0.8s;}div:悬停:之前{最高:80%;}

唯一元素

想要一个不同形状的三角形吗?

div {高度:100px;宽度:200px;背景:灰色;位置:相对;光标:指针;边框半径:10px;}div:之前{内容: "";位置:绝对;顶部:70%;左:100%;高度:20px;宽度:20px;背景:灰色;box-sizing:border-box;变换:平移(-50%)skewX(45deg);box-shadow:继承;过渡:全0.8s;z-索引:-1;}div:悬停:之前{变换:翻译(-50%);边界半径:50%;最高:20%;}

唯一元素

I have a project where I need to insert speech bubbles / message boxes. The general shape I am trying to achieve is this one :

.bubble {
  height: 100px;
  width: 200px;
  border: 3px solid gray;
  background: lightgray;
  position: relative;
  cursor:pointer;
}
.triangle {
  width: 0;
  border-top: 20px solid black;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
  cursor:pointer;
}

<div class="bubble">Speech bubble
</div>
<div class="triangle">
</div>

This currently does not pass a hit-test as the transparent border is also clickable.

Objectives

  • The hit box (clickable / hoverable areas) needs to stick to the shape's boundaries (the transparent borders here are also hoverable, invalidating this).

  • I need to display the shape over various content (images, gradents, text...),

Issues

The main issues I am having when manipulating this shape are:

  • Have the ability to move the triangle around the speech bubble according to the position of the element it refers to (top/left/right/bottom sides)
  • adding a border or box shadow around it when emphasis is needed

Is there anyway of addressing these issues?

解决方案

In order to achieve this, you should consider altering your markup in order to make your html more efficient. This can be achieved using a pseudo element. I'll address each point individually, and put it all together at the end of my answer.

First of all,

Use pseudo elements to avoid extra elements

You could use a pseudo element to remove the extra .triangle div. This not only reduces your div numbers, but also helps with positioning as you can use the top: left: right: and bottom: css properties in order to position according to your main element. This can be seen below:

.oneAndOnlyDiv {
  height: 100px;
  width: 200px;
  border: 3px solid gray;
  background: lightgray;
  position: relative;
}
.oneAndOnlyDiv:before {
  content: "";
  position: absolute;
  top: 100%;
  left: 20px;
  width: 0;
  border-top: 20px solid black;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
}

<div class="oneAndOnlyDiv">Main div</div>


Hit testing

In order to create your "hit test", you may wish to use a rotated element instead of a border hack.

Something like:

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
}
div:before {
  content: "";
  position: absolute;
  top: 100%;
  left: 20px;
  height: 20px;
  width: 20px;
  background: black;
  transform: rotate(45deg);
  transform-origin:top right;
}

<div>Only element</div>

or use a skewed pseudo element:

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
}
div:before {
  content: "";
  position: absolute;
  top: 90%;
  left: 20px;
  height: 30%;
  width: 20px;
  background: black;
  transform: skewY(-45deg);
  transform-origin:bottom left;
  z-index:-1;
}

<div>Only element</div>

which will show the pointer only when the square or main element is hovered. But hang on, that messes up the positioning? how can you deal with that?

There are a few solutions to that. One of which is to use the calc CSS property.

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
}
div:before {
  content: "";
  position: absolute;
  top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
  top: calc(100% - 10px); /*i.e. half the height*/
  left: 20px;
  height: 20px;
  width: 20px;
  background: gray;
  transform: rotate(45deg);
}

<div>Only element</div>

Adding a border

You can add a border quite easily now, simply by adding a border declaration to the main element, and setting the border-bottom and border-right of the pseudo element to inherit

Border

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
  border:3px double black;
}
div:before {
  content: "";
  position: absolute;
  top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
  top: calc(100% - 10px); /*i.e. half the height*/
  left: 20px;
  height: 20px;
  width: 20px;
  background: gray;
  transform: rotate(45deg);
  border-bottom:inherit;
  border-right:inherit;
  box-shadow:inherit;
}

<div>Only element</div>

Box Shadow:

In order to have a box shadow, I've used the :after pseudo element in order to hide the box shadow over the other pseudo, making the element seem as one single element.

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
  box-shadow: 5px 5px 10px 2px black;
}
div:before,div:after {
  content: "";
  position: absolute;
  top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
  top: calc(100% - 10px); /*i.e. half the height*/
  left: 20px;
  height: 20px;
  width: 20px;
  background: gray;
  transform: rotate(45deg);
z-index:-1;
  box-shadow:inherit;
}
div:after{
  box-shadow:none;
  z-index:8;
  }

<div>Only element</div>

Putting it all together

You can also add a border radius to your message box or speech bubble by again, using the border-radius property:

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
  border:3px double black;
  border-radius:10px;
}
div:before {
  content: "";
  position: absolute;
  top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
  top: calc(100% - 10px); /*i.e. half the height*/
  left: 20px;
  height: 20px;
  width: 20px;
  background: gray;
  transform: rotate(45deg);
  border-bottom:inherit;
  border-right:inherit;
  box-shadow:inherit;
}

<div>Only element</div>

This even allows you to create not only a triangle, but how about a circle instead?

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor:pointer;
  border:3px double black;
  border-radius:10px;
}
div:before {
  content: "";
  position: absolute;
  top: -webkit-calc(100% - 13px); /*may require prefix for old browser support*/
  top: calc(100% - 13px); /*i.e. half the height + border*/
  left: 20px;
  height: 20px;
  width: 20px;
  background: gray;
  transform: rotate(45deg);
  border:3px double transparent;
  border-bottom:inherit;
  border-right:inherit;
  box-shadow:inherit;
  border-radius:50%;
}

<div>Only element</div>

If you are having issues with content overflowing and being 'hidden' behind this pseudo element, and you aren't fussed about having a border, you could use a negative z-index which will solve this issue.

Don't like using 'magic numbers'?

If you don't like the idea of using a calc value, in which the positioning in my answer is currently using (whilst working), you may wish to use transform:translate(50%)

This would be a much better approach, since:

  • You do not need to know the size of the border, nor half the width
  • You will be making your message box/ bubble a lot more dynamic in its positioning, and would support further sizings.

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor: pointer;
  border: 3px double black;
  border-radius: 10px;
}
div:before {
  content: "";
  position: absolute;
  top: 100%;
  left: 30px;
  height: 20px;
  width: 20px;
  background: gray;
  box-sizing:border-box;
  transform: rotate(45deg) translate(-50%);
  border-bottom: inherit;
  border-right: inherit;
  box-shadow: inherit;
}

<div>Only element</div>

Want to move it? You can!

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor: pointer;
  border: 3px double black;
  border-radius: 10px;
}
div:before {
  content: "";
  position: absolute;
  top: 100%;
  left: 10%;
  height: 20px;
  width: 20px;
  background: gray;
  box-sizing: border-box;
  transform: rotate(45deg) translate(-50%);
  border-bottom: inherit;
  border-right: inherit;
  box-shadow: inherit;
  transition: all 0.8s;
}
div:hover:before {
  left: 90%;
}

<div>Only element</div>

Want it one the right?

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor: pointer;
  border: 3px double black;
  border-radius: 10px;
}
div:before {
  content: "";
  position: absolute;
  top: 15%;
  left: 100%;
  height: 20px;
  width: 20px;
  background: gray;
  box-sizing:border-box;
  transform: rotate(45deg) translate(-50%);
  border-top: inherit;
  border-right: inherit;
  box-shadow: inherit;
  transition:all 0.8s;
}
div:hover:before{
  top:80%;
  }

<div>Only Element</div>

Want it to be a different shape of triangle?

div {
  height: 100px;
  width: 200px;
  background: gray;
  position: relative;
  cursor: pointer;
  border-radius: 10px;
}
div:before {
  content: "";
  position: absolute;
  top: 70%;
  left: 100%;
  height: 20px;
  width: 20px;
  background: gray;
  box-sizing:border-box;
  transform:  translate(-50%) skewX(45deg);
  box-shadow: inherit;
  transition:all 0.8s;
  z-index:-1;
}
div:hover:before{
  transform:  translate(-50%);
  border-radius:50%;
  top:20%;
  }

<div>Only Element</div>

这篇关于带箭头的气泡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆