How to center SVG within its container? - css

How does one center this SVG horizontally within .svg_wrapper?
.svg_wrapper {
border: 1px solid grey;
width: 200px;
}
<div class="svg_wrapper">
<svg viewBox="0 0 600 425">
<path d="M 175, 175 m 0, -75 a 75,75 0 1,0 0,150 a 75,75 0 1,0 0,-150" fill="none" stroke="black" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000">
<animate attributeType="XML" attributeName="stroke-dashoffset" from="0" to="600" dur="2s" repeatCount="1" fill="freeze" />
</path>
</svg>
</div>
http://jsfiddle.net/frank_o/fj7Xc/
Tried stuff like margin: 0 auto, text-align: center as well as flexbox but to no avail.

The SVG is centered in the wrapper...the path, however, is not centered in the SVG
You would have to adjust the viewbox accordingly
<svg viewBox="0 0 350 350">
JSfiddle Demo

Related

How to fit svg width/height to be the same as path width/height

I have this svg that renders an arrow
<div style="position: absolute; z-index: 0;">
<svg
width="373"
height="280"
overflow="auto"
style="position: absolute; left: 630.922px; top: -305px; pointer-events: none;"
>
<path
d="M 20 260 C 20 260, 334.74671750091653 33.15551891825835, 334.74671750091653 33.15551891825835"
stroke="CornflowerBlue"
stroke-dasharray="0 0"
stroke-width="5"
fill="transparent"
pointer-events="visibleStroke"
></path>
<g
fill="CornflowerBlue"
pointer-events="auto"
transform="translate(319.89194405571646,25.37183689162216) rotate(-35.78107386189255) scale(30)"
opacity="1"
>
<animate
dur="0.4"
attributeName="opacity"
from="0"
to="1"
begin="indefinite"
repeatCount="0"
fill="freeze"
></animate>
<path d="M 0 0 L 1 0.5 L 0 1 L 0.25 0.5 z"></path>
</g>
</svg>
</div>
This results in
As you can clearly see from the photo (it's an inspect element of the svg element though), the diagonal arrow has blue background even after the arrow's head ends. The same thing counts for the width as well, the blue background is wider than the actual arrow width. Is it possible to fit the svg width/height to be the same on as the path's? The paths looks like this:
If possible, how can I achieve this?
Draw your arrows outside the SVG by either changing the path data or by adding a viewBox to the SVG element with a x/y/width/height that shifts the arrows outside the SVG's boundaries. And then add overflow: visible to your SVG element.
In this example I have a viewBox 500 in width and 300 in height. I made a line from the left bottom corner to the top right corner. I turned the arrow into a <marker>. To hide the start and the end of the line I added a stroke-dasharray there the first segment in 0, a space of 1, a segment of 98 and a space of 1 (0 1 98 1). The path length is set to 100.
<svg viewBox="0 0 500 300" width="500">
<defs>
<marker id="arrow" viewBox="0 0 1 1" refX="1" refY=".5"
markerWidth="6" markerHeight="6"
orient="auto-start-reverse">
<path d="M 0 0 L 1 0.5 L 0 1 L 0.25 0.5 z" fill="CornflowerBlue" />
</marker>
</defs>
<rect width="500" height="300" fill="#eee"/>
<line x1="0" y1="300" x2="500" y2="0" stroke-dasharray="0 1 98 1"
pathLength="100" stroke="CornflowerBlue" stroke-width="5" marker-end="url(#arrow)" />
</svg>

How to modify the size of a <g> (SVG element)?

I can not seem to succeed at modifying the size of my element that is rendered inside a recharts graph as X axis. I want it to be 20px height and width. I couldn't even succeed by making modifications in the console css to the element. Could anyone help me out?
Here's the element:
<svg
style={{ cursor: 'pointer', }} width="20px" height="20px"
>
<g transform={`translate(10,10)`} fill="green" stroke="green">
<path
fill="current"
fillRule="evenodd"
d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z"
transform="translate(.5)"
/>
</g>
</svg>
As #enxaneta recommended, a negative viewBox offset like viewBox="-0.5 -0.5 17 17" is a straight forward solution.
Alternatively, you could scale your <g> (or your path) like so:
.svg{
display:inline-block;
width:10em;
border: 1px solid #ccc
}
<svg class="svg" viewBox="0 0 16 16">
<g transform="scale(0.94117647)" transform-origin="8 8" stroke-width="1" fill="green" stroke="green">
<path d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z" ></path>
</g>
</svg>
Edit: correct scaling value
As #Carsten Massmann has pointed out it should be:
The scaling factor 0.94117647 is the result of
16/17 (original svg width / svg width + stroke-width)
transform-origin="8 8" ensures we're scaling from the center of our viewBox.
Another workaround might be to set overflow to visible to avoid any cropping:
.svg{
display:inline-block;
width:10em;
border: 1px solid #ccc
}
<svg overflow="visible" class="svg" viewBox="0 0 16 16">
<path stroke-width="1" fill="green" stroke="green" d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z" ></path>
</svg>
Caveats: your icon will be displayed larger than your original design and might cause layout inconsistencies when used with other elements that fit the 16x16 boundaries.
If it will be useful to you, I found svg similar to yours and I demonstrated how you can add styles
svg {
background: #479840;
border-radius: 50%;
}
path {
filter: invert(99%) sepia(99%) saturate(2%) hue-rotate( 205deg)
brightness(110%) contrast(100%);
}
<svg height="44" viewbox="0 0 24 24" width="44" xmlns="http://www.w3.org/2000/svg">
<path d="m10 15.586-3.293-3.293-1.414 1.414L10 18.414l9.707-9.707-1.414-1.414z"></path></svg>

CSS background-image .SVG not animating on IOS

I have the following CSS class:
&.loading {
background: url(/svg/loading_animated/fff.svg) $actionColor no-repeat center;
}
This loads this SVG image:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block;" width="200" height="200" viewBox="0 0 100 100">
<circle cx="50" cy="50" fill="none" stroke="#fff" stroke-width="15" r="41" stroke-dasharray="193 66">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 50 50" to="360 50 50" dur="1.1s" repeatCount="indefinite"></animateTransform>
</circle>
</svg>
This works fine on desktop, but on iPhone/IOS, the animation does not work. When I navigate straight to the SVG, I do see the animation.
When I embed the SVG into my CSS class, it also animates:
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='margin: auto; background: none; display: block;' width='200' height='200' viewBox='0 0 100 100'> <circle cx='50' cy='50' fill='none' stroke='white' stroke-width='15' r='41' stroke-dasharray='193 66'><animateTransform attributeName='transform' attributeType='XML' type='rotate' from='0 50 50' to='360 50 50' dur='1.1s' repeatCount='indefinite'></animateTransform></circle></svg>") $actionColor no-repeat center;
That seems to be the solution, but I'd rather have it work with the URL (this fits my code better).
Is there a way to keep the SVG animated on iOS, while using it as a background-image?

Before pseudo element not showing up on path element

Hi i am trying to create a 'pin' on a SVG map of the whole world, the SVG is build with path elements, my thought was to use a before or after element and show the pin accordingly.
Apparently it is not showing on the path element, i can see it in the debugger/console and if i put it on a div element it works fine and shows up, i have cut out all countries except the first one in the SVG for simplicity.
CSS
.map-pin::after{
content: url('pin.svg');
background-size: 30px 30px;
background-repeat: no-repeat;
background-position: left top;
width: 30px;
height: 30px;
z-index: 10;
font-size: 1px;
display: inline-block;
position: absolute;
left: -999px;
top: -999px;
/*display: none;*/
}
.map-pin.active::after{
display: block;
}
.map-pin.active[data-id="AF"]::after{
top: 0;
left: 0;
}
SVG
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" style="stroke-linejoin: round; stroke:#000; fill: none;" viewBox="0 0 2000 1001" id="svg2" inkscape:version="0.48.4 r9939" sodipodi:docname="world.svg">
<defs id="defs4">
<style type="text/css" id="style6">path { fill-rule: evenodd; }</style>
</defs>
<g id="countries">
<path id="AF" data-name="Afghanistan" data-id="AF" class="map-pin active" d="m 1369.9,333.8 -5.4,0 -3.8,-0.5 -2.5,2.9 -2.1,0.7 -1.5,1.3 -2.6,-2.1 -1,-5.4 -1.6,-0.3 0,-2 -3.2,-1.5 -1.7,2.3 0.2,2.6 -0.6,0.9 -3.2,-0.1 -0.9,3 -2.1,-1.3 -3.3,2.1 -1.8,-0.8 -4.3,-1.4 -2.9,0 -1.6,-0.2 -2.9,-1.7 -0.3,2.3 -4.1,1.2 0.1,5.2 -2.5,2 -4,0.9 -0.4,3 -3.9,0.8 -5.9,-2.4 -0.5,8 -0.5,4.7 2.5,0.9 -1.6,3.5 2.7,5.1 1.1,4 4.3,1.1 1.1,4 -3.9,5.8 9.6,3.2 5.3,-0.9 3.3,0.8 0.9,-1.4 3.8,0.5 6.6,-2.6 -0.8,-5.4 2.3,-3.6 4,0 0.2,-1.7 4,-0.9 2.1,0.6 1.7,-1.8 -1.1,-3.8 1.5,-3.8 3,-1.6 -3,-4.2 5.1,0.2 0.9,-2.3 -0.8,-2.5 2,-2.7 -1.4,-3.2 -1.9,-2.8 2.4,-2.8 5.3,-1.3 5.8,-0.8 2.4,-1.2 2.8,-0.7 -1.4,-1.9 z" style="fill:#f2f2f2;fill-rule:evenodd"></path>
</g>
</svg>
I also tried a more simple way by just adding an element inside the SVG after all the path elements, but this breaks the whole SVG.
Anyone able to help me out here, is it not possible in SVG path elements? and if so, what other options am i left with?
PIN:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" style="enable-background:new 0 0 512 512;" viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#454545;stroke-width:18;stroke-miterlimit:10;}
</style>
<g>
<g id="XMLID_4245_">
<path class="st0" d="M389.3,208.7c0-73.6-59.7-133.3-133.3-133.3c-73.6,0-133.3,59.7-133.3,133.3 c0,32.6,12.1,62,31.5,85.1l55.3,75.4l46.6,67.5l101.8-142.9C377.2,270.7,389.3,241.2,389.3,208.7z" id="XMLID_4247_"></path>
<path class="st0" d="M311,170.9L311,170.9c-12.1-11.6-31.7-11.6-43.8,0l-10.9,10.5L245.3,171 c-12.1-11.6-31.7-11.6-43.8,0c-12.1,11.6-12.1,30.4,0,42l54.7,52.5L311,213C323.1,201.4,323.1,182.6,311,170.9z" id="XMLID_4246_"></path>
</g>
</g>
</svg>
As I've commented you can't have a before pseudo element for a path. However in your case you can have a symbol for the pin and use it at the end of your document. This way it will stay above all the other paths. (a z-index won't work either in SVG).
If you are using a symbol with a viewBox attribute you can give the <use> element a position (x and y attributes) and a size (width and height attributes)
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" style="stroke-linejoin: round; stroke:#000; fill: none;" viewBox="1280 320 100 100" id="svg2" >
<defs id="defs4">
<style type="text/css" id="style6">path { fill-rule: evenodd; }</style>
</defs>
<symbol id="map-pin-after" viewBox="0 0 30 30">
<circle cx="15" cy="8" r="8" /> <polygon points="15,30 22.7,10 7.3,10 15,30"/>
</symbol>
<g id="countries">
<path id="AF" data-name="Afghanistan" data-id="AF" class="map-pin active" d="m 1369.9,333.8 -5.4,0 -3.8,-0.5 -2.5,2.9 -2.1,0.7 -1.5,1.3 -2.6,-2.1 -1,-5.4 -1.6,-0.3 0,-2 -3.2,-1.5 -1.7,2.3 0.2,2.6 -0.6,0.9 -3.2,-0.1 -0.9,3 -2.1,-1.3 -3.3,2.1 -1.8,-0.8 -4.3,-1.4 -2.9,0 -1.6,-0.2 -2.9,-1.7 -0.3,2.3 -4.1,1.2 0.1,5.2 -2.5,2 -4,0.9 -0.4,3 -3.9,0.8 -5.9,-2.4 -0.5,8 -0.5,4.7 2.5,0.9 -1.6,3.5 2.7,5.1 1.1,4 4.3,1.1 1.1,4 -3.9,5.8 9.6,3.2 5.3,-0.9 3.3,0.8 0.9,-1.4 3.8,0.5 6.6,-2.6 -0.8,-5.4 2.3,-3.6 4,0 0.2,-1.7 4,-0.9 2.1,0.6 1.7,-1.8 -1.1,-3.8 1.5,-3.8 3,-1.6 -3,-4.2 5.1,0.2 0.9,-2.3 -0.8,-2.5 2,-2.7 -1.4,-3.2 -1.9,-2.8 2.4,-2.8 5.3,-1.3 5.8,-0.8 2.4,-1.2 2.8,-0.7 -1.4,-1.9 z" fill="#f2f2f2"></path>
</g>
<use xlink:href="#map-pin-after" stroke="none" fill="red" width="30" height="30" x="1310" y="327"/>
</svg>
UPDATE
An update where I'm using the OP's pin:
Since the new pin is not a square, and in order to preserve the aspect ratio, I had to recalculate the height of the pin.
<svg viewBox="1280 320 100 100" >
<defs>
<symbol id="map-pin-after" viewBox="111 60 290 397">
<g id="XMLID_4245_" fill="none" stroke="#454545" stroke-width="18" stroke-mitterlimit="10">
<path d="M389.3,208.7c0-73.6-59.7-133.3-133.3-133.3c-73.6,0-133.3,59.7-133.3,133.3 c0,32.6,12.1,62,31.5,85.1l55.3,75.4l46.6,67.5l101.8-142.9C377.2,270.7,389.3,241.2,389.3,208.7z" ></path>
<path d="M311,170.9L311,170.9c-12.1-11.6-31.7-11.6-43.8,0l-10.9,10.5L245.3,171 c-12.1-11.6-31.7-11.6-43.8,0c-12.1,11.6-12.1,30.4,0,42l54.7,52.5L311,213C323.1,201.4,323.1,182.6,311,170.9z" ></path>
</g>
</symbol>
</defs>
<g id="countries">
<path id="AF" data-name="Afghanistan" data-id="AF" class="map-pin active" d="m 1369.9,333.8 -5.4,0 -3.8,-0.5 -2.5,2.9 -2.1,0.7 -1.5,1.3 -2.6,-2.1 -1,-5.4 -1.6,-0.3 0,-2 -3.2,-1.5 -1.7,2.3 0.2,2.6 -0.6,0.9 -3.2,-0.1 -0.9,3 -2.1,-1.3 -3.3,2.1 -1.8,-0.8 -4.3,-1.4 -2.9,0 -1.6,-0.2 -2.9,-1.7 -0.3,2.3 -4.1,1.2 0.1,5.2 -2.5,2 -4,0.9 -0.4,3 -3.9,0.8 -5.9,-2.4 -0.5,8 -0.5,4.7 2.5,0.9 -1.6,3.5 2.7,5.1 1.1,4 4.3,1.1 1.1,4 -3.9,5.8 9.6,3.2 5.3,-0.9 3.3,0.8 0.9,-1.4 3.8,0.5 6.6,-2.6 -0.8,-5.4 2.3,-3.6 4,0 0.2,-1.7 4,-0.9 2.1,0.6 1.7,-1.8 -1.1,-3.8 1.5,-3.8 3,-1.6 -3,-4.2 5.1,0.2 0.9,-2.3 -0.8,-2.5 2,-2.7 -1.4,-3.2 -1.9,-2.8 2.4,-2.8 5.3,-1.3 5.8,-0.8 2.4,-1.2 2.8,-0.7 -1.4,-1.9 z" fill="#f2f2f2" stroke="black"></path>
</g>
<use xlink:href="#map-pin-after" stroke="none" fill="red" width="41" height="30" x="1305" y="327"/>
</svg>

Responsive clip-path with inline SVG

On an element with a background (image or solid color don't really matter):
<header id="block-header"></header>
I am trying to apply a clip-path using SVG. To achieve this, I am putting SVG inline into the same element like this:
<header id="block-header">
…
<svg width="100%" height="100%" viewBox="0 0 4000 1696" preserveAspectRatio="none">
<defs>
<clipPath id="myClip">
<path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
</clipPath>
</defs>
</svg>
…
</header>
You can run the code snippet below or check the JSFiddle. You can see original SVG image (in black) put inline, having curviness along the bottom and being responsive. In contrast, the red rectangle shows the same image applied (or, rather, not applied) as a clip-path.
I guess I misunderstand either viewBox or preserveAspectRatio attributes though can not find what is exactly wrong here. Any help would be appreciated.
#block-header {
background: Red;
min-height: 100px;
-webkit-clip-path: url(#myClip);
clip-path: url(#myClip);
}
<h1>SVG image</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none"><path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/></svg>
<h1><code>clip-path</code> using the same SVG</h1>
<header id="block-header">
<svg width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none">
<defs>
<clipPath id="myClip">
<path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
</clipPath>
</defs>
</svg>
</header>
References to SVG clip paths are to the clip path definitions themselves and the dimensions or other attributes of the <svg> are meaningless in this context.
What is happening in your example is that you are applying a 4000 px wide clip path to your header. Which is probably only of the order of 900 px wide. So the curvature isn't visible.
If you want a responsive clip path, you should define it using clipPathUnits="objectBoundingBox".
#block-header {
background: Red;
min-height: 100px;
-webkit-clip-path: url(#myClip);
clip-path: url(#myClip);
}
<h1>SVG image</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1 1" preserveAspectRatio="none"><path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/></svg>
<h1><code>clip-path</code> using the same SVG</h1>
<header id="block-header">
<svg width="0" height="0">
<defs>
<clipPath id="myClip" clipPathUnits="objectBoundingBox">
<path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/>
</clipPath>
</defs>
</svg>
</header>
Fiddle here

Resources