Imposing bleeding circles

I have a green position:relative ring with position:absolute red clone :before and a white clone position:absolute :after spanning both (since they are in the same place and have the same size).

Problem : this is bad for both tested browsers (Chrome and Firefox), where I still see green / red rings under a white mask. Let the green ring with overflow:hidden partially eliminate the problem of removing external blood flow; but the inner border of the bleeding is still there.

Why is this happening and how can I hide the lower circles?

Codepen

 body { background: lavender; } #ring { position: relative; width: 100px; height: 100px; border-radius: 50%; border: 50px solid green; } #ring:before { content: ''; position: absolute; top: -50px; left: -50px; width: 100px; height: 100px; border: 50px solid red; border-radius: 50%; } #ring:after { content: ''; position: absolute; top: -50px; left: -50px; width: 100px; height: 100px; border-radius: 50%; border: 50px solid white; } 
 <div id=ring></div> 

Update: here is a link to the full (not minimum) scenario: Codepen , which only works with the updated Google Chrome at the moment;

+6
source share
3 answers

In a scenario with a radial progress bar, you can use the approach described here: A cycle of indicators of circular percent . Using inline svg and animating the stroke-dasharray attribute for the progress bar.
Adapted to your use case, it might look like this:

 body{background:lavender;} svg{width:200px;height:200px;} 
 <svg viewbox="-2.5 -2.5 105 105"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="#fff"/> <path fill="none" stroke-width="25" stroke="tomato" stroke-dasharray="251.2,0" d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80"> <animate attributeName="stroke-dasharray" from="0,251.2" to="251.2,0" dur="5s"/> </path> </svg> 

Note that in this example, the animation is done using SMIL . But you can also do this with JS as descirbed in the radial response of the execution line.


Previous answer:
If your goal is to remove the bleeding, one solution would be to hide it by making the pseudo-elements wider.
Depending on your actual use case, this solution may be appropriate.

Here is an example:

 body{background:lavender} #ring { position: relative; width: 100px; height: 100px; border-radius: 50%; border: 50px solid green; } #ring:before { content: ''; position: absolute; top: -51px; left: -51px; width: 98px; height: 98px; border: 52px solid red; border-radius: 50%; } #ring:after { content: ''; position: absolute; top: -52px; left: -52px; width: 96px; height: 96px; border-radius: 50%; border: 54px solid white; } 
 <div id="ring"></div> 
+5
source

The cause of the problem is antialiasing in the limit (boundary) pixels. To make the circle border less pixelated, pixels that are only halfway inside the circle are displayed translucent.

The problem is that the circle under the top also displays translucent pixels. (in a different color, of course). Thus, a translucent white hue is obtained on top of the translucent red (which is displayed on top of the translucent green).

The end result is that the pixel is not pure white.

To solve the root of the problem, you need to turn off anti-aliasing that AFAIK cannot be with borders (only text and images are in development). In addition, such a decision would make the circle pretty ugly

To soften it, you can make several hacks, with sizes, shadows, etc.

For another way to solve your original CSS problem (besides the excellent one you already have with SVG) see this answer .

+3
source

On the right side of the next snippet is the result of @ web-tiki svg ring with two clones of the same size / location (but different colors) with anti-aliasing disabled ( shape-rendering="crispEdges" ), as @vals mentioned:

 body { background: lavender; margin: 0; overflow: hidden; } div { width: 200px; height: 200px; display: inline-block; position: relative; } svg { width: 200px; height: 200px; position: absolute; top: 0; left: 0; } span { font-family: arial, sans-serif; text-align: center; position: absolute; left: 0; right: 0; margin: auto; top: 45%; } 
 <div> <svg viewbox="-2.5 -2.5 105 105"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="green"/> </svg> <svg viewbox="-2.5 -2.5 105 105"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="tomato"/> </svg> <svg viewbox="-2.5 -2.5 105 105"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="#fff"/> </svg><span><small>shape-rendering="auto"</small></span> </div><div> <svg viewbox="-2.5 -2.5 105 105" shape-rendering="crispEdges"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="green"/> </svg> <svg viewbox="-2.5 -2.5 105 105" shape-rendering="crispEdges"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="tomato"/> </svg> <svg viewbox="-2.5 -2.5 105 105" shape-rendering="crispEdges"> <circle cx="50" cy="50" r="40" fill="transparent" stroke-width="25" stroke="#fff"/> </svg><span><small>shape-rendering="crispEdges"</small></span> </div> 

Since the OP example uses the :before and :after pseudo-elements, I tried to apply the same shape-rendering="crispEdges" to svg click-to-click, but was unsuccessful in any browser: Link

Source: MDN

+1
source

All Articles