dingo_d
dingo_d

Reputation: 11670

Box shape with right angled trapezoids

I'm wondering if this shape can be done in css3 with as little html as possible:

Screenshot

So far, I've managed to do this:

.wrapper {
  position: relative;
}
.box {
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  position: absolute;
  top: 100px;
  left: 100px;
}
.box:before {
  content: "";
  border: 1px solid #000;
  border-bottom: 1px solid #fff;
  width: 50%;
  height: 10px;
  position: absolute;
  top: -12px;
  left: -1px;
}
.box:after {
  content: "";
  border: 1px solid #000;
  border-top: 1px solid #fff;
  width: 50%;
  height: 10px;
  position: absolute;
  bottom: -12px;
  right: -1px;
}
<div class="wrapper">
  <div class="box"></div>
</div>

The fiddle is here, but I don't know how to skew it like that so that I have right angled trapezoid on top and bottom.

Upvotes: 15

Views: 983

Answers (3)

misterManSam
misterManSam

Reputation: 24692

The shape needs no extra elements

The shape can be created with just the <div>:

  • The left side is created with the divs left, top and bottom borders.

  • The right side is made by :before and its top, right and bottom borders

  • The spans joining the two boxes are created with the :after thanks to skewY

Note the browser support of the transform property. IE 9 requires the -ms- prefix, and Safari and the Android browser require -webkit-.

Screenshot

Working Example - just the shape

The CSS has been condensed and the border style of the pseudo elements is inherited from the div itself.

div {
  border: solid 4px #000;
  border-right-width: 0;
  width: 100px;
  height: 200px;
  position: relative;
}
div:before,div:after {
  content: '';
  display: block;
  height: 100%;
  width: 100%;
  border: inherit;
  border-right-width: 4px;
  border-left: none;
  position: absolute;
  left: 100%;
  top: 13px;
  margin-left: 20px;
}
div:after {
  width: 20px;
  border-right: none;
  top: 5px;
  transform: skewY(40deg);
  margin: 0;
}
<div></div>

Working example - with text

With the example above, the contents will not be contained inside the entire shape. Rather, it will be constrained inside the divs half width. The contents needs to be wrapped in a <span> with 200% width to punch it outside of the divs constraints.

div {
  border: solid 4px #000;
  border-right-width: 0;
  width: 100px;
  height: 200px;
  position: relative;
}
div:before,div:after {
  content: '';
  display: block;
  height: 100%;
  width: 100%;
  border: inherit;
  border-right-width: 4px;
  border-left: none;
  position: absolute;
  left: 100%;
  top: 13px;
  margin-left: 20px;
}
div:after {
  width: 20px;
  border-right: none;
  top: 5px;
  transform: skewY(40deg);
  margin: 0;
}
span {
  width: 200%;
  display: block;
  padding: 20px 10px 10px;
}
<div><span>This is me writing a large amount of words into the div. I think that you may want a span in order to contain them.</span></div>

Upvotes: 16

Weafs.py
Weafs.py

Reputation: 22992

I've used four divs: .left, .right, .middle-top and .middle-bottom; and skewed .middle-top and .middle-bottom to add those connection lines.

.left {
    width: 40px;
    height: 100px;
    border: 3px solid black;
    border-right: 1px solid white;
    position: absolute;
    top: 50px;
    left: 100px;
}
.right {
    width: 40px;
    height: 100px;
    border: 3px solid #000;
    border-left: 1px solid white;
    position: absolute;
    top: 60px;
    left: 160px;
}
.middle-top {
    width: 20px;
    height: 20px;
    border-top: 3px solid black;
    position: absolute;
    transform: matrix(1, 0.5, -0.5, 1, 0, 0);
    top: 55px;
    left: 137px;
    z-index: 9;
}
.middle-bottom {
    width: 21px;
    height: 20px;
    border-top: 3px solid black;
    position: absolute;
    transform: matrix(1, 0.5, -0.5, 1, 0, 0);
    top: 158px;
    left: 135px;
    z-index: 9;
}
<div class="left"></div>
<div class="middle-top"></div>
<div class="middle-bottom"></div>
<div class="right"></div>

Upvotes: 3

Alex Char
Alex Char

Reputation: 33218

Using two different elements:

1) Separate the shape in two different rectangular

2)After use pseudo-elements after and before to create the connection line.

My approach:

enter image description here

.wrapper {
  position: relative;
}
.box {
  width: 50px;
  height: 100px;
  border: 4px solid #000;
  position: absolute;
  top: 100px;
  left: 100px;
  border-right: 0;
}
.box2 {
  width: 50px;
  height: 100px;
  border: 4px solid #000;
  position: absolute;
  top: 112px;
  left: 164px;
  border-left: 0;
}
.box:after {
  content: "";
  position: absolute;
  width: 15px;
  border: 2px solid #000;
  right: -15px;
  top: 2px;
  transform: rotate(45deg);
}
.box:before {
  content: "";
  position: absolute;
  width: 15px;
  border: 2px solid #000;
  right: -15px;
  bottom: -10px;
  transform: rotate(45deg);
}
<div class="box"></div>
<div class="box2"></div>

Upvotes: 4

Related Questions