简体   繁体   中英

HTML css linear-gradient not working as expected

I'm just working with linear-gradient in css, btw the generated gradient effect isn't same as the designs. I have never faced this problem in any Android, iOS, React Native or HTML5 canvas yet, but only on css.

.gradient {
  background-image: linear-gradient(to right top, red, blue);
}

I have made a fiddle for showing the differences between css's linear-gradient and canvas's create createLinearGradient . Please check this fiddle link .

例

The upper is css gradient and lower is canvas one. As you can see the canvas's createLinearGradient working well as expected, but on the css the same-color-line (yellow line in above pic) isn't vertical of the gradient's direction, rather looks as the another diagonal of the element. Is there any reason why is it in css?

This is by design. You can read more about here: https://drafts.csswg.org/css-images-3/#linear-gradients .

If the argument instead specifies a corner of the box such as to top left , the gradient line must be angled such that it points into the same quadrant as the specified corner , and is perpendicular to a line intersecting the two neighboring corners of the gradient box. This causes a color-stop at 50% to intersect the two neighboring corners.

Basically, when using such keywords you will have a kind of stretched gradient going from corners and you loss the perpendicular feature with the diagonal.

 .child { position:relative; width: 100px; height: 100px; border: 1px solid red; background-image: linear-gradient(to top right, red 50%, blue 0); } .child.alt { width:200px; } .child:before { content:""; position:absolute; top:0; left:0; right:0; bottom:0; background:linear-gradient(to top left,transparent calc(50% - 5px),green,transparent calc(50% + 5px) ); } 
 this one is good because it's a square <div class="child"></div> but not this one <div class="child alt"></div> 

If you want to have the second output you need to use explicit angle and find the one that will make your gradient line the same as you diagonal line and for this you need to consider the angle equal to arctang(width/height)

In your case it will be arctang(300/75) = arctang(4) = 75.69deg . Since you are using JS you can easily do this calculation.

 var c = document.getElementById("canvas"); var ctx = c.getContext("2d"); var grd = ctx.createLinearGradient(0, 75, 300, 0); grd.addColorStop(0, "red"); grd.addColorStop(1, "blue"); ctx.fillStyle = grd; ctx.fillRect(0, 0, 300, 75); 
 .parent { width: 300px; height: 300px; align-items: center; justify-content: center; display: flex; flex-direction: column; background-color: #6EE2F5; } .child { width: 300px; height: 75px; border: 1px solid red; background-image: linear-gradient(75.69deg, red, blue); } #canvas { width: 300px; height: 75px; border: 1px solid green; } 
 <div class="parent"> <div class="child"></div> <canvas id="canvas" width=300 height=75/> </div> 

Here is an interactive Demo

 var c = document.getElementById("canvas"); var ctx = c.getContext("2d"); function update() { var H = $('[name=h]').val(); var W = $('[name=w]').val(); $('.child').css('height',H); $('.child').css('width',W); $('canvas').attr("width", W); $('canvas').attr("height", H); var angle = Math.atan(W/H) $('.child').css("--a", (angle * 180 / Math.PI)+"deg"); var grd = ctx.createLinearGradient(0, H, W, 0); grd.addColorStop(0.4, "red"); grd.addColorStop(0.6, "blue"); ctx.fillStyle = grd; ctx.fillRect(0, 0, W, H); } $('input').change(update); update(); 
 .child { border: 1px solid; background-image: linear-gradient(var(--a), red 40%, blue 60%); } #canvas { border: 1px solid green; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> W: <input type="number" name="w" step="1" value="300"> H: <input type="number" name="h" step="1" value="75"> <div class="child"></div> <canvas id="canvas" width=300 height=75/> 

Just replace to right top to to right . If you set it to to right top there is a certain degree applied to linear-gradient() as it takes the bottom left as the starting point and extends up-to right top corner of the rectangle.

 var c = document.getElementById("canvas"); var ctx = c.getContext("2d"); var grd = ctx.createLinearGradient(0, 75, 300, 0); grd.addColorStop(0, "red"); grd.addColorStop(1, "blue"); ctx.fillStyle = grd; ctx.fillRect(0, 0, 300, 75); 
 .parent { width: 300px; height: 300px; align-items: center; justify-content: center; display: flex; flex-direction: column; background-color: #6EE2F5; } .child { width: 300px; height: 75px; border: 1px solid red; background-image: linear-gradient(to right, red, blue); } #canvas { width: 300px; height: 75px; border: 1px solid green; } 
 <div class="parent"> <div class="child"></div> <canvas id="canvas" width=300 height=75/> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM