How to position a tilted/skewed shape of unknown height in CSS?


I need to code a design like in image below in CSS. In addition to pure CSS I also have Sass at my disposal.

Note that the solution needs to be responsive. The angle is fixed (14 degrees), while the distance x is not, because it depends on the height of the container (which will be different on different screen widths).

Fixed height

The fixed height version is not a problem:


<section class="container">
  <p class="left">
    Some text spanning multiple lines
  <p class="right">
    Some text spanning multiple lines


@use "sass:math";

$trapezium-skew-angle: -14deg;

@mixin orange-background {
  position: relative;

  // Needs to use pseudo-element to be able to render it
  // below the trapezium's layer
  &::before {
    z-index: -1;
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-color: orange;

@function trapezium-shift($trapezium-height) {
  @return (-1 * math.tan($trapezium-skew-angle) * $trapezium-height) / 2;

@mixin trapezium($height, $width) {
  overflow: hidden;
  position: relative;

  &::after {
    z-index: -1;
    content: "";
    display: block;
    position: absolute;
    left: -1 * trapezium-shift($height);
    top: 0;
    bottom: 0;
    width: $width;
    background-color: blue;
    transform: skew($trapezium-skew-angle);

@mixin column {
  outline: 1px dashed black;
  padding: 4rem;
  width: 50%;

.container {
  @include orange-background;
  display: flex;
  flex-flow: row nowrap;
  height: 300px;

.left {
  @include column;
  @include trapezium($height: 300px, $width: 50%);

.right {
  @include column;


The problem is that my implementation needs to be responsive. When the screen height changes, the height of the container will change too and so will change the value of trapezium-shift (which is marked as x on the image). Sass runs at build-time, so there is no way for Sass to know the height of the container.


Do you know about any possible solution to this?

This is a pen with one solution a guy gave me on StackOverflow: It mostly works, but there is an important problem: the right padding of the left element (yellow background), and the left padding of the right element (orange background) are visually different. Here is a screenshot that shows the problem:

They have the same values in CSS, but because of how we generate that tilted line visually they are not and the text of the left element gets very close to that line on some screen widths, which looks poor. I need to keep that distance - distance of the text contents of both elements from the tilted line - identical.

So I’m still looking for a solution that won’t break that constraint.

Maybe I’m being a bit simplistic but why can’t you use 50% linear gradient? The gradient mid-point of the height will be exactly 50% giving equal amounts to both sides.


Unlike your example the top of the gradient does not start at 50%. The top and bottom of the slant are where they need to be so that the mid point of the gradient is at 50%.

Or did I miss something obvious :slight_smile: (which may be likely).

Oh, but being simple is a virtue - The simpler the better! I just couldn’t work it out in any simpler way myself.

In terms of layout your solution is perfect. My only worry is that the line is not smooth:

Screenshot_2020-08-07 slant across 2 columns(1)

Do you know how to fix this?

Yes linear gradient stops always do that :slight_smile:
One trick is to add a little more to the stop for the second colour (50.1% or 50.2%).


background: linear-gradient(-80deg, yellow, yellow 50%, orange 50.1%);

I’ve updated the codepen which looks better to my eyes but then I am getting on a bit :slight_smile:

Also sometimes changing the angle by a degree can improve results. Cilp path suffers from similar problems.

Great. Thanks. This answers the problem in my question perfectly (there is a small difference that the tilted line on your solution is in the very center of the container, while in my mockup it ends in the center but starts a little on the left, but it hardly makes a difference and I can render it like this). I didn’t know you can display 2 backgrounds separated like this using gradients.

That leads me to another question though. I have numerous shapes like this in the designs I’m working on now. I’m trying to work out a reusable Sass mixin (or few mixins) that I can use to creating them. While your solution works fine in this case, I’m interested if it can be also applied in places, where the tilted line doesn’t separate 2 solid colors, but a solid color and a background image. Screenshot of such situation below:

Can I make one side of gradient an image?

Using the same approach as above you could layer the gradient on to of the image but the image would be covering the whole width so you would need to choose the image carefully.

I’ve added an example here underneath the other one (which I tidied up a little).

You could also use clip-path on the left box to make an angled section but i’m not sure if its any easier than the gradient.

At the end of the day the slant is going to cut across the image so the image always needs to be bigger than what you see. I think its a case of choosing images carefully so the focal point is at the visible end of the element.

I haven’t bothered with media queries for the demo but you can just remove the linear gradient and color each box as required for smaller screens when necessary.

Everything looks good. That the image will be rendered below the gradient is not a problem. I have a wide image, and I can align it to the right side and things should work fine.

Thanks a lot, it’s been super helpful to me. I wasted the whole day yesterday on trying to work this out :).

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.