Can anyone explain why firefox crops this SVG image? - css

Can anyone explain why firefox crops this SVG image?
It's within a container and being scaled to fit by CSS.
I'm using <symbol> and <use>.
.container {
width: 1em;
height: 1em;
}
svg {
width: 100%;
height: 100%;
}
<svg style="display:none">
<symbol id="icon_triangleup" xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24">
<path d="M12.8,5.4c-0.377-0.504-1.223-0.504-1.6,0l-9,12c-0.228,0.303-0.264,0.708-0.095,1.047 C2.275,18.786,2.621,19,3,19h18c0.379,0,0.725-0.214,0.895-0.553c0.169-0.339,0.133-0.744-0.095-1.047L12.8,5.4z" />
</symbol>
</svg>
<div class="container">
<svg>
<use xlink:href="#icon_triangleup"></use>
</svg>
</div>

I can tell you why, as in, how to fix it. But not why Chrome seems to ignore what's causing the issue in Firefox.
Firefox is using the 24px width and height set on the <symbol> element, so remove those and the symbol will expand to fill the space of it's container.
You can always set the width and height on the <use> element if you want the individual instances of the symbol to be different sizes.
.container {
width: 1em;
height: 1em;
}
svg {
width: 100%;
height: 100%;
}
<svg style="display:none">
<symbol id="icon_triangleup" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12.8,5.4c-0.377-0.504-1.223-0.504-1.6,0l-9,12c-0.228,0.303-0.264,0.708-0.095,1.047 C2.275,18.786,2.621,19,3,19h18c0.379,0,0.725-0.214,0.895-0.553c0.169-0.339,0.133-0.744-0.095-1.047L12.8,5.4z" />
</symbol>
</svg>
<div class="container">
<svg>
<use xlink:href="#icon_triangleup"></use>
</svg>
</div>

Related

Make svg element adapt to container dimensions

I've the following SVG path that is intended to be used as a border of any possible width and height. But currently, I am struggling with the following 2 points and appreciate a lot if some can share some ideas :-)
1. Is it possible to detach SVG from the viewBox and adapt to parent dimension?
2. Is it possible to detach SVG stroke width and always be as defined? (4px)
.c500x200 {
width: 500px;
height: 200px;
}
.c200x600 {
width: 200px;
height: 600px;
}
svg {
width: 100%;
height: 100%;
}
svg path {
stroke-width: 4px;
stroke: #d22f2c;
fill: none;
}
<div class='c500x200'>
<svg data-name="Layer 1" viewBox="0 0 357.5 248" xmlns="http://www.w3.org/2000/svg">
<defs>
</defs>
<path transform="translate(-289 -320)" d="M623,565.5H291.5v-243h341v231s-1,12,14,12"/>
</svg>
</div>
<div class='c200x600'>
<svg data-name="Layer 1" viewBox="0 0 357.5 248" xmlns="http://www.w3.org/2000/svg">
<defs>
</defs>
<path transform="translate(-289 -320)" d="M623,565.5H291.5v-243h341v231s-1,12,14,12"/>
</svg>
</div>
Is it possible to detach SVG from the viewBox and adapt to parent dimension?
The viewBox is the way you get an SVG to adapt to a parent's dimensions. What I think you are asking is whether it is possible to get a viewBox to stretch to fill a parent container.
The answer is yes. You can do that using preserveAspectRatio="none". But note that this stretches the scale of the shape. So curves in the shape will be distorted. See below.
Is it possible to detach SVG stroke width and always be as defined? (4px)
Yes. You can set vector-effect: non-scaling-stroke on the path elements. See below.
.c500x200 {
width: 500px;
height: 200px;
background-color: linen;
}
.c200x600 {
width: 200px;
height: 600px;
background-color: linen;
}
svg {
width: 100%;
height: 100%;
}
svg path {
stroke-width: 4px;
stroke: #d22f2c;
fill: none;
vector-effect: non-scaling-stroke;
}
<div class='c500x200'>
<svg data-name="Layer 1" viewBox="0 0 357.5 248" preserveAspectRatio="none">
<defs>
</defs>
<path transform="translate(-289 -320)" d="M623,565.5H291.5v-243h341v231s-1,12,14,12"/>
</svg>
</div>
<div class='c200x600'>
<svg data-name="Layer 1" viewBox="0 0 357.5 248" preserveAspectRatio="none">
<defs>
</defs>
<path transform="translate(-289 -320)" d="M623,565.5H291.5v-243h341v231s-1,12,14,12"/>
</svg>
</div>

SVG ClipPath: Why does applying the clip path to a DIV have different results to an IMAGE?

I need to create a set of 3 triangles that each have content in them (images, copy, etc).
I have setup this Pen to show roughly what I'm trying to achieve: https://codepen.io/andystent/pen/OJyNdmB
And here is an image for quick reference:
In this example the "Top" and "Left" triangles are IMAGES with the clip-path applied and displaying perfectly.
The "Right" triangle (with the red background) is a DIV with the clip-path applied but the proportions are wrong.
It should look like a mirrored version of the "Left" triangle.
When I apply it to an image it is perfect but when I apply to the div it is not. What is the best way to do this?
I am new to SVG so it is extremely likely that I am not doing this correctly. I have looked at numerous posts and the method I have tried is from a few of those but without success... so now I'm reaching out to you geniuses...
Here's the HTML and CSS for the red "Right" triangle with the clip applied to the DIV in the CSS:
#right-wrapper {
position: absolute;
width: 50%;
height: 100%;
right: 0;
padding: 40px 20px;
box-sizing: border-box;
}
#right-content-div {
background-color: red;
height: 100%;
width: 100%;
position: absolute;
top: 0;
right: 0;
clip-path: url(#clip-path-right);
-webkit-clip-path: url(#clip-path-right);
display: flex;
justify-content: center;
align-items: center;
}
<div id="right-wrapper">
<svg width="100%" height="100%" viewBox="0 0 1220 1214" preserveAspectRatio="none">
<defs>
<clipPath id="clip-path-right">
<path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" id="path-1">
</path>
</clipPath>
</defs>
<div id="right-content-div" preserveAspectRatio="none">
<h1>test heading</h1>
</div>
<!-- <image clip-path="url(#clip-path-right)" height="100%" width="100%" preserveAspectRatio="none" xlink:href="https://www.w3schools.com/css/klematis_big.jpg" /> -->
</svg>
</div>
----- UPDATE: -----
As suggested in the comments, I have created a simplified Pen that gets to the heart of what I'm trying to achieve and the embedded HTML and CSS is below.
Essentially I am trying to get the red <div> to be clipped exactly like the <image>.
https://codepen.io/andystent/pen/RwWRjLd
#right-content-div {
background-color: red;
height: 100%;
width: 100%;
position: absolute;
top: 0;
clip-path: url(#clip-path-right);
-webkit-clip-path: url(#clip-path-right);
}
<svg width="20%" height="20%" viewBox="0 0 1220 1214">
<defs>
<clipPath id="clip-path-right">
<path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" id="path-1">
</path>
</clipPath>
</defs>
<image clip-path="url(#clip-path-right)" height="100%" width="100%" preserveAspectRatio="none" xlink:href="https://www.w3schools.com/css/klematis_big.jpg" />
</svg>
<div id="right-content-div" preserveAspectRatio="none">
<h1>test heading</h1>
</div>
Here is an idea where I will be using mask instead of clip-path. The main trick to correctly set the viewBox (you already have it in your code) add preserveAspectRatio="none" then have a mask size of 100% 100%
.box {
width:200px;
height:200px;
display:inline-block;
background:red;
}
.mask {
-webkit-mask:url('data:image/svg+xml;utf8,<svg preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1220 1214"> <path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" /> </svg>') 0 0/100% 100%;
mask:url('data:image/svg+xml;utf8,<svg preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1220 1214"> <path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" /> </svg>') 0 0/100% 100%;
}
<div class="box mask"></div>
<div class="box mask" style="width:300px;"></div>
<div class="box mask" style="height:300px;"></div>
<img src="https://i.picsum.photos/id/1074/200/200.jpg" class="mask">

Scale SVG clipPath and keep aspect ratio of Image

I have an image inside of an SVG element with a clipPath.
I want the clip path to behave like it is in my codePen https://codepen.io/celli/pen/rNBvmyx with preserveAspectRatio="none" so that I always get the same height for my clipPath which matches the parent and stretch from edge to edge of my browser.
The issue is that I want my image to preserve it's aspect-ratio and not appear squashed, while maintaining that the mask is the only element that is being squeezed and not preserving it's aspect ratio.
I tried adding css to the image to preserve the aspect ratio, but it seems to follow the SVGs preserveAspectRatio="none", but I only want that to apply to my clipPath part of the SVG.
<div id="containerId">
<svg class="svg-graphic" preserveAspectRatio="none" viewBox="0 0 1920 1080" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="auto">
<g>
<clipPath id="svgmask">
<polygon points="0,0 0,650 1920,1045 1920,394 "/>
</clipPath>
</g>
<image clip-path="url(#svgmask)" style="width:100%; height:auto; max-width:100%;" xlink:href="https://img-fotki.yandex.ru/get/5607/5091629.6b/0_612e6_b9039c0d_M.jpg" />
</a>
</svg>
</div>
A solution to your problem would be clipping a div with the image as a background. In this case you use a path instead of a polygon where the coords values are from 0 to 1 and clipPathUnits="objectBoundingBox". This won't work on IE and on Edge: https://caniuse.com/#feat=css-clip-path
*{margin:0;
padding:0;}
#containerId {
width: 100%;
height: 800px;
background-color: green;
}
#media (max-width: 800px) {
#containerId {
width: 100%;
height: 500px;
background: orange;
}
}
.img {
width: 100%;
height: 100%;
background-image: url("https://img-fotki.yandex.ru/get/5607/5091629.6b/0_612e6_b9039c0d_M.jpg");
background-size: cover;
-webkit-clip-path: url(#svgmask);
clip-path: url(#svgmask);
}
<svg height="0" width="0" style="position:absolute;">
<defs>
<clipPath id="svgmask" clipPathUnits="objectBoundingBox">
<path d="M0,0 L0,0.6 1,1 1,0.4"/>
</clipPath>
</defs>
</svg>
<div id="containerId">
<div class="img"></div>
</div>
I found an alternative way to do it that works in IE, without SVG, in-case anyone is interested: https://codepen.io/celli/pen/KKPReKE I wanted to use SVG, but this way seems to be the best solution by using a pseudo element and a rotated div.
<div id="head">
<div id="headAddBkgColor"></div>
</div>
<div id="slantElm"></div>

How to set svg icon to fit the container size?

So, the question is - how to set the svg icon to fit the container size? For not it unfortunately crops without any resize... I cannot figure out how to make my file-svg scale! This is question is not about inline svg manipulation!
div {
width: 50px;
height: 50px;
}
img {
width:100%;
height:100%;
}
<div>
<img src="https://svgshare.com/i/7Bw.svg" viewBox="0 0 10 10" preserveAspectRatio="none">
</div>
You need to define viewBox inside the SVG to able to scale it later:
img {
width:100%;
height:100%;
}
<div style="width:50px;height:50px;">
<img src="https://svgshare.com/i/7EX.svg">
</div>
<div style="width:100px;height:100px;">
<img src="https://svgshare.com/i/7EX.svg">
</div>
Here is the SVG code:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 98">
<circle class='ui-icon__svg ui-icon__border' cx='50' cy='50' r='48' />
<path class='ui-icon__svg' d='M31.5 42.5V36l45-.1.1 22.6H70m0 6.7H25l-.1-22.7H70v22.7zM36 43.1l.1 22-.1-22zm22.9 0l.1 22-.1-22zm-16.3-6.6l.1 6.1-.1-6.1zm22.9 0l.1 6.1-.1-6.1z' />
</svg>

Center Arrows Vertically On Both Sides of Div

I've got two items I can't figure out. I'm trying to center both arrows shown in the image on either side of the div box (no matter what the height, they are always centered). The box is min-height and I need the arrows to be centered depending on the height of the box.
Also, when the media screen kicks in, I want them to always display on the left and right no matter where the user has scrolled. I don't have a clue how to keep them in place when the user scrolls.
Any help you can provide is appreciated.
CSS
#recout{
text-align:center;
width: 80%;
margin: 0 auto;
text-align: center;
}
.recleft,
.recright{
display: inline-block;
width: 50px;
min-height: 550px;
margin: 5px;
}
.recin{
background: #000000;
display: inline-block;
vertical-align:top;
min-height: 550px;
margin: 0;
width: 550px;
border-radius: 70px 70px 0 0;
}
HTML
<div id= "recout">
<div class= "recleft">
<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"
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<circle fill="#9FA1A4" cx="25" cy="25" r="25"/>
<g>
<g>
<path fill="#FFFFFF" d="M31.2,8.4c1,0,2,0.4,2.8,1c0.9,0.7,1.4,1.8,1.4,2.9c0,1.1-0.5,2.2-1.4,2.9l-11.8,10l11.8,10
c0.9,0.7,1.4,1.8,1.4,2.9s-0.5,2.1-1.4,2.9c-1.5,1.3-4,1.3-5.5,0L13.2,28.1c-0.9-0.7-1.4-1.8-1.4-2.9c0-1.1,0.5-2.1,1.4-2.9
L28.4,9.4C29.2,8.8,30.2,8.4,31.2,8.4z"/>
</g>
</g>
</svg>
</div>
<div class= "recin"></div>
<div class= "recright">
<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"
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<circle fill="#9FA1A4" cx="25" cy="25" r="25"/>
<g>
<g>
<path fill="#FFFFFF" d="M20,42c-1,0-2-0.4-2.8-1c-0.9-0.7-1.4-1.8-1.4-2.9c0-1.1,0.5-2.2,1.4-2.9l11.8-10l-11.8-10
c-0.9-0.7-1.4-1.8-1.4-2.9s0.5-2.1,1.4-2.9c1.5-1.3,4-1.3,5.5,0L38,22.3c0.9,0.7,1.4,1.8,1.4,2.9c0,1.1-0.5,2.1-1.4,2.9L22.7,41
C22,41.7,21,42,20,42z"/>
</g>
</g>
</svg>
</div>
If I understand you right you want the svg to be vertically centerd inside the .recleft and .recright respectively.
To do that use position: absolute on a wrapper around the svg (it looks weird when applying it directly to the svg), set top: 50%, this will center the div, and finally apply position: relative to the parent so that the wrapper div is absolutely positioned relative to this parent. See this JSFiddle
For the problem with the mobile view you would need to set position: fixed; like so: https://jsfiddle.net/m9xqnh8y/1/
And for the problem that if the .recin gains in height. I made a flexbox containing recleft, recin and recright, this way the other divs automatically take up the full height and thus the arrows also remain in the middle. See here

Resources