How to make svg size to fit content text - html

Please check my code link
<div class="suj_content">
<header class="suj_content_hd">
<div id="suj_content_hd_ytb"><iframe class="suj_content_hd_ytb" src="https://www.youtube.com/embed/kOc6ME2J_Us?mute=1&loop=1&playlist=kOc6ME2J_Us&autoplay=1&showinfo=0&controls=0" width="100%" height="100%" frameborder="0"></iframe></div>
<h2>
<svg id="suj_content_svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100% 100%" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%"></rect>
<text>
<tspan x="0" dy="33.333333333333%" alignment-baseline="middle" text-anchor="start">mittel</tspan><tspan x="0" dy="23.222222222222%" alignment-baseline="middle" text-anchor="start">stand</tspan><tspan x="0" dy="23.222222222222%" alignment-baseline="middle" text-anchor="start">digital</tspan> </text>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%"></rect>
</svg>
</h2>
</header>
How can I set the width and height of SVG tag to fit its content (the tspan tags). The number of tspan tags is not fixed.
Thanks

First: you are using an invalid viewBox attribute. No percentages are allowed. The value of the viewBox is fromX fromY width height.
I am using a viewBox where the width is 41 - the width of the bounding box of the text.
Second: I suspect you intend to cut the text from the last rect. In this case you need the text to be white.
console.log(t.getBBox())
text{font-size:16px;}
<svg id="suj_content_svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41 50" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%"></rect>
<text fill="white" id="t">
<tspan x="0" dy="25%" dominant-baseline="middle" text-anchor="start">mittel</tspan>
<tspan x="0" dy="25%" dominant-baseline="middle" text-anchor="start">stand</tspan>
<tspan x="0" dy="25%" dominant-baseline="middle" text-anchor="start">digital</tspan>
</text>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)"></rect>
</svg>

Related

How can I make this SVG mask responsive and keep the shadow at the bottom right of the circle? [duplicate]

This question already has answers here:
How to resize a svg
(2 answers)
Closed 17 hours ago.
I have the below SVG which I am using as a mask to overlay on an image, I am trying to make the circle responsive, so it shrinks on mobile devices but haven't had any luck using view box etc as it removes the mask, I am also trying to position the shadow to the bottom right of the circle, but again I am having trouble making it responsive.
Any help would be greatly appreciated.
svg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2000 1000" preserveAspectRatio="xMidYMin slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="250" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<path id="Shadow" d="M462.231,0c19.593,38.355,29.045,88.448,36.926,138.3,9.125,75.59-104.323,237.333-194.755,250.24C246.323,389.921,51.569,371.964,0,313.148c46.559,91.147,141.283,153.59,250.655,153.59,155.395,0,281.365-125.97,281.365-281.365A280.22,280.22,0,0,0,462.231,0" opacity="0.2" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</svg>
Putting the path inside a g container allowed me to scale the shadow relative to the mask, hope this helps someone in the future.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="16.5%" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<g>
<path id="Shadow" d="m 462.231 0 c 19.593 38.355 29.045 88.448 36.926 138.3 c 9.125 75.59 -104.323 237.333 -194.755 250.24 c -58.079 1.381 -252.833 -16.576 -304.402 -75.392 c 46.559 91.147 141.283 153.59 250.655 153.59 c 155.395 0 281.365 -125.97 281.365 -281.365 a 280.22 280.22 0 0 0 -69.789 -185.373" opacity="0.2" style="transform: scale(0.3) translate(579px, 650px);" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</g>
</svg>

Red border in transparent ellipse if affected by the opacity of the container

this code
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<ellipse cx="50%" cy="50%" rx="100" ry="150" stroke="red" stroke-width="10"/>
</mask>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
</svg>
return this as a result
I want to have this same result, but with a red border instead of gray in the ellipse and that this is not affected by the opacity of the rect.
I also need the inside of the ellipse to be transparent (not white) and that it is not affected by the opacity of the rect.
Is this possible?
If you are asking whether you can include a red ellipse as part of your mask, then the answer is no. Any colours in a mask are converted to alpha values.
If you want a red ellipse around your "hole", then you need to add it as a separate element on top of the rect.
body {
background-color: linen;
}
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<defs>
<!-- pull ellipse out as a reusable shape. Used by mask and for red border. -->
<ellipse id="one" cx="50%" cy="50%" rx="100" ry="150"/>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<use xlink:href="#one" fill="black"/>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
<use xlink:href="#one" fill="none" stroke="red" stroke-width="10"/>
</svg>
for set order you can use tag use with the attribute xlink:href for more detail see this How to use z-index in svg elements?
add fill="#fff" tag and id="one" to ellipse and draw it again with <use xlink:href="#one"/>
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<ellipse id="one" cx="50%" cy="50%" rx="100" ry="150" stroke="red" fill="#fff" stroke-width="10"/>
</mask>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
<use xlink:href="#one"/>
</svg>

Text svg is not vertically centered in ms edge

Maybe somebody knows this case when text doesn't center vertically inside svg block
<pre>
<svg class="mask-text category-title" viewBox="0 0 69.34375 18"><defs><mask id="mask" x="0" y="0" width="100%" height="100%"><text class="svg-text" dominant-baseline="central" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text></mask></defs><text class="svg-text" dominant-baseline="central" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text>
<image class="svg-img" width="100%" height="100%" mask="url(#mask)" xlink:href="/uploads/vendor_groups/images/viz1.jpeg?width=1024&height=643" preserveAspectRatio="xMidYMid slice"></image>
</svg>
</pre>
I tried alignment-baseline and <text y="50%" x="50%" but it doesn't work
In the header of the svg write width="100vw" height="100vh"
In this case, vertical centering will work for the text with x="50%" and alignment-baseline
<pre>
<svg class="mask-text category-title" width="100vw" height="100vh" viewBox="0 0 69.34375 18"><defs><mask id="mask" x="0" y="0" width="100%" height="100%"><text class="svg-text" dominant-baseline="central" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text></mask></defs><text class="svg-text" dominant-baseline="central" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text>
<image class="svg-img" width="100%" height="100%" mask="url(#mask)" xlink:href="/uploads/vendor_groups/images/viz1.jpeg?width=1024&height=643" preserveAspectRatio="xMidYMid slice"></image>
</svg>
</pre>
Now in the browser window there is a frame relative to which it can calculate the vertical midpoint for the text <text y="50%"
UPDATE
You probably wanted to use text as a mask to fill the text with a cropped image.
As it turned out, the format of your image does not load.
So I took another image with exactly the same size as your image with 1024 X 643
<image class="svg-img"
xlink:href="https://i.stack.imgur.com/mlqrC.jpg" width="1024" height="643" mask="url(#mask)">
</image>
Your program had an extra line of text; I commented it out.
The font size was not specified, I chose font-size="250px"
Below is code that is responsive and works in all modern browsers except Edge
<style>
.container {
width:100vw;
height:100vh;
}
</style>
<div class="container">
<svg class="mask-text category-title" viewBox="0 30 1024 643" preserveAspectRatio="xMidYMid meet" >
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%" >
<rect width="100%" height="100%" fill="black" />
<text class="svg-text" font-size="250px" dominant-baseline="central" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text>
</mask>
</defs>
<!-- <text class="svg-text" dominant-baseline="central" font-size="200px" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text> -->
<image class="svg-img"
xlink:href="https://i.stack.imgur.com/mlqrC.jpg" width="1024" height="643" mask="url(#mask)">
</image>
</svg>
</div>
Edge scales and centers the image in a very peculiar way
So I had to replace the percent x = "50%" and y = "50%" with fixed values
In this version of the code, the application remains responsive and works in all modern browsers including Edge
<style>
.container {
width:100vw;
height:100vh;
}
</style>
<div class="container">
<svg class="mask-text category-title" viewBox="0 30 1024 643" preserveAspectRatio="xMidYMi meet">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%" >
<rect width="100%" height="100%" fill="black" />
<text class="svg-text" dominant-baseline="central" font-size="250px" text-anchor="middle" x="512px" y="300px" font-family="Sans-serif" font-weight="900" fill="white">Colour</text>
</mask>
</defs>
<!-- <text class="svg-text" dominant-baseline="central" font-size="250px" text-anchor="middle" x="50%" y="50%" font-family="Sans-serif" font-weight="900" fill="white">Colour</text> -->
<image class="svg-img"
xlink:href="https://i.stack.imgur.com/mlqrC.jpg" width="1024" height="643" mask="url(#mask)">
</image>
</svg>
</div>
The size of the entire text block can be changed by edited the width,height in the parent block - .container

Increase the width of SVG rect

Is it possible to increase the width of a <rect> while keeping the height unchanged?
Use case:
There are different svg shapes that contain text like the one in the below example. Depending on the inputs this text may change. If the text is too long,
I want to increase the width to match the width of the text.
<svg viewBox="0 0 300 100" width="300px" height="100px">
<rect x="0" y="0" width="300" height="100" stroke="red" stroke-width="3px" fill="white"/>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Hello World</text>
</svg>
In the above example, the visible size of the <rect> is 300x100 pixels.
If I want to keep the visible height and increase the width,
I found that I can increase the width value of all svg->width, svg->viewBox->width and rect->width attributes.
<svg viewBox="0 0 400 100" width="400px" height="100px">
<rect x="0" y="0" width="400" height="100" stroke="red" stroke-width="3px" fill="white"/>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Hello World</text>
</svg>
Could this go wrong? Is there a better way?
SVGs are amazing when it comes to filling the box that you give it. Simply create a div container with the required width and height styles and then put the svg inside of it set at 100% width and height. and do the same with each graphic element.
Keep in mind that using this method means you will more than likly need to adjust the padding of the div to place the svg where you need it.
<div style="width:600px; height:150px;">
<svg width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" stroke="red" stroke-width="3px" fill="white"/>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Hello World</text>
</svg>
</div>
<br/>
<div style="width:100px; height:25px;">
<svg width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" stroke="red" stroke-width="3px" fill="white"/>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Hello World</text>
</svg>
</div>

Keep <text> element scaled inside <svg> with viewBox

I'm trying to put some text as labels inside some scaled elements, and the text is too big to fit in the container. What can I do here?
<div class="t_container">
<div class="t_x" style="position: relative;">
<svg position="absolute" viewBox="0 0 6 1" preserveAspectRatio="none">
<g>
<rect x="0" y="0" width="1" height="0.4"><title>Nov-21</title></rect>
<text x="0.5" y="0.5" fill="red">A<text>
</g>
<rect x="1" y="0" width="1" height="1"><title>Nov-22</title></rect>
<rect x="2" y="0" width="1" height="1"><title>Nov-23</title></rect>
<rect x="3" y="0" width="1" height="1"><title>Nov-24</title></rect>
<rect x="4" y="0" width="1" height="1"><title>Nov-25</title></rect>
<rect x="5" y="0" width="1" height="1"><title>Nov-26</title></rect></svg>
</div>
Here is a codepen with the result.
You have a very small custom viewport="0 0 6 1" size. 6px - width, 1px - height, so the font can not be displayed with such parameters.
I increased the size of the viewBox 100 times viewBox="0 0 600 100"
Squares for clarity painted in different colors. You can change their coloring according to your choice.
The text is placed inside the squares. I hope that's exactly what you wanted when you used the command
<title> Nov-24 </ title> inside the squares.
But the command <title> in SVG is a system tooltip, the information from which appears when you hover the cursor.
The size of the tooltip and its font can not be changed, so I added in the squares more tags <text> ... </ text>, the parameters of which you can change.
<div class="t_container">
<div class="t_x" style="position: relative;">
<svg position="absolute" viewBox="0 0 600 100" >
<g>
<rect x="0" y="0" width="100" height="40"><title>Nov-21</title></rect>
<text x="35" y="75" font-size="36" fill="red">A</text>
</g>
<rect x="100" y="0" width="100" height="100" fill="orange">
<title>Nov-22</title></rect>
<text x="125" y="55" font-size="18" fill="white">Nov-22</text>
<rect x="200" y="0" width="100" height="100" fill="orangered">
<title>Nov-23</title></rect>
<text x="225" y="55" font-size="18" fill="white">Nov-23</text>
<rect x="300" y="0" width="100" height="100" fill="green">
<title>Nov-24</title></rect>
<text x="325" y="55" font-size="18" fill="white">Nov-24</text>
<rect x="400" y="0" width="100" height="100" fill="dodgerblue">
<title>Nov-25</title></rect>
<text x="425" y="55" font-size="18" fill="white">Nov-25</text>
<rect x="500" y="0" width="100" height="100" fill="yellowgreen">
<title>Nov-26</title></rect>
<text x="525" y="55" font-size="18" fill="white">Nov-26</text>
</svg>
</div>