SVG won't render as CSS background-image - html

I am trying to implement a close button using a SVG image as background-image. Below is the code I am using:
.close-button {
width: 16px;
height: 16px;
background-image: url(data:image/svg+xml;base64,[The data for the image]);
background-size: 16px 16px;
background-position: center center;
}
<span class="close-button"></span>
You can test it here.
It becomes a 16 by 16 span but the image does not render. Why is this happening? Also, the image is originally black-filled. I want to change its fill to white. Is there any way to achieve this?
So, my questions are:
Why doesn't the image render as background?
How to change the SVG fill on :hover? (given my configuration - available in the link above)

You need to set either the width and height, or the viewBox attribute on the <svg>. I would recommend the viewBox, because you do not to scale the graphics to fit in. Of course you are free to set all of them, but that easily leads to confusion for your purposes.
Please note, to gain an SVG that fits into each element, do not use width and height and use viewBox. Here is a nice explanation for the viewBox.
For the SVG you posted a possible viewBox could roughly be like that:
<svg viewBox="16 104 170 170" >
I do not know how you generate your SVG but to fix those Issues I use inkscape. Just open the file > document Properties > resize document to content and save.
Than, if you want, open the svg in an text editor, create a such a viewBox="0 0 <value of width> <value of height>" and remove the width and height attributes.
Good Luck!

Related

Gap in vertical repeat of svg background

I have a simple div, with an SVG set as background image with vertical repeat. On Chrome and Firefox, depending on the screen size, I see a gap in varying sizes (please resize the window).
https://jsfiddle.net/bartadaniel/ejtvy7po/9/
.bg {
width: 50%;
height: 2000px;
display: block;
background-repeat: repeat;
background-size: contain;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='272' height='171' viewBox='0 0 272 171'> <rect class='cls-1' width='272' height='171' fill='green'/></svg>");
}
<div class="bg"></div>
Is there a reason for this?
That's happening due to a combination of background-size:contain and the pixel dimensions of your svg.
You're seeing the browser try to scale the image so that nothing overflows the bounds of your <div>. When you combine that scaling with image pixel dimensions of 171 (can't be evenly multiplied into 2000px) you get lines showing you the sub pixels you're browser is trying to display.
Simply remove the background-size:contain to solve it.
Edit:
In the case where you need to contain width, there are a few tricks to help get a better result.
Make the background image dimensions multiples of 10. Square would be best with something like 100x100px but it could also be a rectangle (try to get close to your target width) like 1000x100px.
Set background-size: 100% auto instead of contain. This will stretch the image proportionalty to fill the container width.
Use background-repeat: repeat-y to force a vertical repeat so the browser is only doing the math on one axis.
It is a problem of subpixel rendering.
Each browser rounds differently and SVG subpixel rendering is pretty messed up.
I suggest you to edit your SVG content to make it slightly bigger than your viewbox.
<svg xmlns='http://www.w3.org/2000/svg' width='272' height='171' viewBox='0 0 272 171'>
<rect class='cls-1' y='-.5' width='272' height='172' fill='green'/>
</svg>
Obviously this trick doesn't work for all the background SVG, but might be useful in your case.
Unfortunately, the only solution that reliably tackled this issue was to convert the SVG to a pixel-based format, like JPG. Apparently, the browsers have no problem scaling pixels but causes side effects at edges when scaling vector-based formats.
If your SVG will still look acceptable with less anti-aliasing, you can change the anti-aliasing of the shapes in your SVG using the shape-rendering property. Example:
<rect shape-rendering="crispEdges">
You can use this on these elements: <circle>, <ellipse>, <line>, <path>, <polygon>, <polyline>, and <rect>.

Printing an SVG from HTML in landscape mode

Okay so my setup is a window object created on the fly.
I'm writing to it with window.document.write() and building out this:
<style>
#page{
size: landscape;
max-height: 100%;
max-width: 100%;}
svg{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
display: block;
overflow: visible;
transform: scale(1, 1.3737);}
</style>
and then I clone the SVG from the page it's on and document.write(svgClone.innerHTML).
I end up with this: https://jsfiddle.net/je0ssLm2/1/
Please excuse the mess but that contains the entire code for the SVG and displays how it renders. The reason I'm scaling by 1.3737 on the Y axis is because the image is 1280 x 720 but 1280 x 989 is close to an aspect ratio of 1:3 which is approximately the AR of US letter.
Anyway, as you can see the display is not very attractive, and when it prints for some reason the margins are very large and the image is quite small and not quite centered in the screen. Is there some crucial CSS I am missing? This is driving me nuts, I've seen a few other answers about this and tried various but I just can't get it to print correctly.
I'm not as worried about size as I am positioning. I can monkey with the scaling to get the size right but if I make the image bigger then I'll cut off axis labels or the title because the graph doesn't center on the page. I also ALWAYS get an extra blank page, which isn't the end of the world but definitely isn't desirable.
You need to modify attributes on the <svg> element for a clean solution.
SVG has two attributes that let you describe scale-to-fit operations declaratively without computing transforms yourself: viewBox and preserveAspectRatio.
Instead of the attributes you have
<svg width="1280" height="720">
you can write
<svg viewBox="0 0 1280 720" preserveAspectRatio="none">
If you cannot get at the source text, you can simply wrap the <svg> in a second one:
<svg viewBox="0 0 1280 720" preserveAspectRatio="none">
<svg width="1280" height="720">...</svg>
</svg>,
and, as long as you define sensible sizes, should work in all media, including the page the SVG originally comes from.
The area defined by the viewBox in SVG userspace coordinates will then be fitted into the size of the <svg> element itself - since you have it defined in CSS with width:100%;height:100%;, it is fitted into the containing element.
preserveAspectRatio="none" does the uneven scaling for you. This didn't work before because as a default, the aspect ratio was preserved (and only after being scaled-down-to-fit, the CSS transform cut in).

SVG looks ok in browser, but not when included as 'img src=file.svg'

I'm having trouble displaying an svg image correctly on an html page.
I created the image using snapsvg, extracted the svg and added xml and doctype tags.
The svg and the test page code is here:
https://gist.github.com/falconair/ed0fbbc5db4135d0f1b2
When I open the svg in chrome, it looks fine. When I open it in this html, the text at the boddom disappears, replaced by dashes:
<html>
<head></head>
<body>
<img src="/assets/composingcontracts/mappingdiagram.svg" width="850px" height="450px">
<img src="/assets/composingcontracts/mappingdiagram.svg" width="100%" height="100%">
</body>
</html>
Note that I display the image twice, once using 100% height/width and once using explicit values, I get the same result.
What's more, when I include this image in my actual web page (jekyll blog post), no matter what height/width values I use, only the top third of the image shows!
Any ideas?
If you are using a specific size like width="850px" height="450px", then the whole image should show. Unless it is in a container (eg. <div>) which is smaller than that.
However, when you use percentages (width="100%" height="100%"), that is referring to the size of the SVG "viewport", which is normally the parent object. But if you haven't specified a specific size for that parent element, SVG has to do some guessing.
What happens when you specify (100% x 100%) is that SVG sets the width of the SVG to 100% of the parent container. Then it tries to calculate a height based on that width and the aspect ratio of the SVG - which it gets from the viewBox. If there is no viewBox, it falls back to the default height for indeterminate elements, which is 150px. That will be why you are only seeing the top third.
You could fix this issue by adding viewBox="0 0 850 450" to your SVG. However then the SVG size will be controlled by its parent container. Which you will need to at least give a width to, otherwise the SVG will be scaled down to that "indeterminate" height of 150px.
Try exporting the image using the PNG file format and use the 100% height/weight. Hope it works.

IMG tag with external SVG file not responsive to scaling of container

This is a commonly asked question (and I have looked for, found and tried a variety of other suggestions, here on stackoverflow and elsewhere)
I have an web page where I'd like to dynamically load in maps, which are in SVG format. I would like the maps to be responsive to rescaling of their container, i.e. fill the width of the container as the window resizes for example.
<div class="container">
<img src="http://snacknack.com/1/08.svg" style="height: 1286px;" />
</div>
The external 08.svg file starts like this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 909 1286">
Instead of resizing the SVG remains rock solid at its original size. Here is the jsfiddle (Note: viewbox edited to viewBox in svg file thanks helderdarocha for spotting that)
I have tried giving the .container a width:100%, height:100%; but that does not work, nor do various other suggestions for related questions. I am not sure whether that is because I have to use an external file to provide the SVG (rather than doing the SVG inline which is what examples do) or
whether it is because of something inside the SVG content.
I have already tried using an OBJECT tag to bring in the SVG file rather than an IMG tag. Same issue.
If I do not provide the hardcoded height in the IMG tag, the map will truncate at around 377-400px vertically (in my Mac OS Chrome & Safari browsers) and if I set it to height:100% the map disappears entirely.
How do make this IMG tag/SVG responsive ?

Inline SVG not scaling as viewport changes...?

I am trying to get an SVG I wrote / drew to scale as the viewport changes, it's the reason I chose sVG as the format for the image.
However, it doesn't seem to be scaling at all.
I did all that my research told me to, added width, height and some attributes to the SVG element and added a div container-parent; and, then added max-height / width and height / width : 100% in CSS to that.
Any idea why this SVG is not scaling and how I can get it to scale?
Here is a live example of the page in question : https://dl.dropbox.com/u/270523/inlineSVG.html
The CSS on #bookmark state: width: 100%; max-width: 106px; this means that the svg will never scale unless the window is less that 106px wide (which most/all browsers do not allow).
It is difficult to discern exactly what you want to achieve, but if you state width: 10% you will observe the SVG is indeed scaling according to the browser width.