This is the result of the rasterization strategy used, and there is no easy fix.
One fix is ββto stroke the triangles, but with a very thin stroke. For example, here is one in 0.2px increments:
Alternatively, you can increase your graphics and display the stroked versions under the actual content.
<g id="underlay"> <polygon class="t1" points="10,10 10,390 390,390 10,10" /> <polygon class="t2" points="10,10 390,390 390,10 10,10" /> </g><g id="content"> <polygon class="t1" points="10,10 10,390 390,390 10,10" /> <polygon class="t2" points="10,10 390,390 390,10 10,10" /> </g>
.t1 { fill:rgb(140,90,90); stroke:rgb(140,90,90) } .t2 { fill:rgb(90,140,90); stroke:rgb(90,140,90) } #underlay polygon { stroke-width:1px } #content polygon { stroke:none }
(You can do this automatically through JS if you are working in a user agent such as a web browser where it is available.)
This demonstration clearly shows the problem.
<svg xmlns="http://www.w3.org/2000/svg"> <g id="aligned"> <polygon class="a" points="10,10 10,100 100,100, 100,10" /> <polygon class="b" points="100,10 100,100 200,100, 200,10" /> </g> <g id="shifted" transform="translate(0.5,110)"> <polygon class="a" points="10,10 10,100 100,100, 100,10" /> <polygon class="b" points="100,10 100,100 200,100, 200,10" /> </g> </svg>
Here we have two vertical edges exactly on top of each other. In the first case, they are precisely aligned with the pixel grid. The left form fills all the pixels to the left exactly, the correct form fills all the pixels to the right exactly and does not fill in the blank.
In the second case, however, both shapes are located directly between the pixel border. Since our shape overlaps these pixels by 50%, anti-aliasing tells us in this case that we need to fill the pixels that we overlap at exactly 50% opacity. Thus, the left shape fills this common column of pixels with an opacity of 50%, and then the correct form fills the common column with pixels, which are an additional opacity of 50%.
Unfortunately, opacity is created by multiplying rather than adding. Pixel rgba(0,0,0,0.5) overtop rgba(0,0,0,0.5) creates rgba(0,0,0,0.75) , NOT rgba(0,0,0,1) .
This is the essence of the problem, and it is not specific to SVG. For example, see
When you select an infinitely accurate vector image in a grid with a finite pixel, information is lost. You need to hack it.