8

I want to make a trapezoid in HTML5. I know it can be done using border radius and a height of 0:

#trapezoid {
    border-bottom: 100px solid red;
    border-left: 50px solid transparent;
    border-right: 50px solid COLOR HERE;
    height: 0;
    width: 100px;
}

However, I want to apply a CSS3 gradient and the above method only allows solid colors.

The following style will make a parallelogram. But is there a way to skew only one of the sides, instead of both?

-webkit-transform: skew(20deg);
Matt Coughlin
  • 18,666
  • 3
  • 46
  • 59
Case
  • 4,244
  • 5
  • 35
  • 53

1 Answers1

11

The trick is to create an angled content mask, and then fill in the masked area with the desired styling, in this case a background gradient. The content will be clipped to the shape of the mask.

A mask is simply a container with overflow:hidden. If a CSS3 transform is applied to the container (for instance, a rotation or a skew operation), the mask will have a rotated or skewed shape, and the content will be clipped to this shape. A pair of nested masks, the outer one skewed and the inner one counter-skewed, produces a trapezoid mask with 2 angled sides. Skewing only the inner mask produces a trapezoid with 1 angled side.

          Both masks skewed           Inner mask skewed
          _________________           _________________
         /                 \          |                \
        /  clipped content  \         | clipped content \
       /_____________________\        |__________________\

JSFiddle demos:

HTML

<div class="main">
    <div class="outer-mask">
        <div class="inner-mask">
            <div class="content">Styled content goes here</div>
        </div>
    </div>
</div>

CSS

.main {
    position: relative;
}
.outer-mask {
    position: absolute;
    left: 95px;
    top: 45px;
    width: 390px;
    height: 110px;
    overflow: hidden;
    -webkit-transform: skew(20deg, 0deg);
        -ms-transform: skew(20deg, 0deg);
         -o-transform: skew(20deg, 0deg);
            transform: skew(20deg, 0deg);
}
.inner-mask {
    position: absolute;
    left: -45px;
    top: 0px;
    width: 390px;
    height: 110px;
    overflow: hidden;
    -webkit-transform: skew(-40deg, 0deg);
        -ms-transform: skew(-40deg, 0deg);
         -o-transform: skew(-40deg, 0deg);
            transform: skew(-40deg, 0deg);
}
Matt Coughlin
  • 18,666
  • 3
  • 46
  • 59
  • You don't need an inner and an outer mask, you can do it with just one. Just make the outer mask a rhombus with vertices pointing to top, bottom, left, right. – Ana Mar 19 '13 at 15:18
  • 2
    See this demo which shows 3 different trapezoids http://codepen.io/thebabydino/pen/eAryD – Ana Mar 19 '13 at 15:35
  • @Ana: I'm starting to get the idea. Two nested elements, both transformed, the outer one a mask. And in your example a pseduo-element is used for the inner one. Fewer masks and HTML elements, though the calculations required are more complex (combining rotation with skew and translation). Thanks for sharing it! – Matt Coughlin Mar 19 '13 at 16:14
  • I was annoyed by the first 5 or so people editing my post that I stopped checking this. I came up with a similar solution but I only use one skew and I didn't know the second option existed. I tried finding more information on Skew before posting but came up with nothing. Instead of making a mask like you did I just had it hidden inside another div because I wanted the top corners of said trapezoid rounded as well. Thank you for taking the time and helping. It's nice to see there are some people on here that actually do that from time to time... – Case Mar 26 '13 at 13:35
  • What if there's a color border with Inner mask skewed? This wouldn't work would it? – bodyfarmer May 22 '15 at 18:22