For reference, see this question: Chrome radial css gradient smoothness.
The OP is having trouble with the smoothness of the gradient, but from the discussion it seems that that's only when using alpha transparency.
Here's the gradient I'm using:
div {
background: radial-gradient(
#000 30%,
transparent 30%, transparent 40%,
#000 40%, #000 60%,
transparent 60%
);
}
As you can see, it's using hard stops (so no color transition) and no rgba (so no alpha either). Still, in Chrome (tested in 23 on Windows 7) it's rendered extremely pixelated:
Is this just the way Chrome handles these things, or am I missing something? Is there anything that can be done to smoothen it out a bit (short of using an image, obviously)?
Here's the fiddle: http://jsfiddle.net/wARGc/
Update: I filed a bug report for this.
It is a rendering problem by Chrome, you can create the smoothing yourself by adjusting the shape slightly. See my update to your fiddle
http://jsfiddle.net/jamestoone/XU7jB/
div {
width: 100px;
height: 100px;
background: radial-gradient(#000 30%, transparent 30%, transparent 40%, #000 40%, #000 60%, transparent 60%);
}
div.new {
background: radial-gradient(#000000 30%, transparent 32%, transparent 38%, #000000 40%, #000000 60%, transparent 62%) repeat scroll 0 0 transparent;
height: 100px;
width: 100px;
}
When building a reusable code that will take different sizes, playing with percentages is not an option because it can fit only a single size of the gradient container, and will distort a smaller or larger one.
Yet, I found that setting explicitly a distance of 1px for the gradient to be smooth between each gradient step, solves completely the problem.
So for each step, instead of setting twice the same percentage, like 40%, just give one of them a pixel more space: calc(40% - 1px).
Demo:
http://jsfiddle.net/zgmfe9v2/
Smooth radial gradient
Related
I'm looking to give an element a background with repeating, 1px wide diagonal stripes. It seems that repeating-linear-gradient should be able to do this, but when rendered in Safari this:
background-image: repeating-linear-gradient(
45deg, black, black 1px, transparent 1px, transparent 3px
);
Looks like this:
#thing {
height: 200px;
background-image: repeating-linear-gradient( 45deg, black, black 1px, transparent 1px, transparent 3px);
}
<div id="thing"></div>
It looks as though the browser's doing a poor job of aliasing, resulting in an uneven banding pattern. Any ideas on how I might be able to fix this, or to accomplish what I'm looking to do another way?
A little more elabourate explanation of the conundrum here: according to the Pythagoras principle (and its triples), it is impossible to have a square (which is simply two right triangles fit together) whose sides are integers that has a diagonal whose length is an integer number, too.
This is because 12 + 12 = sqrt(2)2. Since the square root of 2 is an irrational number, all derivatives of this (a square of whatever side length that is an integer number) will have a diagonal of irrational length.
This is the closest I can get — specify an integer square, but the stripes will be of non-integer width: http://jsfiddle.net/teddyrised/SR4gL/2/
#thing {
height: 200px;
background-image: linear-gradient(-45deg, black 25%, transparent 25%, transparent 50%, black 50%, black 75%, transparent 75%, transparent);
background-size: 4px 4px;
}
The side lengths of the imaginary square, tiled over your element, will be 4px wide. This means the diagonal length would be sqrt(32), and the stripe will be 1.414...px when measured diagonally across (close to 1, but not quite there), or 2px wide when measured parallel to the x or y axis.
Many thanks to Terry for his suggested approach of using a standard linear-gradient with percentages and a background-size. With a bit of playing around, I have managed to obtain the exact gradient I was looking for:
background-image: linear-gradient(
to right top,
transparent 33%,
black 33%,
black 66%,
transparent 66%
);
background-size: 3px 3px;
I'm looking to give an element a background with repeating, 1px wide diagonal stripes. It seems that repeating-linear-gradient should be able to do this, but when rendered in Safari this:
background-image: repeating-linear-gradient(
45deg, black, black 1px, transparent 1px, transparent 3px
);
Looks like this:
#thing {
height: 200px;
background-image: repeating-linear-gradient( 45deg, black, black 1px, transparent 1px, transparent 3px);
}
<div id="thing"></div>
It looks as though the browser's doing a poor job of aliasing, resulting in an uneven banding pattern. Any ideas on how I might be able to fix this, or to accomplish what I'm looking to do another way?
A little more elabourate explanation of the conundrum here: according to the Pythagoras principle (and its triples), it is impossible to have a square (which is simply two right triangles fit together) whose sides are integers that has a diagonal whose length is an integer number, too.
This is because 12 + 12 = sqrt(2)2. Since the square root of 2 is an irrational number, all derivatives of this (a square of whatever side length that is an integer number) will have a diagonal of irrational length.
This is the closest I can get — specify an integer square, but the stripes will be of non-integer width: http://jsfiddle.net/teddyrised/SR4gL/2/
#thing {
height: 200px;
background-image: linear-gradient(-45deg, black 25%, transparent 25%, transparent 50%, black 50%, black 75%, transparent 75%, transparent);
background-size: 4px 4px;
}
The side lengths of the imaginary square, tiled over your element, will be 4px wide. This means the diagonal length would be sqrt(32), and the stripe will be 1.414...px when measured diagonally across (close to 1, but not quite there), or 2px wide when measured parallel to the x or y axis.
Many thanks to Terry for his suggested approach of using a standard linear-gradient with percentages and a background-size. With a bit of playing around, I have managed to obtain the exact gradient I was looking for:
background-image: linear-gradient(
to right top,
transparent 33%,
black 33%,
black 66%,
transparent 66%
);
background-size: 3px 3px;
This is how it looks in Chrome :
and this is a screenshot from Firefox :
It is clear from the screenshots that the gradient boundaries are jagged in Chrome. How can I make them smooth?
Here is my gradient in case that matters:
background-image: linear-gradient(45deg, red 25%, transparent 25%, transparent 75%, red 75%, red),
linear-gradient(-45deg, red 25%, transparent 25%, transparent 75%, red 75%, red);
background-size: 60px 60px;
background-position:0 0, 30px 30px;
EDIT:
Changing the background-size to 40px makes the gradient smooth but I want it to be smooth at all sizes.
Let me know if I need to provide additional code. Thanks.
Reason:
As I had described in comments, when the end point of one color is the start point of another (that is, a hard-stop gradient), the change of colors is sudden and such a sudden change at an angle is known for producing rough edges even in other browsers (which has maybe got fixed by now). Giving a gap between end point of one color and start of the next produces a smoother change of color and thus minimises rough edges.
Not much experimentation is required for this (or trial and error), a 1 or 2% gap is almost always sufficient.
Workaround:
Changing the color stop points to produce a more smooth change of colors instead of giving it a hard stop seems to be helping.
body {
background-image: linear-gradient(45deg, red 24%, transparent 26%, transparent 74%, red 76%, red), linear-gradient(-45deg, red 24%, transparent 26%, transparent 74%, red 76%, red);
background-size: 60px 60px;
background-position: 0 0, 30px 30px;
}
It is produced by a bug in chrome, that treats that kind of backgrounds as a 3D element. You can avoid that writing a border (it converts to flat the element), or with this property.
transform-style: preserve-3d;
OR
-webkit-backface-visibility: hidden; /* Webkit specifically! */
The border solution
border: 1px solid #fff;
See more about this bug:
http://adrianroselli.com/2014/10/linear-gradient-problems-in-chrome.html
Try this on the elements the gradient is in.
transform: translateZ(0);
It smoothens the gradient. See below.
td.normal {
width: 50px;
height: 50px;
background-image: linear-gradient(to top right, red 25%, transparent 25%, transparent 75%, red 75%, red),
linear-gradient(to top right, red 25%, transparent 25%, transparent 75%, red 75%, red);
}
td.smooth {
transform: translateZ(0);
}
<table>
<tr>
<td class="normal"></td>
<td class="normal"></td>
<td class="normal smooth"></td>
<td class="normal smooth"></td>
</tr>
</table>
Try adding backface-visibility: hidden
This happens sometimes when we ask a browser to skew an image.
This maybe a simple question, but I didn't find a clear explanation for this.
I know in css3, the syntax for setting up a radial gradient is as following:
radial-gradient(shape size at position, start-color, ..., last-color);
If I set sth like this:
radial-gradient(circle at 50% 50%, #f00 50%, transparent 50%);
I thought the red circle will be positioned in the center, and the radius of the red circle would be 50%*containerWidth(or containerHeight). i.e. the circle will just touch the edge of the outer container, but what I got is not, please see the demo:
DEMO ON JSFIDDLE
So can anybody help to explain what's the exact meaning of the 50% here please(#f00 50%)? Many thanks.
based on #'s answer:
the 50% is refered to the diagonal from the center to the square
corner
I also put several demo here:
MORE DEMO ON JSFIDDLE
Because under the default option, the percentage is between the gradient stop radius and the diagonal, so when the ratio is 2**0.5/2≈0.707, the circle will touch the edges of the square.
The 50% in the color stop depends on the size of the image that is being generated.
And the size of the image depends on your choice between the 4 posible values for this property.
If you do not set it, the farthest-corner option is choosen (so, in your example, the 50% is refered to the diagonal from the center to the square corner
div{
width:100px;
height:160px;
border:solid 1px blue;
display: inline-block;
}
.gradient1{
background-image: radial-gradient(circle closest-side at 50% 40%, #f00 50%, transparent 50%);
}
.gradient2{
background-image: radial-gradient(circle closest-corner at 50% 40%, #f00 50%, transparent 50%);
}
.gradient3{
background-image: radial-gradient(circle farthest-side at 50% 40%, #f00 50%, transparent 50%);
}
.gradient4{
background-image: radial-gradient(circle farthest-corner at 50% 40%, #f00 50%, transparent 50%);
}
<div class="gradient1"></div>
<div class="gradient2"></div>
<div class="gradient3"></div>
<div class="gradient4"></div>
center 50% 50% places the gradient center at the center of the container, #f00 50% colors the gradient with red color up to 50% of radius the rest 50% being transparent, exactly what you see in jsfiddle. In other words the percent refers to the size (i.e radius) of the gradient object (which in the case of a radial gradient it is the radius, as it unfolds from the center outwards).
https://developer.mozilla.org/en-US/docs/Web/CSS/radial-gradient
I'm trying to create a grid in pure CSS using background-image and -webkit-linear-gradient. I have the spacing and the tiling working fine, but for a reason I can't figure out, the vertical lines are coming out as #B8B8B9 instead of #E3E4E5 like I specify. Any ideas?
JSFiddle: http://jsfiddle.net/2faSt/
CSS:
.grid {
position: absolute;
width: 100%;
height: 500px;
background-image: -webkit-linear-gradient(0deg, #e3e4e5 0px, transparent 1px, transparent 15px, #e3e4e5 16px, transparent 16px, transparent 99px, #e3e4e5 100px, #ffffff 100px), -webkit-linear-gradient(90deg, transparent 20px, #e3e4e5 20px);
background-size: 111px 21px;
}
If you want to get really the color that you specify, you should set 2 color stops with the same color, separated by at least 1 px.
Otherwise, you set only the point of gradient change, but it is already changing to transparent, even in the same pixel
And, even it is non intuitive, transparent if black transparent (rgba (0,0,0,1))
See this fiddle
There, you have this CSS:
#one {
background: linear-gradient(90deg, #e3e4e5, transparent);
}
#two {
background: linear-gradient(90deg, #e3e4e5, rgba(255, 255, 255, 1));
}
In the first div (The same color stops that in your question), you can see that in the middle of the transition the color is darker than at the beginning.
As a comparison, in the second you can see what probably you intended, make the transition to white transparent.