与箭头的讲话泡影 [英] Speech bubble with arrow

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

问题描述

我有一个项目,需要插入语音气泡/消息框。我想实现的一般形状是这一个:





  .bubble {height: 100px; width:200px; border:3px solid gray;背景:lightgray;位置:相对; cursor:pointer;}。triangle {width:0; border-top:20px solid black; border-left:20px solid transparent; border-right:20px solid transparent; cursor:pointer;}  

 < div class = >语音气泡< / div>< div class =triangle>< / div>  

这个目前没有通过命中测试,透明边框也可以点击。



目标




  • 命中框(可点击区域/悬停区域)需要符合形状的边界

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

    >


问题



操纵这个形状是:




  • 有能力根据位置移动三角形围绕气泡


  • 解决方案

    为了实现这一点,你应该考虑改变你的标记,以使你的HTML更有效率。这可以使用伪元素来实现。



    首先,



    使用伪元素避免额外元素



    您可以使用伪元素来移除额外的 .triangle div。这不仅减少了你的div数,而且有助于定位,你可以使用 top: left: right: bottom: css属性,以便根据您的主元素进行定位。如下所示:



      .oneAndOnlyDiv {height:100px; width:200px; border:3px solid gray;背景:lightgray; position:relative;}。oneAndOnlyDiv:before {content:; position:absolute;顶部: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>  






    命中测试



    为了创建你的命中测试,你可能希望使用一个旋转的元素, hack。



    类似:



      div {height: 100px; width:200px;背景:灰色位置:相对; cursor:pointer;} div:before {content:; position:absolute; top:100%; left:20px; height:20px; width:20px;背景:黑色; transform:rotate(45deg); transform-origin:top right;}  

     < div&只有元素< / div>  



    伪元素



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer;} div:before {content:; position:absolute; top:90%; left:20px;身高:30% width:20px;背景:黑色; transform:skewY(-45deg); transform-origin:left left; z-index:-1;}  

     < div&只有元素< / div>  



    方形或主要元素是悬浮的。
    但是挂起,弄乱了定位?你该如何处理?



    有几个解决方案。其中一个是使用 calc CSS属性。



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer;} div:before {content:; position:absolute; top:-webkit-calc(100% -  10px); / *可能需要前缀为旧的浏览器支持* / top:calc(100% -  10px); /*i.e。一半高* /左:20px; height:20px; width:20px;背景:灰色transform:rotate(45deg);}  

     < div&只有元素< / div>  



    添加边框



    现在可以很容易地添加边框,只需在主元素中添加一个边框声明,并设置 border-bottom border-right 继承



    边框



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black;} div:before {content:; position:absolute; top:-webkit-calc(100% -  10px); / *可能需要前缀为旧的浏览器支持* / top:calc(100% -  10px); /*i.e。一半高* /左:20px; height:20px; width:20px;背景:灰色transform:rotate(45deg); border-bottom:inherit; border-right:inherit; box-shadow:inherit;}  

     < div& 

    strong>



    为了有一个框阴影,我使用:之后隐藏框阴影在其他伪元素,使元素看起来像一个单一的元素。



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; box-shadow:5px 5px 10px 2px black;} div:before,div:after {content:; position:absolute; top:-webkit-calc(100% -  10px); / *可能需要前缀为旧的浏览器支持* / top:calc(100% -  10px); /*i.e。一半高* /左:20px; height:20px; width:20px;背景:灰色transform:rotate(45deg); z-index:-1; box-shadow:inherit;} div:after {box-shadow:none; z-index:8; }  

     < div& / code> 



    完全


    $ b b

    您还可以使用border-radius属性将一个边框半径添加到您的消息框或语音泡泡:



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black; border-radius:10px;} div:before {content:; position:absolute; top:-webkit-calc(100% -  10px); / *可能需要前缀为旧的浏览器支持* / top:calc(100% -  10px); /*i.e。一半高* /左:20px; height:20px; width:20px;背景:灰色transform:rotate(45deg); border-bottom:inherit; border-right:inherit; box-shadow:inherit;}  

     < div&元素< / div>  





      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black; border-radius:10px;} div:before {content:; position:absolute; top:-webkit-calc(100% -  13px); / *可能需要前缀为旧浏览器支持* / top:calc(100% -  13px); /*i.e。一半高度+边框* /左:20px; height:20px; width:20px;背景:灰色transform:rotate(45deg); border:3px double double; border-bottom:inherit; border-right:inherit; box-shadow:inherit; border-radius:50%;}  

     < div&只有元素< / div>  



    溢出和隐藏在这个伪元素的后面,你不担心有边框,你可以使用一个负z-index,这将解决这个问题。



    不喜欢使用魔法数字?



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



    更好的方法,因为:




    • 您不需要知道边框的大小,也不需要宽度的一半
    • $ b $

        div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black; border-radius:10px;} div:before {content:; position:absolute; top:100%; left:30px; height:20px; width:20px;背景:灰色box-sizing:border-box; transform:rotate(45deg)translate(-50%); border-bottom:inherit; border-right:inherit; box-shadow:inherit;}  

       < div&元素< / div>  



      您可以!



        div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black; border-radius:10px;} div:before {content:; position:absolute; top:100%;左:10%; height:20px; width:20px;背景:灰色box-sizing:border-box; transform:rotate(45deg)translate(-50%); border-bottom:inherit; border-right:inherit; box-shadow:继承; transition:all 0.8s;} div:hover:before {left:90%;}  

       < div>只有元素< / div>  


      $ b $

      true>

        div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border:3px double black; border-radius:10px;} div:before {content:; position:absolute; top:15%;左:100%; height:20px; width:20px;背景:灰色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& / code> 



    想要成为不同形状的三角形吗? / strong>



      div {height:100px; width:200px;背景:灰色位置:相对; cursor:pointer; border-radius:10px;} div:before {content:; position:absolute; top:70%;左:100%; height:20px; width:20px;背景:灰色box-sizing:border-box; transform:translate(-50%)skewX(45deg); box-shadow:继承; transition:all 0.8s; z-index:-1;} div:hover:before {transform:translate(-50%); border-radius:50%; top:20%; }  

     < div& / code> 


    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 altogether 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 altogether

    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天全站免登陆