6

I have an SVG square with a shape cutout of the middle (think cookie cutter). The SVG was created in Illustrator, with the edges of the shape extending to the edge of the art-board.

The color of the shape is the same as the background color.

To change the color of the SVG shape I'm simply changing the background color of the IMG in CSS. This works fine, however you will notice that there is a half-pixel color leaking outside the shape as if it were a border.

Depending on the size specified to the IMG, the border disappears or reappears. Any clues on how to get rid of that?

Working Example: http://jsfiddle.net/ja6Tx/

HTML:

<div class="container">

     <img class="logo" src="http://toobulo.com/img/logo-icon.svg" />

 </div>

CSS:

 body {background:#252525;}

 img.logo {background:yellow;}

UPDATE: I've decided to replicate the issue in a much simpler form, in order to rule out any pixel decimal issues and the problem still exists. (On any screen).

See here: http://jsfiddle.net/w7vrs/

We now have a 320x240 rectangle. Notice the problem never happens if the container's width is that of the same aspect ratio (160, 640, etc). As soon as you change the .img-container's width to something like 451px, the issue returns.

The point of all this is that SVG is meant to be scalable, so I should not have to specify an exact pixel width in order to take advantage of SVG.

As you can see, the code for the new SVG is almost nothing:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="320px" height="240px" viewBox="0 0 320 240" style="enable-background:new 0 0 320 240;" xml:space="preserve">
<style type="text/css">
<![CDATA[
    .st0{fill:#020202;}
]]>
</style>
<rect class="st0" width="320" height="240"/>
</svg>
Joe
  • 5,955
  • 2
  • 29
  • 42
  • If possible, you might open up your Illustrator file in Photoshop and trim off any transparent pixels. When exporting from Illustrator, I've experienced rogue transparent pixels in bitmaps. If that doesn't work, maybe open a new artboard and Place the artwork into the new file, then resize to be full width/height of your new canvas. You could also try a clipping mask to the artwork and when you export, make sure there aren't any transparent/unfilled areas of your artwork. – dlane Feb 12 '14 at 15:47

8 Answers8

4

The external SVG image is 237.104px wide. If you change all occurrences of 237.104 to 237 then the problem will go away.

Replacing the first few lines with the following should do the trick:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="237px" height="400px" viewBox="0 0 237 400" enable-background="new 0 0 237 400" xml:space="preserve">
<path fill="#252525" d="M65.375,258.523c-0.013-0.014-0.026-0.026-0.04-0.041l0.088,0.1
    C65.388,258.543,65.375,258.527,65.375,258.523z"/>
<path fill="#252525" d="M60.655,171.371C60.631,171.387,60.166,171.83,60.655,171.371L60.655,171.371z"/>
<path fill="#252525" d="M0,0v400h237V0H0z M229.401,236.861c-1.209,3.683-2.285,7.473-3.723,11.129

(There may be other issues, but cleaning up your SVG file and sticking to a pixel grid should resolve everything.)


Update: Your alternative SVG is still drawing outside the box (d="M0,0v400h237.104V0H0z). Here's a cleaned up version of the SVG where it's a bit easier to see what's going on:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="237" height="400" viewBox="0 0 237 400"
   enable-background="new 0 0 237 400" xml:space="preserve">
<path fill="#252525" d="M0,0v400h237v-400H0z M198,290.5c-25.667,25.667-54.125,35.125-85.625,35.125
  c-31.25,0-61.375-15.5-78.708-32.792C17.146,276.353,1.5,253.458,1.5,215.125c0-32.875,19.625-62.375,36.5-75.958
  c12.874-10.362,33.917-20,58.25-20c22.5,0,43.5,11.208,54.271,20.827c10.41,9.295,25.965,28.007,25.965,55.315
  c0,26-14.236,43.691-25.283,51.748c10-13.333,12.464-28.223,12.464-37.89c0-13.542-4.667-27.042-13.667-37.667
  c-8.537-10.078-26.334-20.667-44.333-20.667c-20.167,0-33.575,8.098-44,18.905c-9.417,9.761-16.263,27.011-16.263,41.428
  c0,18.833,7.346,34.708,16.93,44c10.497,10.178,28.333,21.666,50.667,21.666c25.125,0,46.33-10.434,60.667-31
  c12.083-17.333,17-33.333,17-51.334c0-23.625-9.126-48.455-30.134-67.54C137.875,106.375,109.875,97.2,84.443,97.2
  c-28.068,0-56.693,10.425-76.109,25.657C36.625,86,74.79,75.289,105.789,75.289c33.336,0,69.919,14.419,94.586,41.086
  S234,171.25,234,201.833C234,228.167,223.667,264.833,198,290.5z"/>
</svg>

The first part of the <path> element is the bounding rectangle M0,0v400h237v-400H0z. The coordinates are all integers now, so there shouldn't be any problem. (Although Damien's suggestion is worth considering.)


OK, I'll try one more time :-)

I wasn't able to reproduce the problem in the JSFiddle you posted, but if the SVG is allowed to scale with the viewport size then it does grow yellow borders sometimes.

To fix this, I extended the background of the SVG image by an additional pixel past the viewbox dimensions. This seems to have fixed the problem (in Chrome, at least).

So to address your original question, I think all you need to do is change the first part of the path data to M-1,-1v402h239v-402H-1z, as follows:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="237" height="400" viewBox="0 0 237 400"
   enable-background="new 0 0 237 400" xml:space="preserve">
<path fill="#252525" d="M-1,-1v402h239v-402H-1z M198,290.5c-25.667,25.667-54.125,35.125-85.625,35.125
  c-31.25,0-61.375-15.5-78.708-32.792C17.146,276.353,1.5,253.458,1.5,215.125c0-32.875,19.625-62.375,36.5-75.958
  c12.874-10.362,33.917-20,58.25-20c22.5,0,43.5,11.208,54.271,20.827c10.41,9.295,25.965,28.007,25.965,55.315
  c0,26-14.236,43.691-25.283,51.748c10-13.333,12.464-28.223,12.464-37.89c0-13.542-4.667-27.042-13.667-37.667
  c-8.537-10.078-26.334-20.667-44.333-20.667c-20.167,0-33.575,8.098-44,18.905c-9.417,9.761-16.263,27.011-16.263,41.428
  c0,18.833,7.346,34.708,16.93,44c10.497,10.178,28.333,21.666,50.667,21.666c25.125,0,46.33-10.434,60.667-31
  c12.083-17.333,17-33.333,17-51.334c0-23.625-9.126-48.455-30.134-67.54C137.875,106.375,109.875,97.2,84.443,97.2
  c-28.068,0-56.693,10.425-76.109,25.657C36.625,86,74.79,75.289,105.789,75.289c33.336,0,69.919,14.419,94.586,41.086
  S234,171.25,234,201.833C234,228.167,223.667,264.833,198,290.5z"/>
</svg>
r3mainer
  • 23,981
  • 3
  • 51
  • 88
  • 1
    As with the answer below, it seems to do the trick until you look at it on a different device (Retina Macbook Pro and also iPhone screen). New fiddle with an updated SVG using whole numbers resource: http://jsfiddle.net/KWhB9/ – Joe Feb 06 '14 at 22:39
  • try taking it to a number divisible by two for the retina and iphone... 238 – Damien Black Feb 06 '14 at 23:01
  • @DamienBlack nice suggestion, however that doesn't provide consistent result (seems more to do with luck than anything). See updated Question and this fiddle: http://jsfiddle.net/w7vrs/ – Joe Feb 08 '14 at 00:34
  • Related: https://stackoverflow.com/q/21640776/2157640 http://stackoverflow.com/q/11201248/2157640 – Palec Feb 09 '14 at 00:42
  • @Palec as you can see in the fiddle I mentioned above, whole numbers do not solve the issue: http://jsfiddle.net/w7vrs/ – Joe Feb 09 '14 at 18:09
  • 1
    @Joe The linked questions are related to this answer, not to your question, and I posted them here for that reason. I played with the fiddle for a while and I’m sure it is browser bug. The yellow lines disappear when you scroll down only a little bit in Firefox. Also they have sub-pixel size – try setting `img {display: block; outline: 1px solid red;}` and use a magnifier. If it is a cross-browser problem, it is possible that all the browser vendors made the same mistake. E.g. maybe image size is always stored as a float and thus producing round-off errors. Try using powers of 2 as dimensions. – Palec Feb 09 '14 at 18:46
  • thanks for clarifying @Palec, that makes sense. I know it's a rare / nit-picky condition, however i'd imagine this pops up more and more now that SVG is being used alongside responsive layouts. – Joe Feb 09 '14 at 18:51
  • @Joe I think I've found out what the problem is. Please take a look at the update to my answer above. – r3mainer Feb 09 '14 at 19:31
  • @squeamishossifrage ugh i was this -><- close to accepting your answer because it seemed to solve the issue (does look great in Chrome). Sadly, I had to open it in Firefox first and of course- the problem is amplified. I will test by using your method but offsetting it by more than just 1 pixel, maybe that will do the trick.. although it's pretty clear now that the problem is deeply rooted within all browsers as noted above from Palec, some worse than others. – Joe Feb 09 '14 at 19:51
  • @squeamishossifrage Ugly hack but as a work-around it could work. Good idea. I haven’t read SVG spec, however, and I don’t use SVG too much, so I cannot judge. – Palec Feb 09 '14 at 21:10
  • @Joe I recommend filing bugs in browsers’ bug tracking systems, posting links here and getting people to vote on them. This way you can get the browsers fixed. You made a neat demo, the problem seems pretty reproducible, I think it has a good chance to get fixed if browsers’ developers see that fixing this is important for many people. – Palec Feb 09 '14 at 21:13
1

This is an odd bug, probably has to do with padding around inline elements. Here is what I found to handle it. Put your svn inside an 'image container' div, like this:

<div class = 'img-container'>
    <img class="logo" src="http://toobulo.com/img/logo-icon.svg" />
</div>

Then you set the image width to 100%, and set the width on the container to the width you actually want:

.img-container {
    width: 200px;
}

img.logo {background:yellow;
    width:100%;
}

Working fiddle: http://jsfiddle.net/ja6Tx/5/

Damien Black
  • 5,579
  • 18
  • 24
  • Unfortunately with this technique it still remains on varying devices. Showed up fine on my regular display- but when viewed on Retina MacBook Pro screen the issue is still there- as well as iPhone. – Joe Feb 06 '14 at 22:35
  • @DamienBlack I see a yellow line at the bottom of the image in my Firefox 17.0.11esr on Debian Linux. – Palec Feb 09 '14 at 18:51
1

By simply using the recent HTML5 <svg> element the bug does not occur:

http://jsfiddle.net/ja6Tx/55/

It seems browsers are using a different renderer depending on where the SVG came from (svg, object or image element, or defined as a background image in a stylesheet).

Skadi2k3
  • 66
  • 4
0

I think I found an odd little hack for it.

body {
    background:#252525;
    margin:-1px;
}

.img-container {
    width: 199px;
    height:338px;
    overflow:hidden;
}

img.logo {background:yellow;
    width:200px;
    height:340px;
}

Make the container a pixel or two smaller than your image and hide the overflow. In playing around with this I have a theory that your SVG is sized in a way that it falls between pixel sizes. I feel this way because as I was playing around with this in Safari fixing the width would cause the same offset in the height and visa-versa. Perhaps the real solution is to make sure that your image is built and exported at a size that scales exactly in pixels.

But this CSS seems to at least solve this issue short term. If you would like, I can also take some time to remake the svg in illustrator and see if I can fix it there using a different document setup.

http://jsfiddle.net/ENVKA/

UPDATE: Was able to confirm that the SVG was built with a width that was was between a whole pixel. By setting the document units to pixels and setting the artboard to 237 px (previous setting was 237.1 px), the image works as it should. No CSS hack needed!

http://jsfiddle.net/JB9Cc/

innerurge1
  • 718
  • 3
  • 17
  • unfortunately no! It really does seem like there must be an SVG bug and the only way around it is a cropping hack. I updated your fiddle as you can see just by adjusting the height in CSS what happened: http://jsfiddle.net/JB9Cc/1/ – Joe Feb 25 '14 at 10:32
0

I am refering to your update.
It seems that this is mainly a problem in Firefox (where I can reproduce the issue), while in Chrome the issue does not appear.

I guess it results from some "rounding errors" of the browsers internal calculations.

One simple way to avoid this, is to use clip for the image:

img.logo {
   clip:rect(0 0 auto 452px);
}

By doing so the "problem" disappeared (in FF) - see JSFiddle

Netsurfer
  • 5,543
  • 2
  • 29
  • 34
0

As others have pointed out, it has to do with the way different browsers round decimals. Check out this post on how different browsers handle subpixels: http://ejohn.org/blog/sub-pixel-problems-in-css/

I think the best way to handle this is to not assign the color to the image. Instead do what most people would do in this situation and just use a background div. Something like

http://jsfiddle.net/ja6Tx/50/

    <div class="container">

        <div class="logo">
            <div class="bg"></div>
            <img src="http://toobulo.com/img/logo-icon.svg" />
         </div>
    </div>

    .logo{
        position: relative;
        height: 400px;
        width: 237px;
    }
    .bg {
        position: absolute;
        top:10px;
        left: 1px;
        height: calc(100% - 20px);
        width: calc(100% - 1px);
        background:yellow;
    }

    img{
        position: absolute;
        width:100%;
    }

In my testing on my macbook pro retina it doesn't show any yellow borders, plus this is just the most logical way to deal with the the issues relating to the inconsistency of the SVG.

TalkativeTree
  • 609
  • 5
  • 10
0

Create your background using a pseudo-element. You can then place the background a pixel away from the edge of the image, like so:

.logo {
    position: relative;
}

.logo::before {
    background: yellow;
    bottom: 1px;
    content: '';
    display: block;
    left: 1px;
    position: absolute;
    right: 1px;
    top: 1px;
    z-index: -1;
}
Patrick Fisher
  • 7,926
  • 5
  • 35
  • 28
0

I know this is over a year old, but I was having the same issue and considered Paul LeBeau's advice in another thread regarding extending outside the viewBox. Below is an example showing the issue and the fix.

Icons with background colors showing issue and showing fix

The badge icon does not show the bleed, while the medal icon does.

Side-by-side image of icons within viewBox and extended beyond viewBox

Viewing the left SVG in Illustrator, the background of the image goes to the very edge of the viewBox.

Viewing the right SVG in Illustrator, the background of the image extends beyond the edge of the viewBox.

Fixing your SVG so that the solid background extends beyond viewBox will fix your issue.

Vuice
  • 43
  • 6