SVG makes white lines in the browser

svg rendering
illustrator white lines between shapes
svg image-rendering
svg precision
svg pixel alignment
svg code to image
svg aliasing firefox
svg images

I made a 24x24-pixel logo. It consists of polygons that stand side by side.

I'm showing this in various sizes on my web page in the range of 40 pixels and 24 pixels.

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="katman_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<polygon points="6,20 4,16 2,20 "/>
<polygon points="4,16 2,12 0,16 "/>
<polygon points="6,12 4,8 2,12 "/>
<polygon points="8,8 6,4 4,8 "/>
<polygon points="10,12 8,8 6,12 "/>
<polygon points="14,12 12,8 10,12 "/>
<polygon points="18,12 16,8 14,12 "/>
<polygon points="22,12 20,8 18,12 "/>
<polygon points="12,16 10,12 8,16 "/>
<polygon points="20,16 18,12 16,16 "/>
<polygon points="4,16 6,20 8,16 "/>
<polygon points="2,12 4,16 6,12 "/>
<polygon points="0,16 2,20 4,16 "/>
<polygon points="4,8 6,12 8,8 "/>
<polygon points="6,4 8,8 10,4 "/>
<polygon points="8,8 10,12 12,8 "/>
<polygon points="16,8 18,12 20,8 "/>
<polygon points="18,12 20,16 22,12 "/>
<polygon points="10,12 12,16 14,12 "/>
<polygon points="8,16 10,20 12,16 "/>
<polygon points="16,16 18,20 20,16 "/>
<polygon points="20,16 22,20 24,16 "/>
<polygon points="10,20 8,16 6,20 "/>
<polygon points="14,20 12,16 10,20 "/>
<polygon points="18,20 16,16 14,20 "/>
<polygon points="22,20 20,16 18,20 "/>
</svg>

But white lines form between svg elements... For example:

Original svg file: bz.svg

I can't combine them because in some cases I color each one separately. How can I fix this?

shape-rendering will help in most cases. But it is not guaranteed. You still might find the odd white pixel. Plus it has the disadvantage that you lose the anti-aliasing on the outside edges. Leaving the sloped edges "jaggy".

Another solution, as others have suggested, is to add a thin stroke to your shapes. The width that that stroke needs to be will depend on the slope of the join line, and the 2D rendering engine that the browser uses.

A third solution is to merge adjacent triangles if they are the same colour. You can write a little javascript to do the merging. You probably don't have to worry about the adjacent triangles that have different colours. If the colours are different enough, the slight white line probably won't be noticeable.

A fourth option is similar. Instead of merging triangles, look for edges of triangles that later triangles abut against, and give those sides a "bulge". For example by using an extra point halfway along that side, that sticks out a bit. The idea is that the earlier triangle extends under the later one.

One final solution, I can think of, is to run a filter over the shape to remove the anti-aliasing artifacts.

The ideal filter for this would be a median filter, But unfortunately, SVG/CSS has no median filter. Michael Mullany created a very clever hack that simulates a median filter using a combination of the filter primitives that are available.

<svg version="1.1" id="katman_1" viewBox="0 0 24 24">
  <defs>
    <filter id="median">
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 1 0 0 0 0 0" result="1" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="1 0 0 0 0 0 0 0 0" result="2" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 1 0 0 0 0 0 0 0" result="3" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 1 0 0 0 0 0 0" result="4" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 0 0 1 0 0 0" result="5" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 0 0 0 0 0 1" result="6" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 0 0 0 0 1 0" result="7" preserveAlpha="true"/>
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 0 0 0 1 0 0" result="8" preserveAlpha="true" />
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="0 0 0 0 1 0 0 0 0" result="9" preserveAlpha="true" />
      <feBlend in="1" in2="2" mode="lighten" result="a1"/>
      <feBlend in="1" in2="2" mode="darken" result="a2"/>
      <feBlend in="a2" in2="3" mode="lighten" result="a3"/>
      <feBlend in="a2" in2="3" mode="darken" result="a4"/>
      <feBlend in="a4" in2="4" mode="lighten" result="a5"/>
      <feBlend in="a4" in2="4" mode="darken" result="a6"/>
      <feBlend in="a6" in2="5" mode="lighten" result="a7"/>
      <feBlend in="a6" in2="5" mode="darken" result="a8"/>
      <feBlend in="a8" in2="6" mode="lighten" result="a9"/>
      <feBlend in="a8" in2="6" mode="darken" result="a10"/>
      <feBlend in="a10" in2="7" mode="lighten" result="a11"/>
      <feBlend in="a10" in2="7" mode="darken" result="a12"/>
      <feBlend in="a12" in2="8" mode="lighten" result="a13"/>
      <feBlend in="a13" in2="8" mode="darken" result="a14"/>
      <feBlend in="1" in2="2" mode="lighten" result="a15"/>
      <feBlend in="1" in2="2" mode="darken" result="a16"/>    
      <feBlend in="a1" in2="a3" mode="lighten" result="b1"/>
      <feBlend in="a1" in2="a3" mode="darken" result="b2"/>
      <feBlend in="b2" in2="a5" mode="lighten" result="b3"/>
      <feBlend in="b2" in2="a5" mode="darken" result="b4"/>
      <feBlend in="b4" in2="a7" mode="lighten" result="b5"/>
      <feBlend in="b4" in2="a7" mode="darken" result="b6"/>
      <feBlend in="b6" in2="a9" mode="lighten" result="b7"/>
      <feBlend in="b6" in2="a9" mode="darken" result="b8"/>
      <feBlend in="b8" in2="a11" mode="lighten" result="b9"/>
      <feBlend in="b8" in2="a11" mode="darken" result="b10"/>
      <feBlend in="b10" in2="a13" mode="lighten" result="b11"/>
      <feBlend in="b10" in2="a13" mode="darken" result="b12"/>
      <feBlend in="b12" in2="a15" mode="lighten" result="b13"/>
      <feBlend in="b12" in2="a15" mode="darken" result="b14"/>
      <feBlend in="b1" in2="b3" mode="lighten" result="c1"/>
      <feBlend in="b1" in2="b3" mode="darken" result="c2"/>
      <feBlend in="c2" in2="b5" mode="lighten" result="c3"/>
      <feBlend in="c2" in2="b5" mode="darken" result="c4"/>
      <feBlend in="c4" in2="b7" mode="lighten" result="c5"/>
      <feBlend in="c4" in2="b7" mode="darken" result="c6"/>
      <feBlend in="c6" in2="b9" mode="lighten" result="c7"/>
      <feBlend in="c6" in2="b9" mode="darken" result="c8"/>
      <feBlend in="c8" in2="b11" mode="lighten" result="c9"/>
      <feBlend in="c8" in2="b11" mode="darken" result="c10"/>
      <feBlend in="c10" in2="b13" mode="lighten" result="c11"/>
      <feBlend in="c10" in2="b13" mode="darken" result="c12"/>
      <feBlend in="c1" in2="c3" mode="lighten" result="d1"/>
      <feBlend in="d1" in2="c3" mode="darken" result="d2"/>
      <feBlend in="d2" in2="c5" mode="lighten" result="d3"/>
      <feBlend in="d2" in2="c5" mode="darken" result="d4"/>
      <feBlend in="d4" in2="c7" mode="lighten" result="d5"/>
      <feBlend in="d4" in2="c7" mode="darken" result="d6"/>
      <feBlend in="d6" in2="c9" mode="lighten" result="d7"/>
      <feBlend in="d6" in2="c9" mode="darken" result="d8"/>
      <feBlend in="d8" in2="c11" mode="lighten" result="d9"/>
      <feBlend in="d8" in2="c11" mode="darken" result="d10"/>
      <feBlend in="d1" in2="d3" mode="darken" result="e1"/>
      <feBlend in="e1" in2="d5" mode="darken" result="e2"/>
      <feBlend in="e2" in2="d7" mode="darken" result="e3"/>
      <feBlend in="e3" in2="d9" mode="darken" result="e4"/>
    </filter>
  </defs>

  <g filter="url(#median)">
    <polygon points="6,20 4,16 2,20 "/>
    <polygon points="4,16 2,12 0,16 "/>
    <polygon points="6,12 4,8 2,12 "/>
    <polygon points="8,8 6,4 4,8 "/>
    <polygon points="10,12 8,8 6,12 "/>
    <polygon points="14,12 12,8 10,12 "/>
    <polygon points="18,12 16,8 14,12 "/>
    <polygon points="22,12 20,8 18,12 "/>
    <polygon points="12,16 10,12 8,16 "/>
    <polygon points="20,16 18,12 16,16 "/>
    <polygon points="4,16 6,20 8,16 "/>
    <polygon points="2,12 4,16 6,12 "/>
    <polygon points="0,16 2,20 4,16 "/>
    <polygon points="4,8 6,12 8,8 "/>
    <polygon points="6,4 8,8 10,4 "/>
    <polygon points="8,8 10,12 12,8 "/>
    <polygon points="16,8 18,12 20,8 "/>
    <polygon points="18,12 20,16 22,12 "/>
    <polygon points="10,12 12,16 14,12 "/>
    <polygon points="8,16 10,20 12,16 "/>
    <polygon points="16,16 18,20 20,16 "/>
    <polygon points="20,16 22,20 24,16 "/>
    <polygon points="10,20 8,16 6,20 "/>
    <polygon points="14,20 12,16 10,20 "/>
    <polygon points="18,20 16,16 14,20 "/>
    <polygon points="22,20 20,16 18,20 "/>
  </g>
</svg>

Get rid of thin white lines between shape 'joins', (If you posted the SVG source, it would help answer the question.) low to post a third link in an answer, so you'll have to copy/paste the link into your browser.). The SVG 2.0 white-space property will essentially do the same thing, but it will also provide a means to preserve new lines instead of whitespace on a single line. Text Decoration I probably should have included this section in last week’s post on font properties , but since I didn’t, here it is today.

Shape Rendering is your culprit amigo.

Just add shape-rendering="crispEdges" to the svg declaration (see in the source example below)... ....or as CSS to hit more than one if you like at the element level like;

svg {
  shape-rendering: crispEdges;
}

Enjoy, and cool graphic ;)

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="katman_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve" 
shape-rendering="crispEdges"> <!-- **** YOUR NEW FRIEND **** -->
  <polygon points="6,20 4,16 2,20 "/>
  <polygon points="4,16 2,12 0,16 "/>
  <polygon points="6,12 4,8 2,12 "/>
  <polygon points="8,8 6,4 4,8 "/>
  <polygon points="10,12 8,8 6,12 "/>
  <polygon points="14,12 12,8 10,12 "/>
  <polygon points="18,12 16,8 14,12 "/>
  <polygon points="22,12 20,8 18,12 "/>
  <polygon points="12,16 10,12 8,16 "/>
  <polygon points="20,16 18,12 16,16 "/>
  <polygon points="4,16 6,20 8,16 "/>
  <polygon points="2,12 4,16 6,12 "/>
  <polygon points="0,16 2,20 4,16 "/>
  <polygon points="4,8 6,12 8,8 "/>
  <polygon points="6,4 8,8 10,4 "/>
  <polygon points="8,8 10,12 12,8 "/>
  <polygon points="16,8 18,12 20,8 "/>
  <polygon points="18,12 20,16 22,12 "/>
  <polygon points="10,12 12,16 14,12 "/>
  <polygon points="8,16 10,20 12,16 "/>
  <polygon points="16,16 18,20 20,16 "/>
  <polygon points="20,16 22,20 24,16 "/>
  <polygon points="10,20 8,16 6,20 "/>
  <polygon points="14,20 12,16 10,20 "/>
  <polygon points="18,20 16,16 14,20 "/>
  <polygon points="22,20 20,16 18,20 "/>
</svg>

shape-rendering, auto: This value indicates that the user agent shall make appropriate tradeoffs or possibly just for straight lines which are close to vertical or horizontal. Firefox ? IE ? Opera ? Safari ? WebView Android ? Chrome Android ? Using inline SVG allows you to set the fill, which cascades to all the elements within the SVG, or you can fill each element separately if needed. SVG Symbol / Use There is such thing as an SVG sprite , which is a group of SVGs turned into <symbol> elements such that any given icon can be referenced easily with a <use> element.

<line>, line, Chrome Full support 1, Edge Full support 12, Firefox Full support 1.5, IE Full support 9, Opera Full support 8, Safari  The stroke-dasharray attribute is a presentation attribute defining the pattern of dashes and gaps used to paint the outline of the shape; Note: As a presentation attribute, stroke-dasharray can be used as a CSS property. As a presentation attribute, it can be applied to any element, but it only has effect on the following twelve elements:

SVG Rendering In Browsers, Safari renders .svg's based on coordinates, Chrome renders. The different vector renderings make it difficult to keep consistency in Ai and cross–browser. Although line.svg line is drawn with a 1pt stroke and outlined. The x1 attribute defines the start of the line on the x-axis The y1 attribute defines the start of the line on the y-axis The x2 attribute defines the end of the line on the x-axis

5 Gotchas You're Gonna Face Getting Inline SVG Into Production , Just to make the above points crystal clear, here's a CSS selector that would work in browsers that fully support external SVG definitions but Bottom line, if you're artwork really must have a stroke, figure you'll have to target the SVG directly. The lines are still visible on the original AI files, same for the PDF. But at least they disappear on the print now. I also found a way to get rid of the lines in the PDF. Just go to preferences --> page display and disable smooth line art. But in the end it doesn't affect the print.

How SVG Line Animation Works, I bet all of you have seen that little trick where an SVG path is animated to You just need to make stroke-dasharray a longer value than the length of the stroke. <dasharray> contains a list of comma and/or white space separated <length> s browsers interpret the switch to a zero offset as going from a fully-stroked line  The default 300×150 size also applies to inline <svg> elements within HTML documents, but that’s a relatively recent consensus from the HTML5 specifications: other browsers will by default expand inline SVG to the full size of the viewport—equivalent to width: 100vw; height: 100vh; — which is the default size for SVG files that are opened directly in their own browser tab. Internet Explorer cuts the difference, using width of 100% and height of 150px for images and inline SVG.

Comments
  • Sounds like a ronding problem. Perhaps you can add a thin border around every element so it hides it at smaller sizes?
  • @Tordek you mean, should I design a larger size and add a stroke pixel? Because when I add stroke in the "24px" disrupts the image.
  • Right; you could make it, say, 100 times larger and add a 1px stroke around every element.
  • @Tordek thank you so much, I tried x100 higher (240px) from 24px. And i add 1px border (stroke)... Unfortunately there were problems with different sizes such as slippage or overlap. Even a dimmer line in certain sizes comes out. Because i show it "24px" from the original "240px". So, 1px border makes 1/100px ( 0,01px border ) :D
  • Ty :) I tried it. it works I vote well up. But there seems to be a lot of compatibility issues. " caniuse.com/#feat=css-crisp-edges " already low pixel quality of the image quality is also disturbing. Maybe there is another solution. Otherwise I'm going to force the merger. Thank you so much.
  • @l6ls Another quick hack I use around that sometimes would be to ditch the rendering declaration and fake it with like svg polygon { stroke: #000; stroke-width: .01; } except would need considered during your color changes on individual pieces etc.