Robert
Robert

Reputation: 69

Hexagon shaped element with one side broader than the other

I have problem with slope border bottom in my shape. I have this:

enter image description here

I did the left and right side but I didn't know how to modify the central part. Please help.

My Code.

h3{
    font-size: 60px;
    position: relative;
    display: inline-block;
    padding: 10px 30px 8px 30px;
    height: 80px;
    width: auto;
    background: #000;
    line-height: 80px;
    margin-bottom: 20px;
    font-family: 'Bitter', 'Trebuchet MS', Arial;
    text-shadow: 1px 1px 1px rgba(0,0,0,0.9);
    color: white;

}

h3::before{
    content: '';
    width: 0;
    height: 0;
    border-top: 38px solid transparent;
    border-bottom: 60px solid transparent;
    border-right: 60px solid black;
    position: absolute;
    left: -59px;
    top: 0px;
    background: red;
}
h3::after{
    content: '';
    width: 0;
    height: 0;
    border-top: 38px solid transparent;
    border-bottom: 60px solid transparent;
    border-left: 60px solid black;
    position: absolute;
    right: -59px;
    top: 0px;
    background: red;
}

And the HTML is a simple <h3> header.

Upvotes: 3

Views: 598

Answers (2)

Harry
Harry

Reputation: 89760

The shape in question can be achieved by rotating elements with a bit of perspective. The idea is as follows: (not the same approach as the one you have used but this is the best in my opinion).

  • Split the container into two halves with two pseudo-elements
  • Rotate one half along one direction along the X-axis and the other half in the opposite direction. Doing this would produce a regular elongated hexagon shape and
  • Then rotate the whole parent along the Y-axis.
  • All of the rotations are done with a bit of perspective and hence make it look as though one side is broader than the other.

The shape produced using this method can have a transparent (or) a semi-transparent (or) a solid background.

Some of the drawbacks of the CSS based approach are:

  • Not suitable if an image needs to be fit within the shape.
  • The shape is scalable but as the width increases, the perspective and angle of rotation might probably need adjustment depending on the amount of increase.
  • Hover effect on the shape would be triggered even when the mouse is a bit outside the shape because of how it is created. The question was about the shape for a <h3> element and so hover is probably not a big concern.

Below is a sample snippet:

.container {
  position: relative;
  height: 100px;
  width: 300px;
  text-align: center;
  line-height: 100px;
  margin: 10px auto;
  font-size: 20px;
}
.shape {
  position: absolute;
  top: 0px;
  right: 0px;
  height: 100%;
  width: 75%;
  perspective: 10px;
  transform-origin: right 50%;
  transform: perspective(31px) rotateY(2deg);
}
.shape:before,
.shape:after {
  position: absolute;
  content: '';
  left: 0px;
  height: 50%;
  width: 100%;
  background: rgba(0, 0, 0, 0.3);
  z-index: -1;
}
.shape:before {
  top: 0px;
  transform-origin: left bottom;
  transform: rotateX(5deg);
}
.shape:after {
  bottom: 0px;
  transform-origin: 0% top;
  transform: rotateX(-5deg);
}
.container span {
  position: relative;
  display: inline-block;
  height: 100%;
  width: 75%;
  color: white;
  z-index: 2;
}
.solid .shape:after,
.solid .shape:before {
  background: maroon;
}
.transparent .shape:after,
.transparent .shape:before {
  background: transparent;
  border: 2px solid;
}
.transparent .shape:after {
  bottom: -3px;
  border-width: 0px 3px 3px 2px;
}
.transparent .shape:before {
  top: -3px;
  border-width: 3px 3px 0px 2px;
}
.shape:hover:after,
.shape:hover:before,
span:hover + .shape:before,
span:hover + .shape:after {
  background: rgba(0, 0, 0, 0.6);
}
/* just for demo */

body {
  background: linear-gradient(90deg, crimson, indianred, purple);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='container'>
  <span>Hello World</span>
  <div class='shape'></div>
</div>
<div class='container solid'>
  <span>Hello World</span>
  <div class='shape'></div>
</div>
<div class='container transparent'>
  <span>Hello World</span>
  <div class='shape'></div>
</div>


All the drawbacks of the CSS approach can be avoided while using SVG for creating the shape.

.vector {
  position: relative;
  height: 100px;
  width: 300px;
  text-align: center;
  line-height: 100px;
  margin: 10px auto;
  font-size: 20px;
}
svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
polygon {
  fill: rgba(0, 0, 0, 0.5);
}
polygon.solid{
  fill: maroon;
}
polygon.transparent{
  fill: transparent;
  stroke-width: 2;
  stroke: black;
}
polygon.image {
  fill: url(#image);
}
.vector span {
  position: relative;
  color: white;
  z-index: 2;
}
polygon:hover,
span:hover + svg polygon {
  fill: rgba(0, 0, 0, 0.3);
  stroke-width: 2;
  stroke: black;
}
/* just for demo */

body {
  background: linear-gradient(90deg, crimson, indianred, purple);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='vector'>
  <span>Hello World</span>
  <svg viewBox='0 0 350 100' preserveaspectratio='none'>
    <polygon points='0,50 70,7 310,15 350,50 310,85 70,93' />
  </svg>
</div>
<div class='vector'>
  <span>Hello World</span>
  <svg viewBox='0 0 350 100' preserveaspectratio='none'>
    <polygon points='0,50 70,7 310,15 350,50 310,85 70,93' class="solid"/>
  </svg>
</div>
<div class='vector'>
  <span>Hello World</span>
  <svg viewBox='0 0 350 100' preserveaspectratio='none'>
    <polygon points='0,50 70,7 310,15 350,50 310,85 70,93' class="transparent"/>
  </svg>
</div>
<div class='vector'>
  <span>Hello World</span>
  <svg viewBox='0 0 350 100' preserveaspectratio='none'>
    <defs>
      <pattern id='image' width='350' height='100' patternUnits='userSpaceOnUse'>
        <image xlink:href='http://lorempixel.com/350/100' width='350' height='100' />
      </pattern>
    </defs>
    <polygon points='0,50 70,7 310,15 350,50 310,85 70,93' class='image' />
  </svg>
</div>

Upvotes: 2

Akshay
Akshay

Reputation: 14348

Check this pure css solution it works on transform perspective

div {
    cursor:pointer;
    width:200px;
    height:100px;
    transform:perspective(500px) rotateY(40deg);
    background:orange;
    margin:50px;
    overflow:visible;
}
div:after {
    position:absolute;
    content:"";
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-bottom: 50px solid transparent;
    border-right:60px solid orange;
    margin-left:-60px;
}
div:before {
    position:absolute;
    content:"";
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-bottom: 50px solid transparent;
    border-left: 60px solid orange;
    margin-left:200px;
    transition:.5s all;
}

div:hover{
    background:grey;
}
div:hover:before{
     border-left-color: grey;
}
div:hover:after{
    border-right-color: grey;

}
<div>

Upvotes: 2

Related Questions