Something trimming hastag from svg href - svg

I have a sprite with icons. Everything is good when I'm working on localhost. But when I'm uploading files on hosting, something trimming my #plus after .svg.
Only this icon, other icons showing.
<span #click="increment">
<svg class="icon icon-plus">
<use href="../assets/icons/feather-sprite.svg#plus" />
</svg>
</span>

Your problem will be because of the way that icon (and many others in that set) are designed. It looks like this:
<symbol id="plus" viewBox="0 0 24 24">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</symbol>
The problem is that the icon is designed using simple straight lines. This is quite unusual for icon libraries. Normally they use filled shapes.
By default SVG shapes have a black "fill" and no "stroke". The fill is the area inside a shape, and the stroke is a boundary of a shape. Straight lines have no inside, so they have no fill to draw. And if a colour and size are not specified for the stroke, it won't be rendered either. That's why the icon is not showing up.
To fix that you need to specify a stroke and stroke-width for the icons that are like this.
.icon {
width: 100;
}
.icon-plus {
stroke: blue;
stroke-width: 4;
}
<svg class="icon icon-plus">
<symbol id="plus" viewBox="0 0 24 24">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</symbol>
<use href="#plus" />
</svg>

Related

What is the proper way to reference an element inside a SVG file from a HTML file?

I'm trying to construct a buttons collection for a website. Since the buttons share several properties (colours and effects) I've decided to use SVG. In order to reduce the HTTP requests, I tried to nest several elements and filters inside the same SVG file. The idea is instantiate these elements to construct all the buttons, toggle switches, etc by simply using the <use> tag.
After reading great articles like this, this, and this I'm still not being able to do such thing. I found myself stuck. So I decided to simplify the problem as much as I could within the snippet down bellow.
<style>
svg,
img,
object {
width: 50px;
height: 50px;
border: 1px solid black;
}
h3 {
margin-top: 50px;
}
</style>
<h1>Swimming Veggies. The SVG club that's driving me nuts.</h1>
<h3>This is an inline SVG.</h3>
<svg viewBox="0 0 50 50">
<g id="pool">
<rect width="50" height="50" fill="aqua" />
</g>
<symbol id="tomato">
<circle cx="35" cy="35" r="10" fill="tomato" />
</symbol>
<g id="orange">
<circle cx="15" cy="15" r="12" fill="orange" />
</g>
</svg>
<p>Things work as expected here. The <g> elements #pool and #orange show up while the <symbol id="tomato"> doesn't. Great!</p>
<h3>This is a SVG using <use> to referencing elements from the inline SVG above.</h3>
<svg style="border: 1px solid black;" width="50" height="50">
<use xlink:href="#pool"></use>
<use xlink:href="#tomato"></use>
</svg>
<p>Note that the <symbol id="tomato"> element shows up here like the g elemet "pool". The "orange" element is NOT being <use>d. Works fine. Expected behaviour.</p>
<h3>This is a SVG being put as an IMG.</h3>
<img src="club.svg">
<p>Works fine to me and the absence of the <symbol id="tomato"> is the expeted behaviour. I don't want to use SVG this way though.</p>
<p> Unfortunately, IMGUR didn't accept SVGs and I didn't find an image sharing platform that accepts SVG files. The "club.svg" file has the same content as the commented code at the end of this HTML snippet. The SVG file is located ON THE SAME FOLDER of the HTML file. Sorry for the inconvenience :(</p>
<h3>This is a SVG being put as an OBJECT</h3>
<object type="image/svg+xml" data="club.svg"></object>
<p>This works as expected.</p>
<p>Again, the "club.svg" file content is shown as a comment inside and at the end of this HTML snippet.</p>
<h3>An unsuccessful attempt to extract elements from an OBJECT SVG </h3>
<object type="image/svg+xml" data="club.svg#tomato"></object>
<p>The browser is ignoring the "#tomato" after the file name. Is it possible to extract/manipulate elements inside the SVG file this way? If so, how?</p>
<h3>This is a SVG being put as an external reference.</h3>
<svg>
<use xlink:href="club.svg#pool"></use>
<use xlink:href="club.svg#tomato"></use>
<use xlink:href="club.svg#orange"></use>
</svg>
<p>That would be my preferable way to clone/manipulate elements from an external source (in this case, "club.svg"). Unfortunately, it's not working for me. It's not clonning the element. What am I doing wrong?</p>
<h3>Here goes the club.svg content (it's commented inside the snippet).</h3>
<!--
Down bellow is the code inside the club.svg file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50">
<g id="pool">
<rect width="50" height="50" fill="aqua" />
</g>
<symbol id="tomato">
<circle cx="35" cy="35" r="10" fill="tomato" />
</symbol>
<g id="orange">
<circle cx="15" cy="15" r="12" fill="orange" />
</g>
</svg>
-->
By the way... I tried to open up the file on Brave, Opera, Chrome and Safari. All of them show the same results.
Any help will be very much appreciated.

multiple instances of external svg

I'm trying to use external svg file to link particular element from svg stack to "background-image"/"content" of the button element using #fragment identifier.
i.e.:
Button1 - background-image: url(icons.svg#fragment1);
Button2 - background-image: url(icons.svg#fragment2);
External icons.svg consists tons of fragments and pretty big.
Everything works perfectly in all browsers. However for each button that needs only one particular fragment it loads whole svg. At the end, having (let's say) 10 buttons, I've got 10 loaded instances of the whole svg.
An ideal solution (IMHO) would be to use the tag "use" with "inlined" SVG but as far as I know such combination wont work.
Using URI encoded fragments not a solution for my particular case.
What would be the best approach?
You can avoid using a background image if you use the svg as a child of your button element.
To use different icons for different states, you can add multiple icons and only make them visible depending on the state of the button.
button:hover use.hover,
button:active use.active {
display: inline;
}
button use:not(.default),
button:hover use.default,
button:active use.default,
button:active use.hover {
display: none;
}
<!-- inline your icons -->
<svg display="none">
<symbol id="icon1" viewBox="0 0 30 20">
<ellipse cx="15" cy="10" rx="15" ry="10" />
</symbol>
<symbol id="icon2" viewBox="0 0 30 20">
<rect x="5" y="5" width="20" height="10" />
</symbol>
<symbol id="icon3" viewBox="0 0 30 20">
<path d="M7,17H23L15,3z" />
</symbol>
</svg>
<button style="width:80px;height:30px;">
<svg width="100%" height="100%">
<use class="default" href="#icon1" />
<use class="hover" href="#icon2" />
<use class="active" href="#icon3" />
</svg>
</button>

Programmatically Fix text into viewBox

I have this svg:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
viewBox="0 0 ' + size + ' ' + size +'" width="'+ boxW +'" height="'+ boxH +'">
<text>Sample Text</text>
</svg>
size: A parameter that is needed to the viewBox in order to create the wrapper.
width & height: the width and height of the container of the text.
I have a function that generate this svg. The problem is that the text is not fitting into the box; the result is like this:
(Is blue due to the Chrome inspector, you can see up in the top-left corner the text being small instead of full size.
The SVG resulted is this:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
viewBox="0 0 580 532">
<text x="0" y="15" style="font-family:Arial;fill:%230000ff;fill-opacity:1;font-weight:normal;font-style:normal;"
>test</text>
</svg>
The whole img is this:
<img src="data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 580 532"><text x="0" y="15" style="font-family:Arial;fill:%230000ff;fill-opacity:1;font-weight:normal;font-style:normal;">test</text></svg>" class="leaflet-marker-icon leaflet-zoom-animated leaflet-interactive" alt="" tabindex="0" style="margin-left: -298px; margin-top: -291px; width: 309px; height: 295px; transform: translate3d(683px, 317px, 0px); z-index: 317; outline: none;">
So my quesiton is: How to fit the text into the main wrapper?
You either have to:
fit the viewBox to the text, or
fit the text to the viewBox.
You are not doing either. You are not even setting a font-size.
Option 1 is not really available to you. You can measure the text if you have access to the SVG DOM, but you can't do that if you aren't in a rendering environment, like a browser.
Perhaps you could use a font loading library to get metadata about the glyphs in the font. Then calculate the size of a piece of text that way. You don't mention which language you are using to produce these SVGs, so I can't advise further on that.
So you are left with option 2. The only option that SVG has to let you fit text to a particular size, is the textLength and lengthAdjust attributes on the <text> element.
textLength
Sets a length to which you want the text to be fitted
lengthAdjust
Sets the method to be used to adjust the length. You can either stretch just the spacing between the letters, or you can stretch the letter glyphs
See the <text> section in the spec for more information
There are no options for adjusting the text height.
svg {
width: 400px;
background-color: linen;
}
<svg viewBox="0 0 200 40">
<line x1="10" y1="30" x2="190" y2="30" stroke="black" opacity="0.2"/>
<text x="10" y="30"
textLength="180"
lengthAdjust="spacing">Sample Text</text>
</svg>
<br/>
<svg viewBox="0 0 200 40">
<line x1="10" y1="30" x2="190" y2="30" stroke="black" opacity="0.2"/>
<text x="10" y="30"
textLength="180"
lengthAdjust="spacingAndGlyphs">Sample Text</text>
</svg>
If you want the font size to be a better match, then you are going to have to work out a method of calculating an approximate font size. Eg.
var numChars = text.length()
var fontSize = (desiredTextWidth / numChars) * someScalingFactor
The scaling factor will depend on your font.
This is my solution: I'm putting the text inside a <symbol>. I get the size of the text with getBBox() and use it to set the viewBox for the <symbol>. Please note that the <use> element has a width of 100%.
let bb = text.getBBox();
test.setAttributeNS(null, "viewBox", `${bb.x} ${bb.y} ${bb.width} ${bb.height}`);
*{font-size:16px;}
svg{border:1px solid;width:90vh}
body{font-family:Arial;fill:#0000ff;fill-opacity:1;font-weight:normal;font-style:normal;}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 580 532">
<symbol id="test">
<text id="text" dominant-baseline="central" text-anchor="middle" >test</text>
</symbol>
<use id="_use" xlink:href="#test" width="100%" />
</svg>

SVG or HTML text that scales to fully fit a container so it stretches, bot vertically and horizontally, disregarding aspect ratio

I need to make text automatically stretch in both dimensions, to fill a container. It will distort.
This shows the the container space in red
This shows what a long name would normally resize to put in that space and maintaining aspect ratio
.
This shows what my client wants to happen
.
I would prefer to use SVG but I will work with what works.
I have searched for a solution to the best of my abilities but all seem to either refer to maintaining aspect ratio or stretching text when the page or viewbox changes dimensions.
That's quite a broad question, but yes you can do it with svg, I'll let you implement it though since you didn't provided anything to chew on.
The key point is to set your svg's preserveAspectRatio to "none":
svg{
height: 100vh;
width: 50vw;
}
body{
margin:0;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 300 40" preserveAspectRatio="none">
<text x="0" y="35" font-family="Verdana" font-size="35">
Hello, out there
</text>
</svg>
</div>
If your text is already part of an SVG (as it appears in your example), you will probably need to use a nested <svg> element.
<svg width="400" height="400">
<rect width="400" height="400" fill="rebeccapurple"/>
<!-- rect representing area that our text has to squeeze into -->
<rect x="20" y="50" width="200" height="50" fill="white"/>
<!-- x y width height match above rect -->
<!-- viewBox values need to match text bounds -->
<svg x="20" y="50" width="200" height="50"
viewBox="0 8 244 28" preserveAspectRatio="none">
<text x="0" y="35" font-family="Verdana" font-size="35">
HELLO THERE
</text>
</svg>
</svg>
The hardest part is workoing out the correct values for viewBox. It needs to match the bounds of the (normal unsqueezed) text.

Scale a svg text to fit an exact width or the parent container width [duplicate]

This is likely a very simple question, but how do I get text in SVG to stretch to fit its container?
I don't care if it looks ugly from being stretched too long or high, but it needs to fits its container and be as big as possible.
Thanks
If you really don't care that the text gets ugly, here's how to fit unknown length text into a known width.
<svg width="436" height="180"
style="border:solid 6px"
xmlns="http://www.w3.org/2000/svg">
<g>
<text y="50%" textLength="436" lengthAdjust="spacingAndGlyphs">UGLY TEXT</text>
</g>
</svg>
Here is what I have come up with... Its similar to what other people have posted, but I think it resizes and scales nicely. This code will add spacing to any text roughly between 10-25 characters to make it fill the entire width of its parent. If you need longer or shorter text, just adjust the viewBox width and textLength attributes.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox='0 0 300 24'>
<text textLength='290' lengthAdjust="spacing" x='5' y="14" >
Some Unknown Text that is resizing
</text>
</svg>
Maybe this could work for you. You'd have to tweak the values, but it does resize when the parent div resizes. Here's my dabblet example. It works similarly to fittext.js
I used the ‘viewBox’ & ‘preserveAspectRatio’ attributes.
<svg><text x="50%" y="50%" dy=".3em">Look, I’m centered!</text></svg>
<svg viewBox="-50 -50 100 100" preserveAspectRatio="xMidYMid meet"><text font-size="16" dy=".3em" >I’m also resizeable!</text></svg>
other resources I looked at:
Making Sense of SVG viewBox's Madness
How to Style Scalable Vector Graphics Using CSS
You can use the textPath tag in conjunction with the text tag. If you then set the lengthAdjust attribute of the textPath tag to "spacingAndGlyphs" (you may additionally use the method attribute and set it to "stretch" to adjust the rendering method).
Example:
<div style="width: 100%">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 200 100"
style="border:solid 6px"
xmlns="http://www.w3.org/2000/svg">
<g>
<path id="svg-text" d="M 10 50 H 180" fill="transparent" stroke="lightgray" />
<text>
<textPath
xlink:href="#svg-text"
method="stretch"
lengthAdjust="spacingAndGlyphs"
>Beautifully resized!</textPath>
</text>
</g>
</svg>
<div>

Resources