Search code examples
htmlcssbootstrap-4linear-gradients

CSS Shape with Gradient Next Adjacent to Container


I'm trying to put together a specific design for a website we are building. The header needs a parallelogram shape above it, and a trapezium to the right of the container, as shown below.

Header Example

I've managed to add the parallelogram above the container, but i'm struggling to get the element to the right of the container. The following shows what i've done.

HTML

<div class="container">
  <div class="row">
    <div class="col">
      Content Here
    </div>
  </div>
</div>

CSS

.container {
  width: 700px;
}

.container:before {
  content:'';
    width: 100%;
    height: 30px;
    transform: skew(45deg);
    background: #254896;
    background: linear-gradient(90deg, #254896, #2c2b5b 100%);
    display: block;
}

.row {
  background: #f8f9fa;

}

.row:before {
    content:'';
    width: 100%;
    height: 0;
    border-image-source: linear-gradient(90deg, #FF0000, #940202);
    border-image-slice: 1;
    border-top: 30px solid red;
  border-left: 30px solid transparent;
    position: absolute;
    left: 800px;
    top: 30px;
}

.col {
  background-color: #ddd;
  padding: 10px;
}  

https://jsfiddle.net/scarrott/vgtpna14/

The issues i'm having are:

  • Getting the red shape to sit neatly to the right of the container regardless of screen size.
  • Putting a gradient fill on the trapezium shape. If I use border-image-source it makes the shape a rectangle.

Any help would be greatly appreciated.


Solution

  • Here is an idea using multiple background. I used 400px instead of 700px to better see in the snippet

    body {
      overflow-x: hidden;
    }
    
    .container {
      --w:400px;
      max-width: var(--w);
      position: relative;
      margin: 40px auto;
    }
    
    .container:before {
      content: '';
      position: absolute;
      top: -20px;
      left: 0;
      width: calc(50vw + var(--w)/2);
      min-width: 100%;
      height: 40px;
      transform: skew(45deg);
      transform-origin: top;
      background: 
        linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%, 
        linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
      background-repeat: no-repeat;
    }
    
    .row {
      background: #f8f9fa;
    }
    
    .col {
      padding: 10px;
    }
    <div class="container">
      <div class="row">
        <div class="col">
          Content Here
        </div>
      </div>
    </div>

    Another idea with clip-path:

    body {
      overflow-x: hidden;
    }
    
    .container {
      --w:400px;
      max-width: var(--w);
      position: relative;
      margin: 40px auto;
    }
    
    .container:before {
      content: '';
      position: absolute;
      top: -20px;
      left: 0;
      width: calc(50vw + var(--w)/2);
      min-width: 100%;
      height: 40px;
      clip-path:polygon(0 0, calc(var(--w) - 20px) 0,var(--w) 50%,100% 50%,100% 100%,calc(var(--w) + 20px) 100%,var(--w) 50%, 20px 50%);
      background: 
        linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%, 
        linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
      background-repeat: no-repeat;
    }
    
    .row {
      background: #f8f9fa;
    }
    
    .col {
      padding: 10px;
    }
    <div class="container">
      <div class="row">
        <div class="col">
          Content Here
        </div>
      </div>
    </div>

    Including bootstrap

    body {
      overflow-x: hidden;
    }
    
    .container {
      --w: 540px;
      position: relative;
      margin-top: 40px;
    }
    
    @media (min-width: 768px) {
      .container {
        --w: 720px;
      }
    }
    
    @media (min-width: 992px) {
      .container {
        --w: 960px;
      }
    }
    
    @media (min-width: 1200px) {
      .container {
        --w: 1140px;
      }
    }
    
    .container:before {
      content: '';
      position: absolute;
      top: -20px;
      left: 0;
      width: calc(50vw + var(--w)/2);
      min-width: 100%;
      height: 40px;
      clip-path: polygon(0 0, calc(var(--w) - 20px) 0, var(--w) 50%, 100% 50%, 100% 100%, calc(var(--w) + 20px) 100%, var(--w) 50%, 20px 50%);
      background: 
        linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%, 
        linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
      background-repeat: no-repeat;
    }
    
    .row {
      background: #f8f9fa;
    }
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <div class="container">
      <div class="row">
        <div class="col">
          Content Here
        </div>
      </div>
    </div>