简体   繁体   中英

CSS Background Color on an <IMG> using external SVG as the SRC

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>

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>

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/

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).

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/

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

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.

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;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM