How can I make octagon shape box?

2019-04-10 19:22发布

I want to create the below given box by using CSS.

enter image description here

I searched a lot and read very good articles like https://css-tricks.com/examples/ShapesOfCSS/ but I got stuck in one issue - the purple border cutting edges. I tried octagon shape but that is not working for this case.

I almost achieved this. Here is my snippet:

.box-outer {
  width: 300px;
  height: 120px;
  padding: 15px 30px;
  background: rgba(237, 236, 236, 0.72);
  border: 3px solid rgb(89, 67, 128);
  position: relative;
  border-right: 20px solid rgb(89, 67, 128);
}
.box-outer:before {
  content: "";
  position: absolute;
  top: -3px;
  left: -4px;
  border-bottom: 29px solid rgb(255, 252, 252);
  border-right: 29px solid #594380;
  border-top: 28px solid #FFF;
  height: 66%;
  width: 0;
}
.box-outer:after {
  content: "";
  position: absolute;
  top: -3px;
  right: -13%;
  border-top: 29px solid white;
  border-left: 29px solid #594380;
  border-bottom: 28px solid #FFF;
  width: 0;
  height: 66%;
}
.box-outer .right-text {
  position: absolute;
  right: -22%;
  color: white;
  font-size: 20px;
  top: 40%;
  z-index: 10;
  transform: rotate(-90deg);
  -ms-transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);
}
<div class="box-outer">
  <span class="right-text">
           LEGISLATIVE
        </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
<!--box outer-->

Current work screenshot

enter image description here

3条回答
做个烂人
2楼-- · 2019-04-10 19:34

please check out this solution finally i made it

I add box-inner div to make this possible.

check out fiddle

`http://jsfiddle.net/maverickabhi/qfthejb2/`

.box-outer {
  width: 300px;
  height: 120px;
  padding: 15px 30px;
  background: rgba(237, 236, 236, 0.72);
  border: 3px solid rgb(89, 67, 128);
  position: relative;
  border-right: 20px solid rgb(89, 67, 128);
}
.box-outer:before {
  content: "";
  position: absolute;
  top: -3px;
  left: -4px;
  border-bottom: 29px solid rgb(255, 252, 252);
  border-right: 29px solid #594380;
  border-top: 28px solid #FFF;
  height: 66%;
  width: 0;
}
.box-outer:after {
  content: "";
  position: absolute;
  top: -3px;
  right: -13%;
  border-top: 29px solid white;
  border-left: 29px solid #594380;
  border-bottom: 28px solid #FFF;
  width: 0;
  height: 66%;
}
.box-outer .right-text {
  position: absolute;
  right: -22%;
  color: white;
  font-size: 20px;
  top: 40%;
  z-index: 10;
  transform: rotate(-90deg);
  -ms-transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);
}
.box-inner {
  content: "";
  position: absolute;
  top: -2px;
  left: -1px;
  border-bottom: 30px solid transparent;
  border-right: 29px solid #F1F0F0;
  border-top: 29px solid transparent;
  height: 63%;
  width: 0;
}
<div class="box-outer">
  <span class="right-text">
           LEGISLATIVE
        </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
  <div class="box-inner"></div>
</div>
<!--box outer-->

查看更多
三岁会撩人
3楼-- · 2019-04-10 19:36

Here is an alternate method using CSS3 transforms to achieve the octagon shape and also have transparency inside it. While using this method, the background need not be a solid color. It can be a image or a gradient.

The shape essentially consists of the following:

  • A container with a top border, bottom border and an inset box shadow on the right hand side. (Green colored area in below screenshot*)
  • A pseudo-element on the left side with the same height as the container that is rotated with perspective using transforms. (Blue colored area in below screenshot*)
  • Another pseudo-element on the right side which is rotated in the reverse direction of the element on the left side. (Red colored area in below screenshot*)
  • The inset box-shadow on the container is the same as the background of the pseudo-element on the right side (to make it look as though only half of it is skewed).
  • Extra shadows around the parent container and the pseudo-element on the right side to provide a shadow to the whole shape.

enter image description here

* - different colors are used only for illustrating how the shape is formed.

.shape {
  position: relative;
  height: 150px;
  width: 300px;
  margin: 40px;
  border-color: #594380;
  border-style: solid;
  border-width: 2px 0px;
  background: rgba(252, 252, 252, 0.5);
  box-shadow: inset -20px 0px 0px #594380, 2px 3px 3px rgba(0,0,0,0.3);
}
.shape:before,
.shape:after {
  position: absolute;
  content: '';
  top: -2px;
  width: 30px;
  height: 100%;
  border: 2px solid #594380;
}
.shape:before {
  left: -32px;
  border-right: none;
  background: rgba(252, 252, 252, 0.5);
  -webkit-transform-origin: right 50%;
  -moz-transform-origin: right 50%;
  transform-origin: right 50%;
  -webkit-transform: perspective(15px) rotateY(-10deg);
  -moz-transform: perspective(15px) rotateY(-10deg);
  transform: perspective(15px) rotateY(-10deg);
  box-shadow: inset 2px 0px 0px #594380, inset 0px -1px 0px #594380, inset 0px 1px 0px #594380;
}
.shape:after {
  right: -34px;
  background: #594380;
  -webkit-transform-origin: left 50%;
  -moz-transform-origin: left 50%;
  transform-origin: left 50%;
  -webkit-transform: perspective(15px) rotateY(10deg);
  -moz-transform: perspective(15px) rotateY(10deg);
  transform: perspective(15px) rotateY(10deg);
  box-shadow: inset -2px 0px 0px #594380, inset 0px -1px 0px #594380, inset 0px 1px 0px #594380, 6px 2px 5px 3px rgba(0,0,0,0.3);
}
span {
  position: absolute;
  right: 0px;
  top: 12px;
  display: block;
  height: 20px;
  width: 100px;
  text-align: center;
  text-transform: uppercase;
  color: white;
  -webkit-transform-origin: right;
  -moz-transform-origin: right;
  transform-origin: right;
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  transform: rotate(-90deg);
  z-index: 2;
}
body {
  background: url(http://lorempixel.com/500/500);
}
<div class="shape">
  Lorem ipsum dolor sit amet...
  <span>legislative</span>
</div>

Note: There will be a slight misalignment of the borders on the left side when we look at it very closely but it is a barely noticeable glitch. The idea of posting this answer is to give an idea for future readers.


Other methods to get Octagon Shapes:

  • This CodePen contributed by jbutler483 has a sample achieved using a different method. Like the above snippet, this also has a very small glitch wherein the angled borders on left side is a bit thin because of the use of skew transforms.
  • If the need is for a transparent regular octagon shape, the method used in the below snippet can be adopted. This is not all that useful when dealing with semi transparent shapes (as can be seen with the second sample). Note that positioning text within the shape needs to be handled separately.

.shape,
.octagon,
.shape:before,
.shape:after {
  border-top: 2px solid steelblue;
  border-bottom: 2px solid steelblue;
}

.shape {
  height: -webkit-calc(141.44px + 100px); /* width * sin(135) * 2 + width */
  height: -moz-calc(141.44px + 100px);
  height: calc(141.44px + 100px);
  width: 100px;
  position: relative;
  margin: 40px 80px;
}

.shape:after,
.shape:before,
.octagon {
  position: absolute;
  height: 100%;
  width: -webkit-calc(100% + 2px);
  width: -moz-calc(100% + 2px);
  width: calc(100% + 2px);
}

.shape:before,
.shape:after {
  content: '';
  top: -2px;
  left: -2px;
}

.octagon {
  top: -2px;
  left: -2px;
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}

.shape:before {
  -webkit-transform: rotate(135deg);
  -moz-transform: rotate(135deg);
  transform: rotate(135deg);
}

.shape:after {
  -webkit-transform: rotate(-135deg);
  -moz-transform: rotate(-135deg);
  transform: rotate(-135deg);
}

.semi-transparent, .semi-transparent .octagon, .semi-transparent.shape:after, .semi-transparent.shape:before{
  background: rgba(1, 1, 1, 0.5);  
}

body {
  background: -webkit-linear-gradient(90deg, crimson, indianred, purple);
  background: -moz-linear-gradient(90deg, crimson, indianred, purple);
  background: linear-gradient(90deg, crimson, indianred, purple)
}
body > div{
  display: inline-block;
}
<div class="shape">
    <div class="octagon"></div>
</div>

<div class="shape  semi-transparent">
    <div class="octagon"></div>
</div>

查看更多
再贱就再见
4楼-- · 2019-04-10 19:39

Here is a svg solution.

Unfortunately it uses some hard coded numbers for size.

I find the vertical text much easier to do in svg since you can simply rotate it by 90deg and it works.

The main element is two polygons. Considered using an gradient for elements background, but choose this because its easier to understand what's going on with the shapes.

The text element is done with a div and setting it absolute with fixed sizes. I find that this could be done better but could not think of a better solution at the top of my head.

.box div{
  position: absolute;
  margin-left: 70px;
  margin-right: 100px;
  margin-top: 5px;
  width: calc(600px - 70px - 100px);
}
.ticket .content {
  stroke: rgb(100, 0, 100);
  stroke-width: 2px;
  fill: #fff;
}
.ticket .end {
  stroke: rgb(100, 0, 100);
  stroke-width: 2px;
  fill: rgb(100, 0, 100);
}
.ticket #vertical {
  fill: #fff;
}
<div class="box">
  <div>lorem ipsum dolar si amet lorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si ametlorem ipsum dolar si amet</div>
  <svg class="ticket" height="300px" width="600px" viewbox="-1 -1 202 102">
    <polygon class="content" points=" 0 20, 20 0, 170 0, 170 100, 20 100, 0 80" />
    <polygon class="end" points="170 0, 180 0, 200 20, 200 80, 180 100, 170, 100" />
    <text id="vertical" transform="translate(185 93) rotate(-90)">Golden ticket</text>
  </svg>
</div>

查看更多
登录 后发表回答