Search code examples
cssbuttoncss-shapes

CSS hexagonal button with rounded corners


I'm able to create the same button with CSS. The rounded corners are the important part corners are the main reason. Triangle button with rounded corners, please see my below code and image

image

.lngbtn {
	position: relative;
	width: 150px;
	height: 50px;
	margin: 50px;
	color: #FFFFFF;
	background-color: #f4d046;
	text-align: center;
	line-height: 48px;
    padding: 16px;
	font-weight: bold;
}



.lngbtn:before {
    content:"";
    position: absolute;
    right: 100%;
    top:0px;
    width:0px;
    height:0px;
    border-top:25px solid transparent;
    border-right:30px solid #f4d046;
    border-bottom:25px solid transparent;
}

.lngbtn:after {
    content:"";
    position: absolute;
    left: 100%;
    top:0px;
    width:0px;
    height:0px;
    border-top:25px solid transparent;
    border-left:30px solid #f4d046;
    border-bottom:25px solid transparent;
}
<a href="#" class="lngbtn">Get to know us</a>


Solution

  • I am not saying that this cannot be achieved with CSS but doing this with CSS would be a tedious job. SVG is always the recommended tool for creating complex shapes like this (and this particular shape is tough to create even using SVG).

    SVGs are:

    • scalable and so they help in responsive design, the shape can stretch to match the content
    • allows us more control over the shape
    • are easy to maintain
    • allow us to use even gradient or non-solid color backgrounds for the element like done in this answer (which was for a regular hexagon with rounded corners

    In SVG, it just requires a path to be created in the form of a rounded hexagon and then for that path image to be placed behind the container.

    Below is some explanation about the various commands used in the path element's d attribute (but I'd strongly advise you to learn SVG commands - here is a tutor from the MDN):

    • M - moves the imaginary pen to the point specified by the coordinates.
    • L - draws a straight line from the point represented by the previous coordinate to current one.
    • Q - Draws a quadratic curve from the current position of the pen to the point that is indicated by the second set of coordinates that follow the Q command. The first set of coordinates represent the control point. This control point determines the slope of the curve.
    • z - Closes the shape by drawing a straight line from the current pen position to the starting point.

    .hex {
      position: relative;
      height: 100px;
      min-width: 100px;
      padding: 12px 24px;
      margin: 4px;
      float: left;
      font-weight: bold;
      font-size: 20px;
      text-align: center;
      color: white;
    }
    .hex svg {
      position: absolute;
      height: 100%;
      width: 100%;
      top: 0px;
      left: 0px;
      z-index: -1;
    }
    path {
      fill: rgb(251, 208, 0);
    }
    .hex.border path {
      stroke: red;
      stroke-width: 4;
    }
    span {
      display: block;
      margin-top: 50px;
      padding: 8px;
      transform: translateY(-50%);
    }
    <div class='hex'>
      <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
        <path d='M27,7 
                 L72,7  Q76,7 78,11 
                 L95,46 Q97,50 95,54 
                 L78,91 Q76,95 72,95
                 L28,95 Q24,95 22,91
                 L5,54  Q3,50 5,46
                 L22,11 Q24,7 28,7z' vector-effect='non-scaling-stroke' />
      </svg>
      <span>Some text</span>
    </div>
    
    <div class='hex'>
      <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
        <path d='M27,7 
                 L72,7  Q76,7 78,11 
                 L95,46 Q97,50 95,54 
                 L78,91 Q76,95 72,95
                 L28,95 Q24,95 22,91
                 L5,54  Q3,50 5,46
                 L22,11 Q24,7 28,7z' vector-effect='non-scaling-stroke' />
      </svg>
      <span>Some lengthy text
      without line break.</span>
    </div>
    
    <div class='hex border'>
      <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
        <path d='M27,7 
                 L72,7  Q76,7 78,11 
                 L95,46 Q97,50 95,54 
                 L78,91 Q76,95 72,95
                 L28,95 Q24,95 22,91
                 L5,54  Q3,50 5,46
                 L22,11 Q24,7 28,7z' vector-effect='non-scaling-stroke' />
      </svg>
      <span>Some very lengthy text</span>
    </div>
    
    <div class='hex border'>
      <svg viewBox='0 0 100 100' preserveAspectRatio='none'>
        <path d='M27,7 
                 L72,7  Q76,7 78,11 
                 L95,46 Q97,50 95,54 
                 L78,91 Q76,95 72,95
                 L28,95 Q24,95 22,91
                 L5,54  Q3,50 5,46
                 L22,11 Q24,7 28,7z' vector-effect='non-scaling-stroke' />
      </svg>
      <span>Some very lengthy text
      <br>with line break.</span>
    </div>


    For your case, since you need the shape to be a button (or a link), you should wrap the path element inside a a (SVG anchor element) like in the below snippet and use the text element to add text (like a span). You'd also notice that I have modified the shape slightly to make the angles on the sides little narrower.

    .hex {
      position: relative;
      height: 100px;
      min-width: 300px;
      padding: 12px 24px;
      margin: 4px;
      float: left;
    }
    .hex svg {
      position: absolute;
      height: 100%;
      width: 100%;
      top: 0px;
      left: 0px;
    }
    path {
      fill: rgb(251, 208, 0);
    }
    text {
      font-family: Arial;
      font-weight: bold;
    }
    <div class='hex'>
      <svg viewBox='0 0 300 100' preserveAspectRatio='none'>
        <a xlink:href='#'>
          <path d='M52,7 
                 L248,7  Q253,7 258,11 
                 L295,46 Q297,50 295,54 
                 L258,91 Q253,95 248,95
                 L52,95 Q48,95 42,91
                 L5,54  Q3,50 5,46
                 L42,11 Q48,7 52,7z' vector-effect='non-scaling-stroke' />
          <text fill='white' text-anchor='middle' x='150' y='55'>Get to know us</text>
        </a>
      </svg>
    </div>


    Notes:

    • The shape is not 100% perfect but I'd leave the fine tuning to you. The answer is to help you with a starting point.

    • I've added a stroke (border) just to show that it also can be done. If not needed you can remove it by removing the stroke and stroke-width properties from the CSS for path element.

    • Don't be put off by how lengthy the SVG code is, it is so big only because I've repeated it more than once - once for each container. That can be reduced.