For the life of me, I cannot figure out the issue with the inside the following SVGs:
https://codepen.io/LookyRo/pen/wvjezPE
.svgs-container {
display: flex;
gap: 10px;
text-align: center;
width: 100%;
}
.svgs-container div {
border: 2px solid red;
flex: 1 1 auto;
}
svg {
width: 250px;
}
<div class="svgs-container">
<div>
<h1>Mask BAD</h1>
<svg id="eI1EGNfkb8r1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 300" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"
style="background-color:#000">
<g transform="matrix(.984808 0.173648-.173648 0.984808-41.142952 21.499616)" mask="url(#eI1EGNfkb8r6)">
<g transform="translate(-.244181 1.646644)">
<path d="M107.295374,68.86121c-3.202847,15.480427-37.900356,59.25267-13.345196,66.725979s59.252668,9.074732,70.99644-3.736656s11.209963-46.441282-5.871887-46.441282-27.224199-4.804272-25.088968-24.021353-19.217082-30.960854-21.886121-19.75089s10.676157,18.149466-4.804268,27.224202Z"
transform="translate(-8.760641-5.488538)" fill="#5717d1" stroke="#3f5787" stroke-width="0.6"/>
<rect style="isolation:isolate" width="27.224199" height="154.804271" rx="0" ry="0"
transform="matrix(.866025 0.5-.5 0.866025 243.998411-43.500831)" fill="#d2dbed" stroke-width="0"/>
</g>
<mask id="eI1EGNfkb8r6" mask-type="luminance">
<path d="M107.295374,68.86121c-3.202847,15.480427-37.900356,59.25267-13.345196,66.725979s59.252668,9.074732,70.99644-3.736656s11.209963-46.441282-5.871887-46.441282-27.224199-4.804272-25.088968-24.021353-19.217082-30.960854-21.886121-19.75089s10.676157,18.149466-4.804268,27.224202Z"
transform="matrix(-.865792 1.16328-.884732-.658478 328.565567-28.974333)" fill="#e34242"
stroke-width="0.6"/>
</mask>
</g>
</svg>
</div>
<div>
<h1>Mask GOOD</h1>
<svg id="em67u90McsE1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 300" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"
style="background-color:#000">
<g transform="matrix(.984808 0.173648-.173648 0.984808-41.142952 21.499616)" mask="url(#em67u90McsE6)">
<g transform="translate(-.244181 1.646644)">
<path d="M107.295374,68.86121c-3.202847,15.480427-37.900356,59.25267-13.345196,66.725979s59.252668,9.074732,70.99644-3.736656s11.209963-46.441282-5.871887-46.441282-27.224199-4.804272-25.088968-24.021353-19.217082-30.960854-21.886121-19.75089s10.676157,18.149466-4.804268,27.224202Z"
transform="translate(-8.760641-5.488538)" fill="#5717d1" stroke="#3f5787" stroke-width="0.6"/>
<rect style="isolation:isolate" width="27.224199" height="154.804271" rx="0" ry="0"
transform="matrix(.866025 0.5-.5 0.866025 243.013603-43.327183)" fill="#d2dbed" stroke-width="0"/>
</g>
<mask id="em67u90McsE6" mask-type="luminance">
<path d="M107.295374,68.86121c-3.202847,15.480427-37.900356,59.25267-13.345196,66.725979s59.252668,9.074732,70.99644-3.736656s11.209963-46.441282-5.871887-46.441282-27.224199-4.804272-25.088968-24.021353-19.217082-30.960854-21.886121-19.75089s10.676157,18.149466-4.804268,27.224202Z"
transform="matrix(-.865792 1.16328-.884732-.658478 328.565567-28.974333)" fill="#e34242"
stroke-width="0.6"/>
</mask>
</g>
</svg>
</div>
</div>
The left one renders the elements inside the masked group and slightly casts a shadow where the mask should be. The right one works correctly.
I am seeing this issue un Chrome & Edge, yet Firefox, Opera and Safari displays both of this the same.
The only difference between these 2 SVGs is that the element is slightly moved on the X axis.
Bad: matrix(.866025 0.5-.5 0.866025 243.998411-43.500831)
Good: matrix(.866025 0.5-.5 0.866025 243.013603-43.327183)
All the rest of the code is exactly the same.
Can anyone figure this out?
I am trying to recreate an effect in CSS using an SVG. We have text saved as an SVG and needing to blur the backdrop behind the text only.
I know this is possible with block <div> elements by applying a css style of backdrop-filter: blur(10px);, but I am unable to get the same effect with SVG paths.
This is the desired effect
Here is a snippet of 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="1040.474px" height="209.154px" viewBox="0 0 1040.474 209.154"
enable-background="new 0 0 1040.474 209.154"
xml:space="preserve">
<g opacity="0.4">
<path fill="#FFFFFF" d="M6.336,27.021h78.367v6.485l-20.269,2.433l53.506,134.573l33.778-84.852l-20.267-49.721l-19.998-2.433
v-6.485h78.365v6.485l-21.348,2.433l53.504,134.573l47.561-129.979l-23.781-7.026v-6.485h56.478v6.485l-20.538,7.298
l-63.233,168.35h-16.213l-44.586-108.631l 43.236,108.631H98.212L27.145,35.939L6.336,33.507V27.021z"/>
</g>
</svg>
How can you blur the backdrop behind the letters only?
using clipPath SVG and clipping a duplicate img with the blur filter will get you something like this:
body {
margin 10px;
}
.clipped {
position: absolute;
top: 10px;
left: 10px;
clip-path: url(#svgTextPath);
filter: blur(10px);
}
<img src="https://picsum.photos/id/99/500/300">
<img class="clipped" src="https://picsum.photos/id/99/500/300">
<svg height="0" width="0">
<defs>
<clipPath id="svgTextPath">
<text x="50" y="200" textLength="400px" font-family="Vollkorn" font-size="200px" font-weight="700"> Text </text>
</clipPath>
</defs>
</svg>
I am having a problem with setting up shadow for a svg with mask applied to it. This is the code and jsfiddle: http://jsfiddle.net/3kxnmhfL/
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" height="100%" width="100%" viewBox="0 0 100 100">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<circle cx="50%" cy="50%" r="50%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
<!-- <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" /> -->
</mask>
</defs>
<circle cx="50%" cy="50%" r="50%" fill="red" mask="url(#cut-off-bottom)" filter="url(#shadow)" />
</svg>
</div>
I'd like the shadow to appear only around svg circle and not containing div.
What could be the reason for shadow not showing up?
SVG filters have a "filter region". The filter region defines the area of pixels that the browser uses to store the result of the filters. The default filter region is the bounds of the element (that the filter is applied to) plus a margin around it to allow for filter elements that have results larger than the original element.
By default, that margin is 10% of the width and height, applied to all four sides. However in your case, a stdDeviation of "4" causes the blur to extend further than that 10% margin allowance. The result is a clipped blur, even though the viewBox has been enlarged enough to cater for the full blur.
To fix, this, you just need to bump up the filter region size. An allowance of 20% seems to work okay:
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
In addition, I've simplified the SVG by getting rid of the unnecessary mask. I also tweaked the viewBox to include the part of the blur that extends to the left.
.watch-video-svg {
width: 500px;
height: 500px;
background: linen;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="-5 0 120 120">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
</defs>
<circle cx="50" cy="50" r="50" fill="red" filter=url(#shadow) />
<polygon points="31,20, 31,77, 80,50" fill="white"/>
</svg>
</div>
You need to adjust your mask. Since your element is already a circle you don't need a circle in the mask, a rect to fill all the width/height is enough.
You need to also adjust the viewBox to leave some space for the shadow:
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 120 120">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
</mask>
</defs>
<circle cx="50" cy="50" r="50" fill="red" mask="url(#cut-off-bottom)" filter=url(#shadow) />
</svg>
</div>
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 an SVG inlined to html code. Its is scaled to fit width with preserving aspect ratio. Is there a way to set font size fixed to viewport that can be controlled with media queries?
EDIT:
The problem is when i set fixed font-size within width range the font is resized anyway relative to svg size.
#svg-container {
width: 100%;
padding-bottom: 70%;
overflow: hidden;
border: 1px solid red;
}
#svg-container svg text tspan {
font-size: 14px;
}
#media (min-height: 800px) {
#svg-container svg text tspan {
font-size: 50px;
}
}
<div id="svg-container">
<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"
version="1.1"
viewBox="0 0 500 350"
data-name="Layer 1"
id="Layer_1"
inkscape:version="0.91 r13725"
sodipodi:docname="Desktop_Enhanced.svg"
width="100%"
style="position: absolute; left: 0; top: 0;"
>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1280"
inkscape:window-height="961"
id="namedview51"
showgrid="false"
inkscape:zoom="1.0054235"
inkscape:cx="231.42799"
inkscape:cy="361.93137"
inkscape:window-x="1272"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
fit-margin-bottom="150" />
<metadata
id="metadata75">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Desktop</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3">
<style
id="style5">.cls-1{fill:#da1f26;}.cls-2{fill:#252e43;}.cls-3{fill:#d1d3d4;}</style>
</defs>
<title
id="title7">Desktop</title>
<polyline
id="polyline9"
points="329.4 62.24 343.54 76.39 329.4 90.53"
class="cls-1"
style="fill:#da1f26"
transform="translate(59.579252,-43.513817)" />
<polyline
id="polyline11"
points="333.56 328.83 347.7 342.97 333.56 357.11"
class="cls-2"
style="fill:#252e43"
transform="translate(59.579252,-43.513817)" />
<path
id="path35"
d="m 394.84925,294.48618 -25,0 c -57.81,0 -77.28,-34.66 -96.1,-68.18 -15.35,-27.34 -29.86,-53.16 -63.9,-53.16 l -31.27,0 0,10 31.3,0 c 28.19,0 40.7,22.27 55.18,48.06 9.68,17.23 19.69,35.06 35.5,49.13 18.26,16.22 40.93,24.15 69.33,24.15 l 25,0 z"
class="cls-2"
inkscape:connector-curvature="0"
style="fill:#252e43" />
<path
id="path43"
d="m 390.97925,27.876183 -21.09,0 c -28.4,0 -51.07,7.9 -69.32,24.15 -15.81,14.08 -25.82,31.9 -35.5,49.129997 -14.48,25.79 -27,48.06 -55.18,48.06 l -31.31,0 0,10 31.3,0 c 34,0 48.54,-25.82 63.9,-53.16 18.8,-33.569997 38.3,-68.179997 96.11,-68.179997 l 21.09,0 z"
class="cls-1"
inkscape:connector-curvature="0"
style="fill:#da1f26" />
<path
id="path45"
d="m 429.38925,17.956183 a 14.92,14.92 0 1 0 14.92,14.92 14.92,14.92 0 0 0 -14.92,-14.92 z m 0,21 a 6.08,6.08 0 1 1 6.08,-6.08 6.08,6.08 0 0 1 -6.08,6.08 z"
class="cls-1"
inkscape:connector-curvature="0"
style="fill:#da1f26" />
<path
id="path47"
d="m 433.38925,284.53618 a 14.92,14.92 0 1 0 14.92,14.95 14.92,14.92 0 0 0 -14.92,-14.95 z m 0,21 a 6.08,6.08 0 1 1 6.09,-6.05 6.08,6.08 0 0 1 -6.09,6.05 z"
class="cls-2"
inkscape:connector-curvature="0"
style="fill:#252e43" />
<flowRoot
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="flowRoot4236"
xml:space="preserve"
transform="translate(0,-72.53)"><flowRegion
id="flowRegion4238"><rect
y="179.54243"
x="18.988897"
height="58.373276"
width="94.241196"
id="rect4240" /></flowRegion><flowPara
id="flowPara4242">ZakładaZ</flowPara></flowRoot> <text
x="27.791037"
y="169.90349"
font-size="20px"
id="text49-1"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:15px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#252e43;fill-opacity:1"
sodipodi:linespacing="125%">
<tspan
sodipodi:role="line"
id="tspan4528"
x="27.791037"
y="169.90349">PLEASE CHOOSE</tspan>
</text>
</svg>
</div>
The short answer is no.
If the text is in an SVG with a viewBox, and the SVG gets scaled, its contents get scaled also. There is no way to make the text have a "global" size that is unaffected by the SVG scaling.
The only possible solution would be calculate the scaling factor using Javascript and dynamically update the font size every time the SVG size changed.
I'd recommend nested SVG tags. You can keep your outermost SVG without viewBox and add all text under this tag, while adding a second SVG to cover the full area but using a viewBox.
You'll need to change positions for the text from absolute to relative values, but it works quite well.
That way your text will change position with the svg size but not scale the text. The inner SVG will, though, since you set a viewBox.
Example: JS for variable container, SVG always fills the div.
The scaling is pure SVG.
function changeCircleDiv(element) {
s = document.getElementById("container").style;
s.width = element.value + 'px';
s.height = s.width;
}
body {
font-size: 2em;
}
<input type="number" onchange="changeCircleDiv(this);" value="100"></input>
<div id="container" style="width: 100px; height: 100px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%">
<svg width="100%" height="100%" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="8" stroke="black" fill="none"/>
</svg>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Center</svg>
</svg>
</div>
In the end...
I have removed text from svg and added div text block with absolute positioning inside shared html container. That worked prefect. Div's appearance is controlled over css with media queries - it is independent from svg scaling.
Your can see diagram in action at: https://www.xtech.pl/jak-to-dziala-dla-dostawcy (scroll down to second section on the page, then you can resize your screen to see how it works).
You can do it in this way "Responsive SVG with sticky text"
See here: https://bl.ocks.org/veltman/5cd1ba0b3c623e7b5146
Or... if you want to use media queries for font in SVG, the answer is yes. Run this code snippet.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="200px">
<style>
text {
font-size: 10px;
}
#media (max-width: 600px) {
text {
font-size: 20px;
}
}
#media (max-width: 800px) {
text {
font-size: 16px;
}
}
</style>
<circle cx="50" cy="50" r="50" fill="orange"/>
<text x="50" y="60" text-anchor="middle">Testing</text>
</svg>
I actually found a relatively simple workaround.
using D3's scaleSqrt() you can do some math based on the pixel width that the svg is taking up.
For example if the svg viewbox width is 800, then when the svg has a width of 800px, the scale would be 1. When the pixel width of the svg is 400px, relative to the view box, that would be a scale of 1/2
scaleRatio = d3.scaleSqrt()
.domain([1600, 800, 600, 400, 200, 100])
.range([0.5, 1, 1.5, 2, 4, 8]);
const svgWidth = d3.select(svg).node().getBoundingClientRect().width;
someD3Element.attr('transform', `scale(${scaleRatio(svgWidth)})`);