How to achieve curved top pointer

前端 未结 3 1313
醉酒成梦
醉酒成梦 2021-01-28 12:41

Can anyone please help with this? How to achieve the attached button with CSS only(no image)?

This is my code so far:

相关标签:
3条回答
  • 2021-01-28 13:19

    you can use the shadow on both rounded pseudos

    .bubble {
      position: relative;
      background: #00aabb;
      border-radius: 0.4em;
      width: 200px;
      height: 100px;
    }
    
    .bubble:after,
    .bubble:before {
      content: "";
      position: absolute;
      height: 3em;
      width: 3em;
      border-radius: 50%;
      top: 100%;
      margin: -1px;
    }
    
    :after {
      left: 50%;
      box-shadow: -0.8em -1.4em 0 -0.5em #00aabb
    }
    
    :before {
      right: 50%;
      box-shadow: 0.8em -1.4em 0 -0.5em #00aabb;
    }
    <div class='bubble'></div>

    to understand how it works, give a background to the pseudo and another color to the shadows. You'll be able to reproduce for the sides or the top. It's a matter of the circle size and shadow's size and direction.

    0 讨论(0)
  • 2021-01-28 13:21

    Use pseudo element where you apply a radial-gradient:

    .box {
      margin:60px 10px 0;
      display:inline-block;
      color:#fff;
      text-align:center;
      padding:10px 30px;
      background:green;
      border-radius:50px;
      position:relative;
    }
    .box:before {
      content:"";
      position:absolute;
      bottom:100%;
      left:50%;
      width:60px;
      height:25px;
      transform:translateX(-50%);
      background:
        radial-gradient(farthest-side at top left , transparent 98%,green 100%) left,
        radial-gradient(farthest-side at top right, transparent 98%,green 100%) right;
      background-size:50.2% 100%;
      background-repeat:no-repeat;
    }
    
    body {
     background:pink;
    }
    <div class="box">text here</div>
    
    <div class="box">more and more text here</div>
    
    <div class="box">2 lines <br>of text</div>

    Another idea in case you want any kind of coloration:

    .box {
      margin:60px 10px 0;
      display:inline-block;
      color:#fff;
      text-align:center;
      padding:10px 30px;
      background-image:linear-gradient(60deg,yellow,purple,green,blue);
      background-size:100% calc(100% + 25px);
      background-position:bottom;
      border-radius:50px;
      position:relative;
      z-index:0;
    }
    .box:before {
      content:"";
      position:absolute;
      z-index:-1;
      bottom:0;
      left:0;
      right:0;
      height:calc(100% + 25px);
      background-image:inherit;
      -webkit-mask:
        radial-gradient(farthest-side at top left , transparent 98%,#fff 100%) left,
        radial-gradient(farthest-side at top right, transparent 98%,#fff 100%) right;
      mask:
        radial-gradient(farthest-side at top left , transparent 98%,#fff 100%) left,
        radial-gradient(farthest-side at top right, transparent 98%,#fff 100%) right;
      -webkit-mask-size:30px 25px;
      mask-size:30px 25px;
      -webkit-mask-position:calc(50% - 15px) 0,calc(50% + 15px) 0;
      mask-position:calc(50% - 15px) 0,calc(50% + 15px) 0;
      -webkit-mask-repeat:no-repeat;
      mask-repeat:no-repeat;
    }
    
    body {
     background:pink;
    }
    <div class="box">text here</div>
    
    <div class="box" style="
      background-image:linear-gradient(160deg,white,red,black,orange);">more and more text here</div>
    
    <div class="box" style="
      background-image:linear-gradient(180deg,blue 20%,violet 20%,black);">2 lines <br>of text</div>

    0 讨论(0)
  • 2021-01-28 13:24

    One option is to create a normal rectangle and then position two circles over it, such that they create a curved point.

    In the demo below, this rectangle is represented by the .point div, and the circles are represented by the pseudo-elements ::before and ::after.

    .caption {
      position: relative;
      width: 350px;
     margin-top: 40px;
    }
    
    .caption>.content {
      width: 100%;
      height: 100%;
      padding: 10px;
      box-sizing: border-box;
      border-radius: 30px;
      background-color: green;
      color: white;
      text-align: center;
    }
    
    .caption>.point {
      position: absolute;
      left: 50%;
      top: -30px;
      width: 30%;
      height: 30px;
      transform: translateX(-50%) translateZ(1px);
      overflow: hidden;
      background-color: green;
    }
    
    .caption>.point::before,
    .caption>.point::after {
      content: '';
      display: block;
      width: 100%;
      height: 200%;
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 100%;
      background-color: white;
    }
    
    .caption>.point::before {
      transform: translateX(-49%) translateY(-50%);
    }
    
    .caption>.point::after {
      transform: translateX(49%) translateY(-50%);
    }
    <div class="caption">
      <div class="point"></div>
      <div class="content">This is some text!</div>
    </div>

    Here is a more visual demonstration of what the code is actually doing. The ::before and ::after elements are represented by the red circles. I've reduced the transparency of their fill to 50% so you can see which portion of the .point div they're cutting off.

    .caption {
      position: relative;
      width: 350px;
     margin-top: 40px;
    }
    
    .caption>.content {
      width: 100%;
      height: 100%;
      padding: 10px;
      box-sizing: border-box;
      border-radius: 30px;
      background-color: green;
      color: white;
      text-align: center;
    }
    
    .caption>.point {
      position: absolute;
      left: 50%;
      top: -30px;
      width: 30%;
      height: 30px;
      transform: translateX(-50%) translateZ(1px);
      background-color: green;
    }
    
    .caption>.point::before,
    .caption>.point::after {
      content: '';
      display: block;
      width: 100%;
      height: 200%;
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 100%;
      background-color: rgba(255,255,255,0.5);
      border: 1px solid red;
    }
    
    .caption>.point::before {
      transform: translateX(-49%) translateY(-50%);
    }
    
    .caption>.point::after {
      transform: translateX(49%) translateY(-50%);
    }
    <div class="caption">
      <div class="point"></div>
      <div class="content">This is some text!</div>
    </div>

    0 讨论(0)
提交回复
热议问题