Search code examples
csslinear-gradientscss-shapesradial-gradients

Angled div background with linear and radial gradient


I am currently using CSS3 to make an div with the left side angled like a trapezium using the following CSS adapted from this jsfiddle:

background:linear-gradient(75deg, transparent 75px, #35753f 76px);

I would like to combine the following CSS background with a radial one, to create the effect shown in the image below. However, when I do this, I lose the angled side. What is the best way to combine these two backgrounds?

Here is the radial background:

background:radial-gradient(circle closest-corner at right center, #337540 0%, #003832 100%);

Here is what it should look like:

Desired look

Here is a jsfiddle of the below:

.container {
  width: 1024px;
  margin: 0 auto;
}
.clearfix:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
#top-banner {
  position: relative;
}
#top-banner .container {
  height: 350px;
}
#top-banner #banner-right {
  width: 350px;
  height: 350px;
  background: -moz-linear-gradient(75deg, transparent 75px, #35753f 76px);
  background: -o-linear-gradient(75deg, transparent 75px, #35753f 76px);
  background: -webkit-linear-gradient(75deg, transparent 75px, #35753f 76px);
  background: linear-gradient(75deg, transparent 75px, #35753f 76px);
  position: relative;
  float: right;
}
#top-banner #banner-right:after {
  content: ".";
  display: block;
  height: inherit;
  width: 5000px;
  left: 350px;
  top: 0;
  position: absolute;
  /* IE10 Consumer Preview */
  background-image: -ms-radial-gradient(left center, circle closest-corner, #337540 0%, #003832 100%);
  /* Mozilla Firefox */
  background-image: -moz-radial-gradient(left center, circle closest-corner, #337540 0%, #003832 100%);
  /* Opera */
  background-image: -o-radial-gradient(left center, circle closest-corner, #337540 0%, #003832 100%);
  /* Webkit (Safari/Chrome 10) */
  background-image: -webkit-gradient(radial, left center, 0, left center, 140, color-stop(0, #337540), color-stop(1, #003832));
  /* Webkit (Chrome 11+) */
  background-image: -webkit-radial-gradient(left center, circle closest-corner, #337540 0%, #003832 100%);
  /* W3C Markup, IE10 Release Preview */
  background-image: ;
  z-index: -100;
}
/*#top-banner #banner-right {
	width:350px;
    height:350px;
    background:black;
    position:relative;
	float: right;	
}
#top-banner #banner-right:before {
	content:"";
    position:absolute;
    top:0;
    left:0;
    width: 0; 
    height: 0; 
    border-bottom: 350px solid white; 
    border-right: 40px solid transparent; 
}*/

#top-banner .slider {
  float: left;
  height: 350px;
  width: 100px;
  background-color: black;
  background-size: cover;
  shape-outside: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
<div id="top-banner">
  <div class="container clearfix">
    <div id="banner-right">
    </div>
    <div class="slider">
      <img src="http://1.bp.blogspot.com/-9aQmrN3-xpQ/TuYsXHQygrI/AAAAAAAAAtw/cEmz4PgEQdQ/s1600/r-NEW-SPECIES-MEKONG-DELTA-huge.jpg" height="350" alt="banner-1" />
    </div>
  </div>
</div>


Solution

  • Angled div - 2 methods

    The angle is created with transform: rotate and not the linear-gradient.

    #1 - Rotated :before with translate 3d

    In this example, translate3d(0px,0px,1px) is used to eliminate the jagged edge of the rotated element. More information here. I was reminded about this technique from this answer dealing with a similar rendering problem.

    As this is a hack that should be used sparingly, their is an alternative way to mask this edge without it in the second example.

    • Rotate a pseudo element, :before, of the div. This will create our angled edge

    • The :before gets an appropriate percentage height, width: 100px and is positioned appropriately

    • The parent div is given overflow: hidden to cut off the background cleanly

    • Create a second pseudo element, :after, to extend the background to the edge of the viewport.

    • The gradient background is applied to :after

    • The :before pseudo element is given a solid background the same color as the edge of the gradient to blend

    • The :before and :after pseudo elements are given z-index: 1

    • Elements that will sit above the "background" will need position: relative and z-index: 2 to push them above it. (Like the paragraph in the example below)

    Example

    The linear-gradient on the body demonstrates that the div can be placed over any background.

    body {
      background: linear-gradient(#000 0%, #FFF 100%) no-repeat;
      margin: 0;
    }
    div {
      position: relative;
      height: 350px;
      overflow: hidden;
      padding-left: 100px;
      min-width: 500px;
    }
    div:before {
      content: '';
      display: block;
      position: absolute;
      height: 120%;
      width: 90px;
      top: -10%;
      left: 90px;
      background: #003832;
      transform:  translate3d(0px,0px,1px) rotate(-15deg);
      z-index: 1;
    }
    div:after {
      content: '';
      display: block;
      position: absolute;
      height: 120%;
      width: 100%;
      top: -10%;
      left: 135px;
      background: radial-gradient(circle closest-corner at 50% 50%, #33753E 0%, #003832 80%);
      z-index: 1;
    }
    p {
      color: #FFF;
      left: 10px;
      position: relative;
      z-index: 2;
    }
    <div>
      <p>This is some text</p>
    </div>


    #2 - Rotated :before and :after without translate 3d

    • Rotate a pseudo element, :before, of the div

    • Apply the background to the pseudo element

    • The pseudo element gets height: 200% and width: 200% and is positioned appropriately

    • The parent div is given overflow: hidden to cut off the gradient cleanly and the rotated pseudo element becomes the background

    • A second pseudo element, :after, is used to help mask the jagged edge with a box-shadow (the left edge is jagged at all rotations that are not 45deg increments)

    • The :before and :after pseudo elements are given z-index: 1

    • Elements that will sit above the "background" will need position: relative and z-index: 2 to push them above it. (Like the paragraph in the example below)

    Example 1

    body {
      background: linear-gradient(#000 0%, #FFF 100%) no-repeat;
    }
    div {
      position: relative;
      width: 500px;
      height: 350px;
      overflow: hidden;
      padding-left: 100px;
    }
    div:before,
    div:after {
      content: '';
      display: block;
      position: absolute;
      height: 200%;
      width: 200%;
      top: -220px;
      left: 90px;
      background: radial-gradient(circle closest-corner at 20% 50%, #33753E 0%, #003832 100%);
      transform: rotate(-15deg);
      z-index: 1;
    }
    div:after {
      top: -220px;
      left: 92px;
      box-shadow: 0 0 2px 2px #003832;
    }
    p {
      color: #FFF;
      z-index: 2;
      position: relative;
    }
    <div>
      <p>This is some text</p>
    </div>

    Example 2 - extended

    body {
      background: linear-gradient(#000 0%, #FFF 100%) no-repeat;
      margin: 0;
    }
    div {
      position: relative;
      height: 350px;
      overflow: hidden;
      padding-left: 100px;
      max-width: 1600px;
    }
    div:before,
    div:after {
      content: '';
      display: block;
      position: absolute;
      height: 300%;
      width: 300%;
      top: -200%;
      left: 90px;
      background: radial-gradient(circle closest-corner at 20% 50%, #33753E 0%, #003832 100%);
      transform: rotate(-15deg);
      z-index: 1;
    }
    div:after {
      left: 92px;
      box-shadow: 0 0 2px 2px #003832;
    }
    p {
      color: #FFF;
      z-index: 2;
      position: relative;
      left: 80px;
    }
    <div>
      <p>This is some text</p>
    </div>