I have this SVG:
<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em"
height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"
data-v-41e50536="" data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91
8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
This is a blue star. I want to do add an arbitrary number of these stars to an existing div using JavaScript.
How could I do it?
Update :
This is the existing div (it already has five stars and a short paragraph):
<div class="stars-real-container" id="dsc1">
<svg style="fill:#1780df; color: #1780df; margin-right: 6px; "
xmlns="http://www.w3.org/2000/svg" width=".8em" height=".8em" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-star" data-v-41e50536=""
data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em"
height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"
data-v-41e50536="" data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em"
height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"
data-v-41e50536="" data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em"
height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"
data-v-41e50536="" data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em"
height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"
data-v-41e50536="" data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon>
</svg>
<p class="number-of-comments" id="dc1">(۱۲ نظر )</p>
</div>
Its CSS:
.stars-real-container {
height: 100%;
width: 50%;
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
}
The idea is to have stars to show the popularity of something. I have not ever created SVG elements with JavaScript. I checked several other stackoverflow threads like This. But it was a simple SVG.
There are many options to do that. The easiest way is this one in my opinion.
Updated code:
document.querySelector('.stars-real-container').innerHTML = '<svg style="fill:#1780df; color: #1780df; " xmlns="http://www.w3.org/2000/svg" width=".8em" height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" lass="feather feather-star" data-v-41e50536="" data-v-50fd7d5a=""><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" data-v-41e50536="" data-v-50fd7d5a=""></polygon></svg>' + document.querySelector('.stars-real-container').innerHTML;
To keep your paragraph as the last-child, you have to put the svg as first child and then add the existing content (+ document.querySelector('.stars-real-container').innerHTML)
This is a "deliberate" solution example where I clone the "star". Might be better ways but this is one way. Note I put the color of the star in CSS to illustrate how to do that also - could be done by using classes to provide a value fo the currentColor. I made mine more "pink" :)
Note I went with the "clone" approach so I could put the svg element in the HTML and not have to muck with string constants for the SVG, harder to maintain etc.
let howMany = 4;
let prettystar = document.getElementById("star-container").querySelector('svg');
let targetElement = document.querySelector("#star-target").querySelector('.star-me');
for (let step = 0; step < howMany; step++) {
let pclone = prettystar.cloneNode(true);
console.log(step)
targetElement.appendChild(pclone);
}
.star-me {
color: #df80df;
}
#star-container {
display: none;
}
<div id="star-container">
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" width=".8em" height=".8em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-star" data-v-41e50536=""
data-v-50fd7d5a="">
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91
8.26 12 2"
data-v-41e50536="" data-v-50fd7d5a=""></polygon></svg>
</div>
<div id="star-target"><span>Please make me a star!</span>
<span class="star-me"></span>
</div>
Related
I have two SVG paths that have a gap between them.
From reading through other questions (in particular this one) I understand this is because of the native anti-aliasing properties of SVGs.
So I added shapeRendering="crispEdges"
This does remove the gap. However it results in jagged edges because of the removal of anti-aliasing.
<svg height="300" width="300" shapeRendering="crispEdges">
<path
d="M150 10 a120 120 0 0 1 103.9230 60"
fill="none"
stroke="green"
stroke-width="20"
/>
<path
d="M253.9230 70 a120 120 0 0 1 0 120"
fill="none"
stroke="green"
stroke-width="20"
/>
</svg>
I've also tried the suggestion in this question to add crispEdges to the parent svg of the path and add shapeRendering="optimizeQuality" to the path but that didn't work.
How can I remove the gap AND keep the smooth edges of my svg path?
You could also mitigate this gap rendering effect by applying a subtle svg feMorphology dilate filter – resulting in slightly expanded strokes closing thin gaps between paths:
SVG feMorphology filter
svg {
overflow: visible;
}
.chart path {
filter: url(#outline);
}
path:hover {
stroke: red;
}
<svg height="300" width="300" shape-rendering="geometricPrecision">
<g class="original">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
</g>
<text x="50%" y="50%">Original</text>
</svg>
<svg height="300" width="300">
<filter filterUnits="userSpaceOnUse" id="outline" >
<feMorphology in="SourceGraphic" result="DILATED" operator="dilate" radius="0.5" />
</filter>
<g class="chart">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
</g>
<text x="50%" y="50%">Dilate filter</text>
</svg>
But this approach will also introduce slightly rounded edges (you can see this effect on hover).
More importantly, svg filters are quite expensive with regards to rendering performance – rather negligible if you only display a few elements per page view.
Add concatenated background path
As suggested by #Robert Longson: you could also prepend a background path based on concatenated d path data.
This task could be achieved with a javaScript helper method cloning the first path and displaying the concatenated paths.
addBgPaths(".addBGPath");
function addBgPaths(selector) {
let addPathSvgs = document.querySelectorAll(selector);
addPathSvgs.forEach(function(svg) {
let paths = document.querySelectorAll(".addBGPath path");
let firstPath = paths[0];
let firstPathCloned = firstPath.cloneNode();
//cloned elements shouldn't have ids to avoid non unique ids
firstPathCloned.removeAttribute("id");
let dArr = [firstPath.getAttribute("d")];
for (let i = 1; i < paths.length; i++) {
let path = paths[i];
let d = path.getAttribute("d");
dArr.push(d);
}
firstPathCloned.setAttribute("d", dArr.join(" "));
svg.insertBefore(firstPathCloned, svg.children[0]);
});
}
<svg height="300" width="300" shape-rendering="geometricPrecision">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
<text x="0" y="50%">Original</text>
</svg>
<svg class="addBGPath" height="300" width="300" shape-rendering="geometricPrecision">
<path id="first2" d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
<text x="0" y="50%">Add bg path</text>
</svg>
<svg class="addBGPath" height="300" width="300" shape-rendering="geometricPrecision">
<path id="first" d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="red" stroke-width="20" />
<text x="0" y="50%">Add bg path (red)</text>
</svg>
<svg height="300" width="300" shape-rendering="geometricPrecision">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="red" stroke-width="20" />
<text x="0" y="50%">Original (red)</text>
</svg>
If all your path segments have the same color, this is probably the most elegant solution.
But this approach will also introduce colored "halos" when segments use different stroke colors (example #3 compared to #4).
If you able to edit the svg in editor, you can overlap like this. The darker green is the intersection between two paths.
As a quick fix, you can make the ends overlap with stroke-linecap="square"
But ideally, you need to create a single path instead of two separate paths.
<svg height="300" width="300" shapeRendering="crispEdges">
<path
d="M150 10 a120 120 0 0 1 103.9230 60"
fill="none"
stroke="green"
stroke-width="20"
stroke-linecap="square"
/>
<path
d="M253.9230 70 a120 120 0 0 1 0 120"
fill="none"
stroke="green"
stroke-width="20"
stroke-linecap="square"
/>
</svg>
I have a header with Logo, on left side, page title - in the middle, and user menu, on the right. Currently I'm displaying a SVG next to each page title. For example, on page /organizations I display this:
After that I've added a SVG that shows when I hover on the element (it's the same SVG, but filled)
How could I make transition between these two smooth? I'm using Tailwind for styling and tried adding transition-all to almost every class but that sadly didn't work.
This is the code responsible for switching between the SVGs:
const [hover, setHover] = React.useState(false);
const handleMouseOver = () => {
setHover(true);
};
const handleMouseLeave = () => {
setHover(false);
};
return (
...
<div className="w-1/2 flex justify-center">
<Link
to={getModuleInfo(pathname, t, organization).url}
className="max-w-fit flex items-center gap-2"
prefetch="intent"
>
<div
className="flex items-center gap-2"
onMouseOver={handleMouseOver}
onMouseLeave={handleMouseLeave}
>
<>
{hover
? getModuleInfo(pathname, t, organization).logoHover
: getModuleInfo(pathname, t, organization).logo}
</>
<h5 className="organizations text-md md:text-2xl font-sans font-normal text-center text-colublue-500">
{getModuleInfo(pathname, t, organization).title}
</h5>
</div>
</Link>
</div>
...
)
UPD: to make things more clear, these would be 2 SVG examples that I would like to transition between:
And this are the <svg> for them:
// Unfilled SVG
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2V7C10 7.55228 9.55228 8 9 8H4.5" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
// Filled SVG
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843ZM16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" fill="#052141"/>
</svg>
With plain CSS and SVG, you can do this with opacity and transition.
.filled {
opacity: 0;
transition: opacity 0.3s;
}
svg:hover .filled {
opacity: 1;
}
<svg width="96" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2V7C10 7.55228 9.55228 8 9 8H4.5" stroke="#052141" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path class="filled" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843ZM16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" fill="#052141"/>
</svg>
You could also use css variables to transition between the design states.
Similar to #ksav's this approach will also need to combine both svgs.
This way we can render the icon with more design variations.
let icon = document.querySelector('.iconTrans');
function toggleState() {
icon.classList.toggle('active')
}
svg {
border: 1px solid #ccc;
overflow: visible;
width: 10em;
}
svg path {
transition: 1s;
}
.iconTrans {
--strokeColor: #052141;
--strokeWidth: 2px;
--opacity1: 1;
--opacity2: 0;
--fillColor: #052141;
}
.active {
--strokeColor: #052141;
--strokeWidth: 0px;
--opacity1: 0;
--opacity2: 1;
--fillColor: #ccc;
}
<p><button id="btnToggle" onclick="toggleState()">Toggle state</button></p>
<svg class="iconTrans" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="paper" d="M8.41421 2.58579C8.78929 2.21071 9.29799 2 9.82843 2H18C18.5304 2 19.0391 2.21071 19.4142 2.58579C19.7893 2.96086 20 3.46957 20 4V20C20 20.5304 19.7893 21.0391 19.4142 21.4142C19.0391 21.7893 18.5304 22 18 22H6C5.46957 22 4.96086 21.7893 4.58579 21.4142C4.21071 21.0391 4 20.5304 4 20V7.82843C4 7.29799 4.21071 6.78929 4.58579 6.41421L8.41421 2.58579Z
M10 2V7C10 7.55228 9.55228 8 9 8H4.5" style="stroke:var(--strokeColor); stroke-width:var(--strokeWidth); opacity:var(--opacity1)" stroke-linecap="round" stroke-linejoin="round" />
<path class="paperCheck" d="M9.82843 1C9.03278 1 8.26972 1.31607 7.70711 1.87868L3.87868 5.70711C3.31607 6.26972 3 7.03278 3 7.82843V20C3 20.7957 3.31607 21.5587 3.87868 22.1213C4.44129 22.6839 5.20435 23 6 23H18C18.7956 23 19.5587 22.6839 20.1213 22.1213C20.6839 21.5587 21 20.7957 21 20V4C21 3.20435 20.6839 2.44129 20.1213 1.87868C19.5587 1.31607 18.7956 1 18 1H9.82843Z
M16.7071 9.29289C17.0976 9.68342 17.0976 10.3166 16.7071 10.7071L11.3738 16.0404C10.9832 16.431 10.3501 16.431 9.95956 16.0404L7.29289 13.3738C6.90237 12.9832 6.90237 12.3501 7.29289 11.9596C7.68342 11.569 8.31658 11.569 8.70711 11.9596L10.6667 13.9191L15.2929 9.29289C15.6834 8.90237 16.3166 8.90237 16.7071 9.29289Z" style="fill:var(--fillColor); opacity:var(--opacity2); " />
</svg>
I cannot get the console log after clicking on this element.However changing div to button will fetch result.
Here is my code snippet.
<div class="navbar">
<div x-on:click="console.log('clicked')" class="navitem msn">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"`enter code here`
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<div class="navtitle">Title1</div>
</div>
</div>
You have a couple of errors:
No x-data directive. You need at least an empty x-data on any Alpine.js component.
There's a random "enter code here" string in the SVG code.
You have a missing </div> element.
The corrected example:
<div x-data="" class="navbar">
<div x-on:click="console.log('clicked')" class="navitem msn">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<div class="navtitle">Title1</div>
</div>
</div>
</div>
I'm trying to create a popout menu for an array of values that are echoed from the database. On the click of the svg, the popout menu that corresponds with the svg in the echo, needs to be shown. Except so far, it only works for the first one that is echoed. How to I fix it so that it show the popout that corresponds with the correct svg. Here's what I've currently got :
PHP/HTML :
echo('
<svg class="option-3" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 10.5C9.82843 10.5 10.5 9.82843 10.5 9C10.5 8.17157 9.82843 7.5 9 7.5C8.17157 7.5 7.5 8.17157 7.5 9C7.5 9.82843 8.17157 10.5 9 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 10.5C15.8284 10.5 16.5 9.82843 16.5 9C16.5 8.17157 15.8284 7.5 15 7.5C14.1716 7.5 13.5 8.17157 13.5 9C13.5 9.82843 14.1716 10.5 15 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<div class="menu-option-popout"></div>
');
JS :
document.querySelector(".option-3").addEventListener("click", function(){
document.querySelector(".menu-option-popout").style.display = "block";
});
If each popout <div> appears immediately after its corresponding <svg> tag (as in your example), you can take advantage of the .nextElementSibling property to get the <div> that follows the <svg> that was clicked.
At the end of your HTML:
<script>
// Add an event listener to each .option-3 element:
document.querySelectorAll('.option-3').forEach(item => {
item.addEventListener('click', event => {
let popout = event.target.nextElementSibling; // This element's next element (a .menu-option-popout)
popout.style.display = 'block'; // Show the popout
})
})
</script>
First of all PHP is executed first, so you will not be able to call php from a JS action unless using AJAX features. But it is not your use case here.
That said, we can continue with :
echo('
<svg class="option-3" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 10.5C9.82843 10.5 10.5 9.82843 10.5 9C10.5 8.17157 9.82843 7.5 9 7.5C8.17157 7.5 7.5 8.17157 7.5 9C7.5 9.82843 8.17157 10.5 9 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 10.5C15.8284 10.5 16.5 9.82843 16.5 9C16.5 8.17157 15.8284 7.5 15 7.5C14.1716 7.5 13.5 8.17157 13.5 9C13.5 9.82843 14.1716 10.5 15 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<div class="menu-option-popout"></div>
');
should be written as this to improve the readability of your generated HTML document :
echo '<svg class="option-3" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 10.5C9.82843 10.5 10.5 9.82843 10.5 9C10.5 8.17157 9.82843 7.5 9 7.5C8.17157 7.5 7.5 8.17157 7.5 9C7.5 9.82843 8.17157 10.5 9 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 10.5C15.8284 10.5 16.5 9.82843 16.5 9C16.5 8.17157 15.8284 7.5 15 7.5C14.1716 7.5 13.5 8.17157 13.5 9C13.5 9.82843 14.1716 10.5 15 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<div class="menu-option-popout"></div>'.PHP_EOL;
And it is only HTML stored inside database, so there are many things to look at :
Any bad escaped string can put the mess inside your displayed datas
Any bad char's encoding can put the mess inside your displayed datas
Maybe just call the equiv .toogle() JQuery method of ECMAScript on that .option-3 class will work and display your item as you wish.
I have na SVG Map that contains cities and their districts. You can look one of them below. I want to add a pin icon on the center of district. You can see the text (district's name) in the middle of the district. I want to put over the text.
<g id="Hakkari" transform="translate(4607.000000, 1335.000000)" data-transform-left="-521.5" data-transform-top="-87">
<g id="Merkez" transform="translate(10.000000, 2.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="31 59 119 38 181 0 193 43 155 64 163 167 49 175 0 142"></polygon>
<g id="MER" transform="translate(85.000000, 98.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<text>
<tspan x="0" y="6">MER</tspan>
</text>
</g>
</g>
<g id="Yüksekova" transform="translate(165.000000, 0.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="38 44 122 0 163 7 185 27 185 107 118 133 79 177 38 176 25 190 7 168 0 66"></polygon>
<g id="YÜK" transform="translate(78.000000, 86.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<text>
<tspan x="0" y="6">YÜK</tspan>
</text>
</g>
</g>
<g id="Şemdinli" transform="translate(244.000000, 107.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="106 0 168 47 172 104 121 94 40 169 14 127 31 87 0 70 39 26"></polygon>
<g id="ŞEM" transform="translate(81.000000, 62.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<text>
<tspan x="0" y="6">ŞEM</tspan>
</text>
</g>
</g>
<g id="Çukurca" transform="translate(0.000000, 143.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="190 47 163 76 70 72 20 51 0 24 10 0 58 33 173 26"></polygon>
<g id="ÇUK" transform="translate(104.000000, 50.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<text>
<tspan x="0" y="6">ÇUK</tspan>
</text>
</g>
</g>
</g>
I'm using the Google's icon "location on" as as symbol. I hope this is what you need.
<svg viewBox="4600 1300 500 300">
<defs>
<symbol id="pin" viewBox='0 0 24 24'><title>location on</title>
<path d='M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z'></path>
<path d='M0 0h24v24h-24z' fill='none'></path>
</symbol>
</defs>
<g id="Hakkari" transform="translate(4607.000000, 1335.000000)" data-transform-left="-521.5" data-transform-top="-87">
<g id="Merkez" transform="translate(10.000000, 2.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="31 59 119 38 181 0 193 43 155 64 163 167 49 175 0 142"></polygon>
<g id="MER" transform="translate(85.000000, 98.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">MER</tspan>
</text>
</g>
</g>
<g id="Yüksekova" transform="translate(165.000000, 0.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="38 44 122 0 163 7 185 27 185 107 118 133 79 177 38 176 25 190 7 168 0 66"></polygon>
<g id="YÜK" transform="translate(78.000000, 86.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">YÜK</tspan>
</text>
</g>
</g>
<g id="Şemdinli" transform="translate(244.000000, 107.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="106 0 168 47 172 104 121 94 40 169 14 127 31 87 0 70 39 26"></polygon>
<g id="ŞEM" transform="translate(81.000000, 62.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">ŞEM</tspan>
</text>
</g>
</g>
<g id="Çukurca" transform="translate(0.000000, 143.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="190 47 163 76 70 72 20 51 0 24 10 0 58 33 173 26"></polygon>
<g id="ÇUK" transform="translate(104.000000, 50.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">ÇUK</tspan>
</text>
</g>
</g>
</g>
</svg>
UPDATE
In this case I'm using a png instead of an SVG path. The png is in this case square (120px/120px) with a transparent background.
<svg viewBox="4600 1300 500 300">
<symbol id="pin" viewBox='0 0 24 24'><title>location on</title>
<!--<path d='M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z'></path>
<path d='M0 0h24v24h-24z' fill='none'></path>-->
<image width="24" height="24" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/pin.png" />
</symbol>
<g id="Hakkari" transform="translate(4607.000000, 1335.000000)" data-transform-left="-521.5" data-transform-top="-87">
<g id="Merkez" transform="translate(10.000000, 2.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="31 59 119 38 181 0 193 43 155 64 163 167 49 175 0 142"></polygon>
<g id="MER" transform="translate(85.000000, 98.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">MER</tspan>
</text>
</g>
</g>
<g id="Yüksekova" transform="translate(165.000000, 0.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="38 44 122 0 163 7 185 27 185 107 118 133 79 177 38 176 25 190 7 168 0 66"></polygon>
<g id="YÜK" transform="translate(78.000000, 86.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">YÜK</tspan>
</text>
</g>
</g>
<g id="Şemdinli" transform="translate(244.000000, 107.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="106 0 168 47 172 104 121 94 40 169 14 127 31 87 0 70 39 26"></polygon>
<g id="ŞEM" transform="translate(81.000000, 62.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">ŞEM</tspan>
</text>
</g>
</g>
<g id="Çukurca" transform="translate(0.000000, 143.000000)">
<polygon id="Shape" stroke="#FFFFFF" fill="#9FB4B7" fill-rule="nonzero" points="190 47 163 76 70 72 20 51 0 24 10 0 58 33 173 26"></polygon>
<g id="ÇUK" transform="translate(104.000000, 50.000000)" font-size="6" font-family="Helvetica-Bold, Helvetica" fill="#000000" font-weight="bold">
<use xlink:href="#pin" x="-5" y="-24" width="24" height="24" />
<text>
<tspan x="0" y="6">ÇUK</tspan>
</text>
</g>
</g>
</g>
</svg>
My idea is same as "enxaneta" below:
// use <path> or <use> element as you like
var pinIconNode = document.createElement("path");
// supporse the <g> element id is the city you want
var city = document.getElementById("cityName");
city.prepend(pinIconNode);