Search code examples
htmlcsscss-shapes

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.


Solution

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