0

I want to use SVG image and color it using scss variables like $blue.

If I paste SVG code in the HTML it works fine. But I am going to use more than one SVG file like this and I don't want my HTML file to look complex.

So I tried to use other ways like pasting SVG url directly and defining the color variables in SVG file .

https://codepen.io/cankilic-gh/pen/xxxKOGZ

HTML

<!-- EXAMPLE 1 -->
<svg id="triangle" width="448" height="414" viewBox="0 0 448 414" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path
        d="M137.784 50.1096C176.303 -16.54 272.529 -16.4973 310.989 50.1865L434.102 263.644C472.563 330.328 424.413 413.64 347.433 413.606L101.017 413.496C24.0365 413.462 -24.039 330.107 14.4807 263.458L137.784 50.1096Z"
        fill="url(#triangle-grad)" />
  <defs>
    <linearGradient id="triangle-grad" x1="0.911862" y1="206.877" x2="447.627" y2="206.877"
                    gradientUnits="userSpaceOnUse">
      <stop class="stop1" offset="0%" />
      <stop class="stop2" offset="100%" />
    </linearGradient>
  </defs>
</svg>

<!-- EXAMPLE 2 -->

<div id="svg"></div>

<!-- EXAMPLE 3 -->

<img src="assets/images/triangle-md-a.svg" alt="">

SCSS

$purple:hsl(297, 28%, 38%);
$green:hsl(176, 59%, 48%);

svg path {
fill: url(#triangle-grad);
}

#triangle-grad .stop1 {
  stop-color: $purple;
}

#triangle-grad .stop2 {
  stop-color: $green;
}

/* Example 2 & 3 Paste this same classes in to SVG files <defs>*/

#svg {
  background-image: url(/assets/images/triangle-md-a.svg);
}

$purple or $green is not working when I try one like SVG import.

If I paste SVG in the HTML and move these styles into my scss file, it works.

I tried css variables too but it needs SVG code in the HTML too.

What is the best way using single line SVG in HTML and using SCSS variables to change its gradient stop colors?

Thanks

Newsha Nik
  • 806
  • 2
  • 12
  • 29
Can KILIC
  • 1
  • 2
  • *What is the best way using single line SVG in HTML and using SCSS variables to change its gradient stop colors?* --> the example 1 – Temani Afif Jan 31 '21 at 07:54
  • If you have more than one svg, is example 1 still the best way? – Can KILIC Jan 31 '21 at 09:12
  • if I had to choose I would use another expample where I will rely on mask to make the gradient outside the SVG. Related: https://stackoverflow.com/a/52812880/8620333 (check the last snippet) – Temani Afif Jan 31 '21 at 09:14

1 Answers1

0

.. going to use more than one SVG, and I dont want my HTML file look complex.

<defs> IDs must be unique in the document, so you can't just whack in multiple SVGs

One modern way around it is to generate the SVGs client side with a Custom Element,
supported in all modern browsers.
Without attaching shadowDOM, all your CSS is applied to the created SVGs

Declare the Custom Element <svg-icon> once, then all HTML required is:

<svg-icon id="ONE" shape="triangle"></svg-icon>
<svg-icon id="TWO" shape="rect"></svg-icon>
<svg-icon shape="triangle"></svg-icon>

unfinished, but working, SVGElement code that will get you started:

<style>
  svg {
    width: 150px;
    background: grey;
    vertical-align: top;
  }
  [shape] .stop1 { stop-color: yellow }
  #ONE .stop2 { stop-color: darkgreen }
  #TWO .stop2 { stop-color: blue  }
  svg-icon:not([id]) .stop2 { stop-color: red }
</style>

<svg-icon id="ONE" shape="triangle"></svg-icon>
<svg-icon id="TWO" shape="rect"></svg-icon>
<svg-icon shape="triangle"></svg-icon>

<script>
  customElements.define("svg-icon", class extends HTMLElement {
    connectedCallback() {
      let shape = {
        "triangle": "M7.5 4.5c2-4 7-4 9 0l6 10c2 4-1 8-5 8l-12 0c-4 0-6-4-4-8l6-10z",
        "rect": "M4 4h16v16h-16z"
      }[this.getAttribute("shape")];
      this.innerHTML = `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="${shape}" fill="url(#Gradient${this.id})"/>
<defs>
<linearGradient id="Gradient${this.id}">
<stop class="stop1" offset="0%"/><stop class="stop2" offset="100%"/>
</linearGradient>
</defs>
</svg>`}})
</script>
Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49