I tried to display a circle centered in a div.
This is my solution, but the circle appears cut.
What is the problem?
<svg>
<svg x="10%" y="20%">
<g transform="scale(1, 1)">
<circle r="100"/>
</g>
</svg>
</svg>
JSFiddle
By default inner <svg> elements clip their contents. You can set overflow="visible" if you don't want this to happen.
In addition the outer <svg> element has no width/height so it falls back to the defaults of 300 x 150.
If you fix it, it looks like this
html, body {
width: 100%;
height: 100%;
}
<svg width="100%" height="100%">
<svg x="50%" y="50%" overflow="visible">
<g transform="scale(1,1)">
<circle r="100"></circle>
</g>
</svg>
</svg>
Related
Ideally, I'd like to have this svg at the right side of my screen, and become mobile friendly. I was looking into media queries, but I realized I would have to code the exact position for every different media size. Let me know if there is an efficient way of making the svg position mobile friendly.
Here is the code:
<!-- side design neon pink -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="87.43" height="867.24" viewBox="0 0 87.43 867.24">
<defs>
<clipPath id="clip-path">
<rect width="87.43" height="867.24" fill="none"/>
</clipPath>
</defs>
<g id="Repeat_Grid_1" data-name="Repeat Grid 1" clip-path="url(#clip-path)">
<g transform="translate(-287.868 -0.348)">
<path id="wave_2_" data-name="wave (2)" d="M-40.233,309.629l67.77-59.788C55,217.986,69.618,180.03,124.543,186.934,179.469,193.353,274.7,243.422,329.627,237c54.925-6.9,130.937-40.482,185.862-53.806s88.765-3.969,143.69,27.886c54.926,32.339,109.851,32.339,137.314,32.339h27.463V359.7H.074Z" transform="matrix(-0.017, -1, 1, -0.017, 124.954, 830.456)" fill="#f638dc"/>
</g>
</g>
</svg>
Any help/comment is greatly appreciated. Thank you!
Try removing the width and height of the SVG.
Wrap SVG in parent container <div class =" container ">
And give it width and height in relative units.
This will make your application responsive.
.container {
width:5vw;
height:5vh;
}
<div class="container">
<!-- side design neon pink -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 87.43 867.24" style="border:1px solid">
<defs>
<clipPath id="clip-path">
<rect width="87.43" height="867.24" fill="none"/>
</clipPath>
</defs>
<g id="Repeat_Grid_1" data-name="Repeat Grid 1" clip-path="url(#clip-path)">
<g transform="translate(-287.868 -0.348)">
<path id="wave_2_" data-name="wave (2)" d="M-40.233,309.629l67.77-59.788C55,217.986,69.618,180.03,124.543,186.934,179.469,193.353,274.7,243.422,329.627,237c54.925-6.9,130.937-40.482,185.862-53.806s88.765-3.969,143.69,27.886c54.926,32.339,109.851,32.339,137.314,32.339h27.463V359.7H.074Z" transform="matrix(-0.017, -1, 1, -0.017, 124.954, 830.456)" fill="#f638dc"/>
</g>
</g>
</svg>
</div>
I added a class to my svg, then I added translate (im positioning for iphone x 375px
width):
.neon_pink_svg {
transform: translate(287.87px, -32px);
vertical-align: top;
overflow: hidden;
z-index: -1;
position: fixed;
}
I'm having a problem coverting inline SVG to be wrapped in divs. I was using nested SVGs before and now I'm told I have to use nested divs with inline SVG.
Basically, I need the SVG to be sized to the "container" - the "container" is size to the browser window.
For an example of what works before I tried the whole div thing:
SVG Only Example - works perfectly
<html>
<body>
<svg id="container" style="position:relative;border:dashed;width:100%;height:100%;" viewBox="0 0 1000 500">
<svg id="background" name="Box" x="0" y="0">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
<svg id="shape" name="Triangle" x="275" y="50" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</svg>
</svg>
</body>
</html>
But when I try to wrap divs around them, it just stays the same size as my viewBox, no matter what I've tried. I've looked up a lot on this on SO and elsewhere and nothing seems to work: padding tricks, 100vw, width, height, etc.
Here's the latest of what I've tried:
SVG wrapped in DIV Example - doesn't behave the same
<html>
<body>
<div id="container" style="position:relative;border:dashed;width:100%;height:0;margin:5px">
<div id="background" style="position:absolute;left:0px;top:0px;width:1000px;height:500px;">
<svg name="Box" viewBox="0 0 1000 500">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;left:275px;top:50px;width:371px;height:378px;">
<svg name="Triangle" viewBox="0 0 371 378" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
</div>
</body>
</html>
I put a "border:dashed;" in the first div, just to make sure it is resizing with the browswer window and it is. It's just that everything inside that div doesn't change.
Any advice on how to get the "wrapped in div" strategy to match the "plain SVG" strategy?
More clarity:
I guess what I'm saying is that "background" shape needs to be 1000w x 500h, relative to the "container" size. Any of it's children need to be absolutely positioned inside of that 1000w 500h and relative to it. The "container" size is the available space. So if if the browser window is 3000w x 2000h, then technically the "background" shape should be 3000w x 1500h (and the child shapes resize accordingly too - but the stay in their original relative position - relative to 1000w x 500h). If the window 800 w by 600 h, the "background" and child shapes shrink to fit that, relatively. Just like the SVG example.
It might be helpful to take the SVG example above, save it as an html file, launch locally and resize your browser up and down. That's what I'm to find help with, but divs don't seem to know how to handle this.
There's no real equivalent to viewBox property of SVG on DIV elements. The closest one would transform scale. So if you give your div containers a specific size in pixel without adjusting on resize, you're going to somewhat override the viewbox calculations.
That being said, if your div containers are resized with the window, then it can work. Also with minimal javascript you can get the same result as viewbox.
For the css only solution, you define your div containers so they are 100% the size of the window. The SVG viewbox is then still making the calculations. You'll need to define a preserveAspectRatio to have the same behavior as your SVG example. Like this:
html, body {
width: 100%;
height: 100%;
padding: 0px;
margin:0px;
}
* {
box-sizing: border-box;
}
<div id="container" style="position:relative;border:dashed;width:100%;height:100%;">
<svg name="Box" style="position:relative;width:100%;height:100%;" viewBox="0 0 1000 500" preserveAspectRatio="xMinYMin">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;left:0px;top:0px;height:100%;width:100%;">
<svg style="position:relative;width:100%;height:100%;" viewBox="0 0 1000 500" preserveAspectRatio="xMinYMin">
<svg id="shape" name="Triangle" x="275" y="50" width="371" height="378" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</svg>
</div>
</div>
For the javascript solution, you define the size on your div containers, and your svg can then be relative and not have the positioning info. And on resize you adjust the scale based on the innerWidth. Like this:
window.onload = window.onresize = calculateScale
function calculateScale() {
var scaleFactor = innerWidth / 1000;
document.getElementById('container').style.transform = `scale(${scaleFactor})`
}
html,
body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
* {
box-sizing: border-box;
}
<div id="container" style="position:absolute;border:dashed;width:1000px;height:500px;transform-origin: left top">
<svg name="Box" style="position:relative;width:100%;height:100%;">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;width: 371px;height: 378px;top: 50px;left: 275px;">
<svg style="width: 100%; height: 100%" id="shape" name="Triangle" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
I think I got what you are looking for but this is two different svgs not the same vector image.
I'm wrapping both svgs with a div and im overlaying the second div using an absolute position.
<html>
<body>
<div id="containerouter" style="position:relative;border:dashed;width:100%;height:100%;margin:0;">
<div id="background" style="position:relative;width:100%;height:100%;">
<svg name="Box" viewBox="0 0 1000 500">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
</svg>
</div>
<div id="shape" style="position:absolute;height:100%; width:auto;left:175px;top:10%;">
<svg name="Triangle" viewBox="0 0 371 378" fill="red" stroke="yellow" stroke-width="3" x="0" y="0" height="75%">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
</body>
</html>
Like this?
<html>
<body>
<div class="container" style="width:100%; height:100%;">
<div class="container" style="width:100%; height:100%;">
<svg id="container" style="position:relative;border:dashed;width:100%;height:100%;" viewBox="0 0 1000 500">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
<foreignObject x="275" y="50" width="371px" height="378px">
<div class="container" style="width:100%; height:100%;">
<svg id="shape" name="Triangle" x="0" y="0" fill="red" stroke="yellow" stroke-width="3" width="100%" height="100%">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</foreignObject>
</svg>
</div>
</div>
</body>
</html>
EDIT: Changed the snippet.
This version uses a <foreignObject> to wrap the inner svg with a div element. Outcome is as expected.
If you are trying to have something like this:
<div>
<div>
<svg> <!-- rect --> </svg>
</div>
<div>
<svg> <!-- triangle --> </svg>
</div>
</div>
Then you'll need to overlay the divs on top of one another and you can't manipulate the svg any further
There are similar questions like this, but none are identical.
The goal is to scale text as its enclosing rectangle or SVG element scales.
In the example below, the enclosing SVG element is 200x300.
The goal is for the whole element to preserve proportionality, including text.
If you scale by 0.5 to 100x150, the text should scale accordingly.
However, changing the size to 100x150 scales the SVG element correctly, but the text remains the same size and no longer retains the same proportions to the enclosing container.
Code pen: https://codepen.io/anon/pen/BvLZKv?page=1&
<svg width="200" height="300">
<g>
<rect x="0" y="0" width="100%" height="100%" fill="red"></rect>
<text x="50%" y="50%" font-family="Verdana" font-size="20" fill="blue" dominant-baseline="middle" text-anchor="middle">Hello</text>
</g>
</svg>
You can create the base svg and scale that entire svg with a scale value, then the text also will be scaled.
Here is a demo in which I scaled the svg to .5, the entire svg with the text is scaled to half.
svg {
transform: scale(.5);
transform-origin: 0% 0%;
}
<svg width="200" height="300">
<g>
<rect x="0" y="0" width="100%" height="100%" fill="red"></rect>
<text x="50%" y="50%" font-family="Verdana" font-size="82" fill="blue" dominant-baseline="middle" text-anchor="middle">Hello</text>
</g>
</svg>
I have a SVG that needs to have a fixed height so its not super big when the width is 2000+ pixels (widescreens...)
The clipping mask should always be visible and the background image should be sliced and not be stretchend, i tried several things but nothing seems to work.
This is what i have now:
https://codepen.io/bucky208/pen/OEqbPp
div {
width: 100%;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1381.5" preserveAspectRatio="none" style="display: block; position: absolute; width: 100%;height: 400px;">
<g id="clipgroup">
<defs>
<polygon id="mask" points="0,572.1 0,1381.3 1024,1040.5 1024,337.6 0,0"/>
</defs>
<clipPath id="mask_1_">
<use xlink:href="#mask" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#mask_1_);">
<image style="overflow:visible;" width="331" height="444" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" transform="matrix(3.1119 0 0 3.1111 -3.0528 -2.604167e-04)"></image>
</g>
</g>
</svg>
</div>
Do i need another wrapper around everything? How do i restore the image ratio?
Kind regards and a big thank you for everyone trying to help.
In order to get image fills to fill their container but preserve the original aspect ratio, a filter combined with objectBoundingBox sizing and preserveAspectRatio is your friend. The following code does what I think you want:
svg {
background: red;
}
#svgcont {
position: absolute;
width: 100%;
}
<div id="svgcont">
<svg x="0" y="0" width="100%" height="800px">
<defs>
<filter id="image-fill-nostretch" primitiveUnits="objectBoundingBox">
<feImage x="0" y="0" width="1" height="1" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" preserveAspectRatio="xMidYMid slice"/>
<feComposite operator="in" x1="SourceGraphic"/>
</filter>
<clipPath id="mask_1_" clipPathUnits="objectBoundingBox">
<polygon id="mask" points="0,0.5 0,1 1,0.75 1,0.25 0,0"/>
</clipPath>
</defs>
<g clip-path="url(#mask_1_)">
<rect width="100%"height="100%" x="0%" y="0%" filter="url(#image-fill-nostretch)"/>
</g>
</svg>
</div>
I have the fiddle with this problem. If I set viewBox property on the symbol element, icon displayed correctly. But if I set viewBox with same value on svg element with use inside, around use element appears weird empty space, inside of SVG-container.
Viewport of first variant is the same with viewport of second variant - 35x35px size at 2.5x3.5px coords.
What's the reason of this behavior? Bug or my own mistake?
EDIT: Add picture with correct and incorrect areas.
#svg-icons {
display: none;
}
.icon {
display: inline-block;
border: 1px solid red;
}
.icon + .icon {
margin-left: 20px;
}
<svg version="1.1" id="svg-icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="icon-1" viewBox="2.5 3.5 35 35">
<rect x="2.5" y="3.5" stroke="#000000" stroke-miterlimit="10" width="35" height="35" />
<circle fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" cx="20" cy="21" r="14" />
</symbol>
<symbol id="icon-2">
<rect x="2.5" y="3.5" stroke="#000000" stroke-miterlimit="10" width="35" height="35" />
<circle fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" cx="20" cy="21" r="14" />
</symbol>
</svg>
<svg class="icon icon-1" width="100" height="100">
<use xlink:href="#icon-1"></use>
</svg>
<svg class="icon icon-2" viewBox="2.5 3.5 35 35" width="100">
<use xlink:href="#icon-2"></use>
</svg>
This probrem will be solved by thinking about how the use element is treated on drawing.
According to SVG 1.1 2nd edition, use element refers symbol element is treated as svg element on drawing. So the result by that svg structure is same as this.
<svg class="icon icon-2" viewBox="2.5 3.5 35 35" width="100">
<g>
<svg width="100%" height="100%">
<rect x="2.5" y="3.5" stroke="#000000" stroke-miterlimit="10" width="35" height="35" />
<circle fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" cx="20" cy="21" r="14" />
</svg>
</g>
</svg>
Inner svg element has range of 100% width and height positioned at (0,0), and outer svg element has viewBox offset to (2.5, 3.5).
Thus shapes are cutoff by displacement of 2 svg element's rendering ranges.