Tilted Angles in Sass


There are quite a few ways to implement this. You could have base 64 encoded images applied as a background, but it makes it hard to customise (color, angle, etc.).

Another way would be to skew and/or rotate an absolutely positioned pseudo-element, but if there is one thing I don’t want to deal with, it’s the skew transform. God, no.

When using Sass, you could use the Angled Edges library that encodes dynamically generated SVG. It works super well, however it requires a fixed width and height expressed in pixels, which kind of bothered me.

I also really wanted to see if and how I could be able to implement this. I ended up with a solution that I am really proud of, even if it might be a bit over-engineered for simple scenarios.

<div class="container">
  <div class="content">
    <h1>Tilted angles in CSS</h1>
    <p>Thanks to Pythagoras Theorem, some gradients and a bit of Sass-powered trigonometry, we can easily created tilted angles with nothing but CSS.</p>
    <pre><code>.container {
  @include tilted(3deg, $color: #fff);
    <p>How handy!</p>
/// Computes the height of the tilted pseudo-element based on the given angle
/// using Pythagoras Theorem.
// sin(..), pow(..) and sqrt(..)  functions come from this pen:
// http://codepen.io/HugoGiraudel/pen/rLpPGo
/// @access public
/// @author Hugo Giraudel
/// @param {Angle} $angle - the tilt angle
@function get-tilted-height($angle) {
  $a: (100% / 1%);
  $A: (90deg - $angle);
  $c: ($a / sin($A));
  $b: sqrt(pow($c, 2) - pow($a, 2));

  @return (abs($b) * 1%);

/// Apply a tilted effect by generating a pseudo-element with a diagonal
/// splitted background.
/// @access public
/// @author Hugo Giraudel
/// @param {Angle} $angle - the tilt angle
/// @param {Color} $color - the color to be used as background + gradient
/// @param {String} $position ['top'] - either `top` or `bottom`
/// @param {String} $pseudo ['before'] - either `before` or `after`
@mixin tilted($angle, $color, $position: 'top', $pseudo: 'before') {
  $height: get-tilted-height($angle);

  position: relative;
  background-color: $color;

  &::#{$pseudo} {
    content: '';
    padding-top: $height;
    position: absolute;
    left: 0;
    right: 0;

    @if ($position == 'top') {
      bottom: 100%;
      background-image: linear-gradient($angle, $color 50%, transparent 50%);
    } @else {
      top: 100%;
      background-image: linear-gradient($angle, transparent 50%, $color 50%);

 * Demo styles

html {
  box-sizing: border-box;
  height: 100%;

*, ::before, ::after {
  box-sizing: inherit;

body {
  background-color: rgb(223, 231, 238);
  line-height: 1.5;
  font-size: 125%;
  display: flex;
  align-items: flex-end;
  height: 100%;

.container {
  @include tilted(3deg, rgb(255, 255, 255));
  padding: 0 1em;
  max-width: 80%;
  margin: 0 auto;
  filter: drop-shadow(0 1em 1em rgba(0, 0, 0, 0.1));

.content {
  max-width: 600px;
  margin: 0 auto;
  padding: 0 1em;

h1 {
  border-bottom: 3px double deepskyblue;
  padding-bottom: 0.25em;
  margin-bottom: 0.25em;

pre {
  background-color: #efefef;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 0.5em;


Live example


All Rights Reserved

Let's register a Viblo Account to get more interesting posts.