CSS hexagonal button with rounded corners

2019-06-23 18:55发布

问题:

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

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

回答1:

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.



回答2:

Try this one.

.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:"";
       transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -webkit-transform: rotate(45deg);
    -o-transform: rotate(45deg);
    -moz-transform: rotate(45deg); 
    background-color: #f4d046;
    width:38px;
    height:39px;
    top: 5.3px;
    right: 85%;
    position:absolute;
    border-radius:6px;
    z-index:-1;
   }

.lngbtn:after {
       content:"";
       transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -webkit-transform: rotate(45deg);
    -o-transform: rotate(45deg);
    -moz-transform: rotate(45deg); 
    background-color: #f4d046;
    width:38px;
    height:39px;
    top: 5.3px;
    left: 85%;
    position:absolute;
    border-radius:6px;
    z-index:-1;
}
<a href="#" class="lngbtn">Get to know us</a>



回答3:

Here is how we can achieve with css

.button{
		position: relative;
		display:block;
		background: transparent;
		width:200px;
		height:60px;
		line-height:60px;
		text-align:center;
		font-size:15px;
		text-decoration:none;
		text-transform:uppercase;
		margin:40px auto;
	}

	.button:before, .button:after {
		width:200px;
		left: 0px;
		height:27px;
		z-index: -1;
		border-radius:5px;
		background:yellow;
	}

	/* Button Border Style */
	.violet:before,.violet:after {
		border: 3px solid yellow;
	}
	
	.button:before{
		position: absolute;
		content: '';
		border-bottom: none;
		-webkit-transform: perspective(15px) rotateX(5deg);
		-moz-transform: perspective(15px) rotateX(5deg);
		transform: perspective(15px) rotateX(5deg);  
	}

	.button:after{
		position: absolute;
		top: 32px;
		content: '';
		border-top: none;
		-webkit-transform: perspective(15px) rotateX(-5deg);
		-moz-transform: perspective(15px) rotateX(-5deg);
		transform: perspective(15px) rotateX(-5deg);
	}

	/* Just for presentation */
	body{
		position: absolute;
		height: 100%;
		width: 100%;
		background: #fff;
	}
<a href="#" class="button violet">get to know us!</a>



回答4:

Since the triangles and the main body of the button are the same color, you can make your before and after into squares and rotate them by 45 degrees with transform: rotate(45deg) to make it look like they are triangles. You can then use border-radius to make the edges rounded. It'll take some positioning and sizing to get them look right. I've made an example at https://jsfiddle.net/93zbLqLy/

The downside of this method is that you can only have triangle edges that are 45 degrees.