When I scale an SVG using the scale transform, the surrounding html does not respect this scale and fails to adjust its size.
I have the following SVG:
<div>
<svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1">
<circle r="150px" cx="150px" cy="150px" fill="orange"/>
</svg>
</div>
<div>
<svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1">
<circle r="150px" cx="150px" cy="150px" fill="green"/>
</svg>
</div>
For some reason the surrounding html doesn't adjust for the scaled up Svg.
All my testing so far has been on chrome and using primarily Svg declared in millimeter units.
When tested, the above example with the scale transform, the two circles overlap.
Without the transform they do not.
I want them NOT to overlap when scaled.
How can I get the Html to correctly adjust with the scaling of Svg?
Thanks in advance.
You have set fixed height and width and fixed pixels for your svg.
You have to change the properties of your svg and the actual circle path to correct it like in my example.
the transform property is something you don't need here in my opinion!
Try to change that and your HTML will surround like you want.
<div>
<svg height="100" width="100" viewbox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1">
<circle r="100px" cx="100px" cy="100px" fill="orange"/>
</svg>
</div>
<div>
<svg height="100" width="100" viewbox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1">
<circle r="100px" cx="100px" cy="100px" fill="green"/>
</svg>
</div>
That should do the job!
I think the problem is that, in SVG 1.1, I believe it wasn't properly defined how a transform attribute behaved when placed on a root <svg> element.
In SVG2 it has been. The behavior is defined in the CSS Transforms specification.
Chrome seems to have implemented that, but Firefox hasn't yet done so for SVGs. The behaviour in Chrome seems correct. transform on <svg> elements behaves the same as an HTML element (see example below).
<div>
<svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1">
<circle r="150px" cx="150px" cy="150px" fill="orange"/>
</svg>
</div>
<div>
<div style="width:300px; height:300px; background-color:green; border-radius:50%; transform:scale(1.55)">
</div>
</div>
Related
Could I load only part of a SVG (that could be identified by an #id tag) in an <img> or <object> tag ?
Reason (if I need one) is I don't want to have two SVG files if I'm only using part of a already in use one.
If I can't by using these tags, could I by using CSS or other means ?
Please take a look at this svg file in view-source. Inside the root svg there are 2 other svg elements. Those 2 svg elements have an id each and the style is saying that the nestedsvg elements are visible only if :target.
svg > svg:not(:target) {
display: none;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" height="100px" viewBox="0 0 225 225">
<style type="text/css">
<![CDATA[
svg > svg:not(:target) {
display: none;
}
]]>
</style>
<desc>
<g id="cat">
<path id="body" fill-rule="evenodd" clip-rule="evenodd" d="M121.506,..."/>
<path id="head" fill-rule="evenodd" clip-rule="evenodd" d="M129.747,..."/>
</g>
</desc>
<svg version="1.1" id="blackcat" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 225 225">
<use xlink:href ="#cat" fill="black" />
</svg>
<svg version="1.1" id="redcat" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 225 225">
<use xlink:href ="#cat" fill="red" />
</svg>
</svg>
Here is how to use one of those svg elements as an image or as an object:
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/cat.svg#redcat" width="200" />
<object width="200" data="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/cat.svg#blackcat"></object>
What you want to achieve is easiest done with another inline SVG instead of a <img> or <object> tag:
<svg style="width:200px;height:200px" viewBox="35 50 150 150">
<use xlink:href="myFile.svg#head" />
</svg>
Two things you need to get right are
the viewBox: to get just the part of your SVG that you want, you have to identify where the path is and what bounding box it has. The <use> element takes care that only the element you select is visible, but it does not identify where inside that image the element is.
the overall size your selected element is shown at. SVG has no notion of a "natural size, you always have to give a width and height. The viewBox will then be fitted inside that area.
I'm trying to embed an svg inside an svg (the real application is to be able to embed an image in a d3 chart). Here's a simplified version:
<svg viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="0" r="80" style="fill:blue" />
<image x="10" y="20" width="120" height="150" xlink:href="https://webkit.org/blog-files/circle.svg" />
</svg>
The embedded image scales correctly if it's a raster image (png/jpg), but not an svg. Here's a fiddle of it not working - the big red rectangle should actually be this circle.
https://jsfiddle.net/rg4kyuc7/1/
How do I get the svg to scale to the specified width and height?
Edit - working on Chrome but not Firefox?! Any ideas why?
The behaviour of <image> changed a little between SVG 1.1 and the upcoming SVG 2.
It looks like Chrome is following the SVG 2 behaviour. Chrome seems to be further along in implementing SVG 2 than other browsers. The way it is displaying the embedded image would be wrong if it were still supporting only the SVG 1.1 standard.
Firefox (and IE, which is behaving the same) are both incorrect with respect to both SVG 1.1 and SVG 2. The SVG 1.1 standard says that when the SVG file referenced by <image> has no viewBox, it should just be displayed at the position defined by the x and y attributes, and the width and the height of the <image> element is ignored. In other words like this:
<svg viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="0" r="80" style="fill:blue" />
<image x="10" y="20" width="335" height="296" xlink:href="https://webkit.org/blog-files/circle.svg" />
</svg>
In any case, there is a simple fix. Add an appropriate viewBox to circle.svg and it will render the same in all browsers, whether they support SVG 2 or not.
<svg xmlns="http://www.w3.org/2000/svg" width="335" height="296" viewBox="0 0 335 296">
I've came across a similar issue where we ended up using the SVG's tag.
This way you will be able to embed an html img tag in it and style it as such. Something like this:
<svg viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="0" r="80" style="fill:blue" />
<foreignObject x="10" y="20" width="120" height="150"
requiredExtensions="http://www.w3.org/1999/xhtml">
<body xmlns="http://www.w3.org/1999/xhtml">
<img src="https://webkit.org/blog-files/circle.svg" alt="Smiley face" height="150" width="120">
</body>
</foreignObject>
</svg>
Here is the MDN documentation for
https://developer.mozilla.org/en/docs/Web/SVG/Element/foreignObject
I want to fill a path in my svg with a background image, that autoscales to fill the entire path while maintaining the aspect-ratio of the image, thus as if you'd use the css background-size: cover, I've managed to get this working with clipPath or making a pattern from the image (would also like to know which of these is the option with best browser support) but I can't get the auto scaling to use.
If anyone would have some tips or solutions I would appreciate.
Here's a jsfiddle with an example of what i've got to work.
https://jsfiddle.net/shd50cvt/
The svg:
<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="341.722px" height="267.549px" viewBox="0 0 341.722 267.549" style="enable-background:new 0 0 341.722 267.549;"
xml:space="preserve">
.st0{fill:#FF0000;}
.st1{fill: url(#pattern);}
In the pattern element, you can use patternUnits="objectBoundingBox" and x="0" and y="0" and width="1" and height="1" to auto scale a single pattern tile to the size of the path. You can use preserveAspectRatio="xMidYMid slice" to maintain the aspect ratio of the tile while covering the entire path. You may need to also set preserveAspectRatio on the image element in case the jpg size does not match the image element size.
Refer to the SVG reference for more information on patterns.
http://www.w3.org/TR/SVG/pservers.html#Patterns
I have modified your example to scale the image to fill the path.
<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="341.722px" height="267.549px" viewBox="0 0 341.722 267.549" style="enable-background:new 0 0 341.722 267.549;"
xml:space="preserve">
<pattern id="pattern" patternUnits="objectBoundingBox" preserveAspectRatio="xMidYMid slice"
x="0" y="0" width="1" height="1" viewbox="0 0 400 300">
<image xlink:href="https://static.pexels.com/photos/909/flowers-garden-colorful-colourful.jpg"
x="0" y="0" width="400" height="300" preserveAspectRatio="xMidYMid slice"/>
</pattern>
<style type="text/css">
.st0{fill:#FF0000;}
.st1{fill: url(#pattern);}
</style>
<path class="st1" d="M199.668,52.98c-17.815,0-32.711,12.454-36.484,29.128c23.783,3.473,43.093,20.685,49.641,43.322
c14.174-5.325,24.262-18.998,24.262-35.033C237.086,69.732,220.334,52.98,199.668,52.98z"/>
<circle class="st0" cx="154.305" cy="142.384" r="60.927"/>
</svg>
I have an SVG document with an emebedded image element like so:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 200 200">
<image xlink:href="hannibal.jpg" x="0" y="0" width="200" height='200' />
</svg>
I can't know ahead of time the width and height of the linked image.
How can I set the width of the image to be the same as the viewBox, and allow the height to autoscale?
Failing this, can I align the image content to the top of the image element?
If you want the image to be at the top of the viewBox, rather than the centre, you just have to set preserveAspectRatio="xMidYMin".
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 200 200">
<image xlink:href="hannibal.jpg" x="0" y="0" width="200" height="200"
preserveAspectRatio="xMidYMin"/>
</svg>
This should work as long as the height is never greater than the width.
I've tried to make the SVG viewport take up 100% of the width and height of the page here:
http://jsfiddle.net/XZ57u/2/
However it seems to appear only when I change this:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" id="city">
To this (viewport size):
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1400 1400" enable-background="new 0 0 1400 1400" xml:space="preserve" id="city">
My understanding was that the 100 meant it was taking up the whole viewport percentage so why then does it appear off the page?
viewBox="0 0 100 100"
Simply put viewbox defines the coordinate-system limits of your SVG...it has nothing (really) to do with the dimensions of the element in the HTML which you can either set in the SVG itself or in your CSS.
By changing the viewbox you are effectively saying, I only want to see the top left 100x100 section of my 1400x1400 SVg.
EDIT: JSfiddle demo
with original 1400 viewbox and any CSS dimensions.
The viewbox numbers stand for pixels, not for percentatge. If you want to cover the whole container you have to set the SVG elements width and height to 100%
use this instead:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="100%" y="100%" xml:space="preserve" id="city">
here is the fiddle: http://jsfiddle.net/t5rhp/
you have to define the viewBox attribute as well. In addition you could also use Preserving Aspect Ratio as well.
svg {
width:100%;
height:100%;
}
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid none">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>