Home > Software design >  How to apply custom CSS style on SVG <use> element
How to apply custom CSS style on SVG <use> element

Time:03-11

I am working with an svg element

var defsElement = document.querySelector('defs');
var defsElementX = defsElement.getBBox().x;
var defsElementY = defsElement.getBBox().y;

var colX = [];


for (var i = 0; i < 3; i  ) {
    (i == 0) ? colX.push(25): colX.push(colX[i - 1]   60)
};
//console.log(colX);

const y = 145;

const svg = document.querySelector("svg");

const svgns = "http://www.w3.org/2000/svg"

colX.forEach(
    (a, i) => {
        let useEl = document.createElementNS(svgns, 'use');
        useEl.setAttributeNS('http://www.w3.org/1999/xlink', "xlink:href", "#stick man");
        useEl.setAttribute("class", "use"   [i]);
        useEl.setAttribute("id", "id"   [i]);
        useEl.setAttribute("x", `${a}`);
        useEl.setAttribute("y", `${y}`);
        svg.appendChild(useEl);
    }
)
.stickman {
    stroke: red;
    fill: none;
}

.stickman>.head {
    fill: black;
    stroke: blue;
}

.head {
    fill: brown;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <link rel="stylesheet" href="style.css"></link>
    <svg id="layer" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
        <defs>

            <g id="stick man" style="fill: none; stroke: black;">
            <circle  cx="10" cy="10" r="10"/>
            <line  x1="10" y1="20" x2="10" y2="44"/>
            <polyline  points="1 58, 10 44, 19 58"/>
            <polyline  points="1 24, 10 30, 19 24"/>
            </g>
            </defs>

            <g  id="stickman" transform = "translate (85,50)">
                <circle  cx="10" cy="10" r="10"/>
                <line  x1="10" y1="20" x2="10" y2="44"/>
                <polyline  points="1 58, 10 44, 19 58"/>
                <polyline  points="1 24, 10 30, 19 24"/>
    
    <script href="index.js"></script>

    
    </svg>
</body>

</html>

I want to learn how to apply CSS styles to different <use></use> element. For example, how can I apply 3 different colors for fill for each of the head. What CSS selector should I use?

I tried like

.use0>.head {
    fill: brown;
}

It did not do anything.

The javascript is generating this

S1

CodePudding user response:

In your example there's no use0 class so obviously is not changing anything and your rule:

.head {
    fill: brown;
}

is just overwritten by:

.stickman>.head {
    fill: black;
}

Be sure you have a priority css rule to overwritte another rule... there's many ways for it avoiding, if possible, the !Important like, for example:

body .stickman .head  {
    fill: brown;
}

a bit more info about css priorities here

CodePudding user response:

You can use CSS variables for this:

const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg";

for (let i = 0; i < 3;   i) {
  let useEl = document.createElementNS(svgns, 'use');
  useEl.setAttributeNS('http://www.w3.org/1999/xlink', "xlink:href", "#stickRef");
  useEl.setAttribute("id", `id${i}`);
  useEl.setAttribute("x", (i * 60)   25);
  useEl.setAttribute("y", 25);
  svg.appendChild(useEl);
}
#id0 { --head-colour: #F00; --line-colour: #900; }
#id1 { --head-colour: #0F0; --line-colour: #090; }
#id2 { --head-colour: #00F; --line-colour: #009; }
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
  <defs>
    <symbol id="stickRef" style="fill: none; stroke: var(--line-colour);">
      <circle  cx="10" cy="10" r="10" style="fill: var(--head-colour)" />
      <line  x1="10" y1="20" x2="10" y2="44"/>
      <polyline  points="1 58, 10 44, 19 58"/>
      <polyline  points="1 24, 10 30, 19 24"/>
    </symbol>
  </defs>
</svg>

CodePudding user response:

You can wrap in a group <g> with style="fill: none;" only the line and polylines of the stick man, leaving the circle with an unspecified fill.

Now you can set a fill attribute or give a style to the <use> element. The fill will be applied only to the circle.

use{fill:red}
use:nth-of-type(2){fill:gold}
use:nth-of-type(3){fill:blue}
<svg id="layer" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 100 500 500">
  <defs>
    <g id="stickman" style="stroke: black;">
      <circle  cx="10" cy="10" r="10"></circle>
      <g style="fill: none;">
      <line  x1="10" y1="20" x2="10" y2="44"></line>
      <polyline  points="1 58, 10 44, 19 58"></polyline>
      <polyline  points="1 24, 10 30, 19 24"></polyline>
      </g>
    </g>
  </defs>


  <use xlink:href="#stickman" x="25" y="145"></use>
  <use xlink:href="#stickman" x="85" y="145"></use>
  <use xlink:href="#stickman" x="145" y="145"></use>
</svg>

  • Related