Search code examples
htmlcsscss-shapes

How to achieve curved top pointer


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

Curved top Button CSS

This is my code so far:

.triangle-up {
  width: 0;
  height: 0;
  border-left: 25px solid transparent;
  border-right: 25px solid transparent;
  border-bottom: 50px solid #555;
}
<div class="triangle-up"></div>


Solution

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