HitomiTenshi HitomiTenshi - 7 months ago 16
HTML Question

linear-gradient triangle with 2 gradient levels (color stops)

I'm currently displaying 2 triangles on the bottom of my page, one on the left and one on the right. The right triangle is transparent. Both triangles have one color.

I want the

triangle-bottom-right
to have an additional gradient level (additional color stops).

It should go from left to right, start with
rgba(70, 70, 70, 0.15)
and end with
rgba(70, 70, 70, 0)
. The target browser is Chrome (running through Electron).

My CSS:

.triangle-footer {
position: relative;
bottom: 0px;
height: 176px;
width: 100%;
}
.triangle-bottom-left {
position: absolute;
width: 40%;
height: 100%;
left: 0px;
bottom: 0px;
background: linear-gradient(to right top, rgba(94, 194, 82, 100) 50%, rgba(255, 255, 255, 0) 50%);
}
.triangle-bottom-right {
position: absolute;;
width: 125%;
height: 140%;
right: 0px;
bottom: 0px;
background: linear-gradient(to left top, rgba(70, 70, 70, 0.15) 50%, rgba(255, 255, 255, 0) 50%);
}


My HTML:

<div class="ui fixed bottom sticky triangle-footer">
<div class="triangle-bottom-left"></div>
</div>

<div class="ui fixed bottom sticky triangle-footer">
<div class="triangle-bottom-right"></div>
</div>


(Using Semantic-UI for the bottom stickyness)

Live Example: http://jsfiddle.net/fu2dhfdv/1/

Expected output:
gradient

Answer

As far as I am aware this cannot be done using linear-gradient background image alone because the right triangle itself shows up as a triangle only because it is transparent for 50% and filled for rest. If we put another layer of left-to-right gradient on top of this layer then the gradient will show up for the entire square area of triangle-bottom-right (or) if we put the left-to-right gradient on bottom of this layer then also it will show up for the entire square area because the top half of gradient that produces the triangle is transparent. So, the only choices are (a) to make top half as "white" and place the 2nd gradient below it or (b) use a mask or clip-path to hide the top half.

Using SVG Mask:

Since neither CSS mask nor CSS clip-path has good browser support at present. The best option is to make use of inline SVG for the mask like in the below snippet.

.triangle-footer {
  position: relative;
  bottom: 0px;
  height: 176px;
  width: 100%;
}
.triangle-bottom-left {
  position: absolute;
  width: 40%;
  height: 100%;
  left: 0px;
  bottom: 0px;
  background: linear-gradient(to right top, rgba(94, 194, 82, 100) 50%, rgba(255, 255, 255, 0) 50%);
}
.triangle-bottom-right {
  position: absolute;
  width: 125%;
  height: 140%;
  right: 0px;
  bottom: 0px;
}
svg {
  position: relative;
  right: 0px;
  bottom: 0px;
  width: 100%;
  height: 100%;
}
polygon#right-triangle {
  fill: url(#grad);
  mask: url(#triangle);
}
<script src="http://semantic-ui.com/dist/semantic.js"></script>
<link href="http://semantic-ui.com/dist/semantic.css" rel="stylesheet" />
<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-left"></div>
</div>

<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-right">
    <svg viewBox="0 0 100 100" preserveAspectRatio="none">
      <defs>
        <linearGradient id="grad">
          <stop offset="0%" stop-color="rgba(70, 70, 70, 0.35)" />
          <stop offset="100%" stop-color="rgba(255, 255, 255, 0)" />
        </linearGradient>
        <mask id="triangle">
          <polygon points="0,0 100,0 100,100 0,100" fill="black" />
          <polygon points="0,90 0,100 100,100 100,0" fill="white" />
        </mask>
      </defs>
      <polygon points="0,0 100,0 100,100 0,100" id="right-triangle" />
    </svg>
  </div>
</div>


Using SVG Polygon: (can be done with path element also)

This can also be done using one SVG polygon element instead of a mask like in the below snippet. I will leave it to you to choose one :)

.triangle-footer {
  position: relative;
  bottom: 0px;
  height: 176px;
  width: 100%;
}
.triangle-bottom-left {
  position: absolute;
  width: 40%;
  height: 100%;
  left: 0px;
  bottom: 0px;
  background: linear-gradient(to right top, rgba(94, 194, 82, 100) 50%, rgba(255, 255, 255, 0) 50%);
}
.triangle-bottom-right {
  position: absolute;
  width: 125%;
  height: 140%;
  right: 0px;
  bottom: 0px;
}
svg {
  position: relative;
  right: 0px;
  bottom: 0px;
  width: 100%;
  height: 100%;
}
polygon#right-triangle {
  fill: url(#grad);
}
<script src="http://semantic-ui.com/dist/semantic.js"></script>
<link href="http://semantic-ui.com/dist/semantic.css" rel="stylesheet" />
<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-left"></div>
</div>

<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-right">
    <svg viewBox="0 0 100 100" preserveAspectRatio="none">
      <defs>
        <linearGradient id="grad">
          <stop offset="0%" stop-color="rgba(70, 70, 70, 0.35)" />
          <stop offset="100%" stop-color="rgba(255, 255, 255, 0)" />
        </linearGradient>
      </defs>
      <polygon points="0,90 0,100 100,100 100,0" id="right-triangle" />
    </svg>
  </div>
</div>


Using CSS Masks: (best for you as Chrome is the only target)

Since you've indicated that the target browser is only Chrome and given that CSS mask is supported in it, you can also use the -webkit-mask-image property with a linear-gradient like in below snippet. I have listed it as last only because it is least recommended for any other user viewing this thread with a different browser requirement.

.triangle-footer {
  position: relative;
  bottom: 0px;
  height: 176px;
  width: 100%;
}
.triangle-bottom-left {
  position: absolute;
  width: 40%;
  height: 100%;
  left: 0px;
  bottom: 0px;
  background: linear-gradient(to right top, rgba(94, 194, 82, 100) 50%, rgba(255, 255, 255, 0) 50%);
}
.triangle-bottom-right {
  position: absolute;
  width: 125%;
  height: 140%;
  right: 0px;
  bottom: 0px;
  background: linear-gradient(to right, rgba(70, 70, 70, 0.15), rgba(255, 255, 255, 0));
  -webkit-mask-image: linear-gradient(to top left, white 50%, transparent 50%);
}
<script src="http://semantic-ui.com/dist/semantic.js"></script>
<link href="http://semantic-ui.com/dist/semantic.css" rel="stylesheet" />
<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-left"></div>
</div>

<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-right">
  </div>
</div>


Using CSS Clip Path: (again useful since Chrome is the only target)

It can be done with CSS clip-path also like in the below snippet. The right-bottom element is clipped to the required triangle-ish shape and a left-to-right gradient is applied to it.

.triangle-footer {
  position: relative;
  bottom: 0px;
  height: 176px;
  width: 100%;
}
.triangle-bottom-left {
  position: absolute;
  width: 40%;
  height: 100%;
  left: 0px;
  bottom: 0px;
  background: linear-gradient(to right top, rgba(94, 194, 82, 100) 50%, rgba(255, 255, 255, 0) 50%);
}
.triangle-bottom-right {
  position: absolute;
  width: 125%;
  height: 140%;
  right: 0px;
  bottom: 0px;
  background: linear-gradient(to right, rgba(70, 70, 70, 0.15), rgba(255, 255, 255, 0));
  -webkit-clip-path: polygon(0% 90%, 0% 100%, 100% 100%, 100% 0%);
}
<script src="http://semantic-ui.com/dist/semantic.js"></script>
<link href="http://semantic-ui.com/dist/semantic.css" rel="stylesheet" />
<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-left"></div>
</div>

<div class="ui fixed bottom sticky triangle-footer">
  <div class="triangle-bottom-right">
  </div>
</div>