Resizing an SVG to specific dimensions - css

I am trying to resize an svg to the exact size which I want it (32x32).
Look at the example at http://jsfiddle.net/Uy94k/6/
This fiddle is a short outtake of a larger .svg file which I include in my html file and refeer to which image I want using:
<svg class="small" viewBox="0 0 512 512" preserveAspectRatio="none">
<g filter="">
<use xlink:href="#login"></use>
</g>
</svg>
(Any easier way to do this by the way?).
As you can see, I've tried using preserveAspectRatio, but without luck. I've also tried different styling techniques (ie. sizing in span tags outside the svn, styling in the svn tags, fiddling with height both in and where I call it by id.).
If you use a developer tool to look at the height/width of the images in the fiddle, you will see that it is 26x20.. But why is that?

Tweeking the viewBox values (guessing the value of viewBox="120 70 340 340" in this case) kinda did the trick. But it is error prone, not nice, and tedious to tweek the parameters.. Look at the example at http://jsfiddle.net/veZSX/1/ for a tweeked vs untweeked version.
There must be a better way?

Related

Chrome is clipping the edges off SVG images , where other browsers don't

I have some SVG icons I'm using which show up correctly in Firefox and Safari, like this:
...but they come out clipped at the edges like this in Chrome (both MacOS and Windows):
The source images are square (they have square viewBoxes, even if there's extra internal blank space), and my SVG markup treats them as square:
<image id="download" href="assets/download.svg" x="161.5" y="0.5" width="2.5" height="2.5"/>
<text id="low-battery-text" x="169" y="2.75" text-anchor="end"></text>
<image id="low-battery" href="assets/low-battery.svg" x="169.5" y="0.5" width="2.5" height="2.5"/>
If I make the specified height of these icons a bit taller then Chrome stops clipping them, but that changes the positioning and scaling of the images a bit too. And besides, it shouldn't be necessary.
I get the impression that Chrome is ignoring the viewBox values for the SVG images, it's finding the internal edges of the images, and scaling according to that (but that's just a guess). (No, that's not it.)
Here's what the SVG inside one of the SVG files looks like:
<?xml version="1.0" encoding="iso-8859-1"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<g>
<path fill="#0F0" d="M25.462,19.105v6.848H4.515v-6.848H0.489v8.861c0,1.111,0.9,2.012,2.016,2.012h24.967c1.115,0,2.016-0.9,2.016-2.012
v-8.861H25.462z"/>
<path fill="#0F0" d="M14.62,18.426l-5.764-6.965c0,0-0.877-0.828,0.074-0.828s3.248,0,3.248,0s0-0.557,0-1.416c0-2.449,0-6.906,0-8.723
c0,0-0.129-0.494,0.615-0.494c0.75,0,4.035,0,4.572,0c0.536,0,0.524,0.416,0.524,0.416c0,1.762,0,6.373,0,8.742
c0,0.768,0,1.266,0,1.266s1.842,0,2.998,0c1.154,0,0.285,0.867,0.285,0.867s-4.904,6.51-5.588,7.193
C15.092,18.979,14.62,18.426,14.62,18.426z"/>
</g>
</svg>
I can only find very different topics discussed when I try to Google for an answer to this problem, so I hoping someone who may have encountered a similar issue might have a suggestion for fixing it.
Update:
Interesting experiment - it isn't a good solution, but it's perhaps revealing of the underlying problem.
If I bypass using an SVG image file, and paste the content of the SVG file into my own SVG, the clipping problem goes away:
<svg viewBox="0 0 30 30" x="161.5" y="0.5" width="2.5" height="2.5">
<g>
<path fill="#0F0" d="M25.462,19.105v6.848H4.515v-6.848H0.489v8.861c0,1.111,0.9,2.012,2.016,2.012h24.967c1.115,0,2.016-0.9,2.016-2.012
v-8.861H25.462z"/>
<path fill="#0F0" d="M14.62,18.426l-5.764-6.965c0,0-0.877-0.828,0.074-0.828s3.248,0,3.248,0s0-0.557,0-1.416c0-2.449,0-6.906,0-8.723
c0,0-0.129-0.494,0.615-0.494c0.75,0,4.035,0,4.572,0c0.536,0,0.524,0.416,0.524,0.416c0,1.762,0,6.373,0,8.742
c0,0.768,0,1.266,0,1.266s1.842,0,2.998,0c1.154,0,0.285,0.867,0.285,0.867s-4.904,6.51-5.588,7.193
C15.092,18.979,14.62,18.426,14.62,18.426z"/>
</g>
</svg>

How can you use a symbol from SVG defs.svg as background image in CSS?

I'm trying to use a symbol from my defs.svg as a background image in CSS, as opposed to a direct path to an individual SVG file.
So instead of:
background: url(spoon.svg);
I want to do something like this:
background: url(defs.svg#spoon);
With #spoon being a symbol in defs.svg with id="spoon". Unfortunately, this isn't working for me. Has anyone come across a solution that doesn't involve custom JS/etc?
You'd need to define view and use tags inside your defs.svg so CSS would know where to look and what to show.
So, for example, say you have inside your SVG a symbol defined as this:
<symbol id="poop" viewBox="0 0 100 100">
<!-- Your shapes here -->
</symbol>
And before closing the svg tag, you must add the view and use defining tags:
<view id="poop-view" viewBox="0 0 100 100" /><!-- This ID used here is what you'll use in your CSS! -->
<use xlink:href="poop" width="100" height="100" x="0" y="0"></use>
Note that at this point, you can open your raw SVG file in a browser and it will show your drawing - before it showed blank!
And now you can set your SVG symbol in your CSS:
div{background-image:url("defs.svg#poop-view")} /* Remember, it's the ID used on your <view> def! */
Also, be sure your SVG includes a xmlns:xlink namespace on the opening tag, or it won't be supposed to work.
Disclaimer: I'm trying to use this setup at work hosting the SVG file on a server on my university, but for some reason this doesn't work (even SVG files won't show if <?xml>and <!DOCTYPE> tags are missing on the SVG), so be sure to check the sanity of your SVG file.
Find more about this on Jennifer Hiller's codepen blog.

Stripping down SVG Code

I have created SVG code from coreldraw and want to place it inline in my HTML5 document and have a couple of queries.
How universal is SVG now-a-days? Any suggestions on backwards compatibility?
I have taken out the style data from the svg and put that into my css, I guess that's not a problem - or is it? I also added a hover rule...
.Borderline {stroke:#0099FF;stroke-width:7.45541;stroke-linejoin:round}
.BorderFill1 {fill:#71C6FF}
.BorderFill2 {fill:#CBEAFF}
.BorderFill1:hover {fill: green; }
Can I remove any of the following data that is not needed. (but I want it to work and look the same)
<svg xmlns="http://www.w3.org/2000/svg" class="myimgleft" xml:space="preserve" width="100px" height="105px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" viewBox="0 0 92 97" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Layer_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<path class="BorderFill1 Borderline" d="M55 51c10,0 18,0 24,0 4,-5 9,-10 9,-15 0,-6 0,-22 0,-32l-16 14c-5,-4 -8,-6 -17,-14l0 47z"/>
<path class="BorderFill2 Borderline" d="M79 51c-5,-1 -41,0 -47,0l0 -14c-8,8 -25,25 -28,28l28 28 0 -13c7,0 11,1 17,-2 6,-2 23,-21 30,-27z"/>
</g>
</svg>
Any other hints / tips that might be useful are very welcome.
1 MDN keeps an accurate list of compatibility per-element. Here's the list for SVG: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg
Feature Chrome Firefox (Gecko) IE Opera Safari
Basic support 1.0 1.5 (1.8) 9.0 8.0 3.0.4
2 Keep the style in your SVG - it'll make it easier to swap out for other SVG images later. You want to be able to quickly update your svg. This one is more a matter of preference.
3 I wouldn't get in the habit of tweaking vector-art exported from CorelDraw by hand. You may think to run it through a minifier, but hand-tuning is almost certainly more work than it's worth.
Here's the first minifier Google gives me:
http://petercollingridge.appspot.com/svg-optimiser
For cases where you're not inlining, you can give .svgz (compressed svg) a shot, which will make it significantly smaller: https://graphicdesign.stackexchange.com/questions/24797/when-should-i-use-svg-or-svgz-for-my-web-graphics
4 Hmm, other tips - well good on you for using vector art on your site. Too many web devs/designers take the shortcut of doing everything in raster. While that gets you a nice looking image for a demo, in the long run it's really hurting your site. With ubiquitous tablets + phones, pinch + zoom is everywhere and your images need to scale nicely.
Personally, I've never loved the idea of inlining svg - I've always preferred saving as .svg and src-ing it like an image. I see why you are inlining it, though, as you're using some hovers.

How to scale an SVG with <image> tag fallback?

I am examining how to add external SVG files in a responsive manner, and fell for the SVG image tag trick, because it doesn't require JavaScript.
(The SVG has been 'washed' with scour, thus being stripped of height/width attributes, and viewBox being added, as recommended.)
The problem is that this technique seems to require a height and width attribute to work, on the image tag, which isn't responsive. Suggested syntax is:
<svg width="200px" height="100px">
<image xlink:href="logo.svg" src="logo.png" width="200px" height="100px"/>
</svg>
However, setting relative dimensions, like so:
<svg style="width:100%; height:100%">
<image xlink:href="logo.svg" src="logo.png" width="100%" height="100%"/>
</svg>
.. makes the SVG responsive, however renders the <image> element incorrectly (or, not as expected anyway). This can be fixed by adding preserveAspectRatio and viewBox attributes:
<svg style="width:100%; height:100%" preserveAspectRatio="xMidYMid meet" viewBox="0 0 200 100">
<image xlink:href="logo.svg" src="logo.png" width="100%" height="100%"/>
</svg>
Now everything works as expected in all major browsers, except that in IE9-11, the problem now lies with <svg> tag: it's not wrapped around the <image> tag.
Been playing around with various combinations, like omitting the <svg>'s height attribute, but to no avail.
Has anyone solved this without using JavaScript or conditional statements?
Note: Other methods to achieve the same is of course welcome (that is, responsive, external SVG file, working fallback, and without using JavaScript)
Note 2: The described method does not fallback gracefully in Safari on IOS 5 either.
I was working on the same issue today and ran across your question hoping for an answer.
Check out this code for the answer: http://jsfiddle.net/ECTBL/
The trick was having the right attributes in my SVG file i.e.
height="..."
width="..."
viewBox="..."
xml:space="preserve"
When I saved the file from illustrator, it was missing a height and width attributes in the SVG file.
Finally, you'll need the following CSS for it to work:
This is for a bug in webkit
svg { max-height: 100%; }
And of course, this makes the image stretch.
img { width: 100%; }

Write an equivalent <svg> for a <image xlink:href="something.svg" />

Feel free to ask for more context if you're wondering why this is necessary, or want to suggest a better way to solve the bigger problem. (It involves laying out a bunch of building floor plans onto a campus map and finding the absolute location of certain things that are in those building maps; more detail was bogging the question down.)
The short version is that I want to take an SVG file that has <image xlink:href="something.svg" /> references and merge it into one big file with each referenced SVG being embedded with an <svg> and inline SVG XML content.
So, my top-level source file (composed in Inkscape) looks like this:
<image xlink:href="floorplans/bldg1.svg"
width="165.52684" height="107.10559" y="-1937.7657"
x="2507.1565" transform="matrix(0,1,-1,0,0,0)" />
And my attempt at a merged version to inline all the vector data:
<svg x="2507.1565" y="-1937.7657" width="165.52684" height="107.10559"
transform="matrix(0,1,-1,0,0,0)" viewBox="0 0 1224 792">
<g id="surface0">
<path style="fill:none;stroke-width:0.72;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);...
So, basically I'm using a script to replace <image> with <svg> and paste in the contents of the root <svg> of "floorplans/bldg1.svg". (Copying attributes from the <image> to the <svg>, and copying the viewBox attribute from the original <svg> to the new one.)
This technique worked for things that aren't rotated, but Chrome seems to be saying this particular element is off the top of the viewport. I'm new to SVG, but I'm thinking the order of the transformations isn't the same on the <svg> as it is on the <image>. Did I make a dumb mistake I'm not spotting, or is there more involved in converting an <image xlink:href="something.svg" transform=... /> to an <svg> with inline XML?
Thanks.
The transform attribute doesn't apply to the <svg> element according to the SVG specification. You can put the transform that was on the <image> element on the <g> element either outside or inside the <svg> instead.
The reason for transform behaving this way is that the <svg> element sets up the coordinate system, and the transform depends on that (a question that would arise if it did apply is "should the transform be interpreted in the coordinate-space before or after the svg coordinate system is setup?")

Resources