skip to Main Content

If I have several SVG elements in a HTML body, where each SVG references a CSS class name, and this class name is defined in one of the SVG elements like below, then all the SVG elements are affected by this style. I am trying to find out whether this is by design, and how to make sure that the CSS class name is local to the SVG that defines it.

<svg ...><path class="iconMain" d="..." /></svg>
<svg ...>
    <defs>
        <style>.iconMain {fill: #9cbacf;}</style>
    </defs>
    <path class="iconMain" d="..." />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <path class="iconMain" d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <defs>
        <style>
            .iconMain {
                fill: #9cbacf;
            }
        </style>
    </defs>
    <path class="iconMain"
        d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
</svg>

https://codepen.io/napsta32/pen/ExOPGae

3

Answers


  1. You are misunderstanding the usage of defs they are used to define graphical elements to be used later on with the tag use If you put something inside that is not a graphical element it will go straight into the document, a style or script for example. And even the defs are global, if you define one element inside an svg you can use it in another one.

    <svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
      <defs>
      <circle id="circle_defined_in_first_svg" cx="1" cy="2" r="6" />
     </defs>
      
        <path class="iconMain" d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
    </svg>
    
    <svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
        <defs>
            <style>
                .iconMain {
                    fill: #9cbacf;
                    background-color:pink;
                }
            </style>       
          <script>
            var variableInsideDef = 7987;
          </script>      
        </defs>
        <path class="iconMain"
            d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
      
      <use x="5" y="5" href="#circle_defined_in_first_svg"/>
      
    </svg>
    
    <p class="iconMain"> P ELEMENT IN ROOT AFFECTED BY THE STYLE INSIDE DEF</p>
    
    <script>
      alert("Variable declared inside def: " + variableInsideDef)
    </script>
    Login or Signup to reply.
  2. Inlined SVGs containing <style> elements will affect the global document styles just as any other appended stylesheet.

    As already pointed out by Paulo Fernando

    See this example also affecting HTML elements:

    <svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
        <path class="iconMain" d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
    </svg>
    <svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
        <defs>
            <style>
                .iconMain {
                    fill: #9cbacf;
                }
              p{
                color: red
              }
              body{
                background: #ccc
              }
              h1{
                color:green
              }
            </style>
        </defs>
        <path class="iconMain"
            d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
    </svg>
    
    <h1>New Heading</h1>
    <p>New paragraph</p>

    Use case 1: icons

    Common practice: keep your icon graphics as neutral as possible to facilitate styling like changing fill/stroke colors for each instance.

    You can take inspiration from popular icon libraries like fontAwesome, feather icons, Material Icons etc.

    The main concept: organize your icons as <symbol> elements and create instances via <use> elements.

    svg{
      width:1em;
      border:1px solid #ccc;
    }
    <svg viewBox="0 0 15 10">
      <use href="#angle-double-down" fill="red"/>
    </svg>
    
    <svg viewBox="0 0 15 10">
      <use href="#angle-double-down" fill="green"/>
    </svg>
    
    <svg viewBox="0 0 15 10">
      <use href="#angle-double-down" fill="purple"/>
    </svg>
    
    
    <!-- hidden svg icon asset -->
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 10" style="position:absolute; height:0; width:0;">
      <symbol id="angle-double-down">
        <path d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
      </symbol>
    </svg>

    To some extent you can also use external <use> references like

    <svg viewBox="0 0 15 10">
      <use href="icons.svg#angle-double-down" fill="green"/>
    </svg>
    

    However there are some limitations or issues concerning gradients, masks clip paths etc. (Related "SVG ignores Gradient styling").

    Use case 2: complex SVG graphics with predefined colors

    It is not always necessary to manipulate the SVG styles, for example, when you display a complex vector illustration.

    In this case – just use an <img> element referencing a SVG file.
    This file can also contain style rules but it won’t override any global HTML element styles.

    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' viewBox='0 0 15 10'%3E%3Cdefs%3E%3Cstyle%3E .iconMain %7B fill: %239cbacf; %7D body %7B background: red; %7D %3C/style%3E%3C/defs%3E%3Cpath class='iconMain' d='M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z' /%3E%3C/svg%3E" />

    Otherwise, using a native web component might be a good alternative as explained here: "How can I change the color of an ‘svg’ element?"

    Login or Signup to reply.
  3. No, CSS classes in SVG (Scalable Vector Graphics) are not global by default. SVG is an XML-based language used for describing two-dimensional vector graphics, and it provides its own way of applying styles through attributes and properties.

    In SVG, you can use the "class" attribute to assign a class name to an element, similar to HTML. However, unlike HTML, the class name in SVG is not automatically global across the entire document. The scope of a class in SVG is limited to the current document fragment or the current SVG file.

    If you want to apply styles to multiple SVG elements using a class, you need to define the class and its associated styles within the same SVG document or file. In other words, the styles defined for a class in one SVG file will not affect elements in another SVG file unless you explicitly reference that class within the second file.

    It’s important to note that SVG can be embedded within HTML documents, and in that case, the CSS classes in the HTML document would have a global scope, including any SVG elements within it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search