skip to Main Content

I have and SVg and adding tag inside svg and using nested css delcration syntax and wehn using & it gives error of some XMl error ;

first see this html example

<style type="text/css">
  :root {
    --color-red: #FF5733;
  }

  div {
    background-color: yellow;
    .card {
    border: 2px solid grey;
      height:2rem;
      width:2rem;
      margin: 1rem;
        background-color: var(--color-red);
        &:nth-child(odd) {
          background-color: blue;
        }
      }
  }

  </style>

  <div>

    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>

  </div>
<section>
<p>Working SVG but not applying pseudo-class</p>
<svg width="600" height="90" viewBox="0 0 600 90" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect class="card" x="42" y="50" width="16" height="16" />
  <rect class="card" x="120" y="20" width="16" height="16" />
  <style type="text/css">
:root {
--color-red: #FF5733;
}
rect {
.card {
fill: var(--color-red);
:nth-child(odd) {
fill: blue;
}
  }

  }   
</style>
</svg>
</section>
<section>
<p> works when nested under svg `&` does not works </p>
<svg width="600" height="90" viewBox="0 0 600 90" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect class="card" x="42" y="50" width="16" height="16" />
  <rect class="card" x="120" y="20" width="16" height="16" />
<style type="text/css">
:root {
--color-red: #FF5733;
}
svg {
.card {
fill: var(--color-red);
}
:nth-child(odd) {
fill: blue;
}
}
</style>
</svg>
</section>

which works and if we remove & ahead to :nth-child then does not work as expected;

now same thing trying in svg ( and my requirement is every odd rectacle will be blue and otherwise red ( note: background-color replace by fill )

<svg width="600" height="90" viewBox="0 0 600 90" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect class="card" x="42" y="50" width="16" height="16" />
  <rect class="card" x="120" y="20" width="16" height="16" />
  <style type="text/css">
    :root {
    --color-red: #FF5733;
    }
    svg {
    .card {
    fill: var(--color-red);
    :nth-child(odd) {
    fill: blue;
    }
    }

    }
  </style>
</svg>

in above :nth-child does not work nor &:nth-child

although changing the navigation, then it works

<svg width="600" height="90" viewBox="0 0 600 90" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect class="card" x="42" y="50" width="16" height="16" />
  <rect class="card" x="120" y="20" width="16" height="16" />
<style type="text/css">
    :root {
    --color-red: #FF5733;
    }
    svg {
    .card {
    fill: var(--color-red);
    }
    :nth-child(odd) {
    fill: blue;
    }
    }
</style>
</svg>

but then adding & ahead to nth-child, it does not work and show nothing in browser

so my question is

  • does css nesting does not work proper in svg style tag
  • why does adding nth-child selector on parent svg works but not on .card

2

Answers


  1. <style> inside a SVG is not scoped.

    Cleaning up your long code.

    The second style styles the whole page:

    <svg viewBox="0 0 100 10">
      <rect x="0"  width="10" height="10" />
      <rect x="10" width="10" height="10" />
      <rect x="20" width="10" height="10" />
      <style type="text/css">
        svg {
          rect {
            fill: red;
            &:nth-child(odd) {
              fill: green;
            }
          }
        }   
      </style>
    </svg>
    <svg viewBox="0 0 100 10">
      <rect x="0"  width="10" height="10" />
      <rect x="10" width="10" height="10" />
      <rect x="20" width="10" height="10" />
      <style type="text/css">
        svg {
          rect {
            fill: rebeccapurple;
            &:nth-child(odd) {
              fill: hotpink;
            }
          }
        }   
      </style>
    </svg>
    Login or Signup to reply.
  2. The 🙴 Ampersand is Key

    The 🙴 is a placeholder for the nested selector’s parent selector. I’ve seen comments about how the 🙴 is optional for nested CSS, and while that’s true what’s not mentioned is the fact that when the CSS is parsed that 🙴 and a space is added to all nested selectors. So if you neglect to add a 🙴, a 🙴 and a space will be added. Review the code block below to see the difference this makes. Assume that there are 3 .child within .parent.

    Example 1

    /**
     *
     * The & is .child
     * The space after the & means that what next is a descendant
     *
     *   Flattened Selector
     *   .parent .child :nth-child
     *
     * This selector points to nothing .child doesn't have any
     * descendants.
     */
    .parent {
      .child {
        background: gold;
        & :nth-child(odd) {
          background: cyan;
        }
      }
    }
    

    In the following Demos are the HTML is identical:

    Example 2

      <svg id="A to D">
        <polygon class="shape">
        <circle class="shape">
        <rect class="shape">
      </svg>
    
    • Demo 1

      • 2 levels of nested selectors
        • .shape in <svg>, :nth-child(odd) in .shape
    • Demo 2

      • 1 level of nested selectors
        • .shape and :nth-child(odd) are direct descendants of <svg>

    Demo 1

    :root {
      font: 10px/1 "Palatino Linotype"
    }
    
    #area1 {
      background: linear-gradient(to right, black 0%, black 50%, navy 50%);
    }
    
    .id {
      fill: #fff;
      font-size: 3.6rem;
    }
    
    /**
     * Flattened Selector
     * #A .shape:nth-child(odd) ⭐
     * CORRECT
     * Prefixing &:nth-child is .shape:nth-child
     */
    #A {
      .shape {
        fill: gold;
    
        &:nth-child(odd) {
          fill: cyan;
        }
      }
    }
    
    /**
     * Flattened Selector
     * #B .shape :nth-child 💩
     * INCORRECT
     * Missing & defaults to & + space
     */
    #B {
      .shape {
        fill: gold;
    
        :nth-child(odd) {
          fill: cyan;
        }
      }
    }
    <svg id="area1" width="420" height="150" xmlns="http://www.w3.org/2000/svg">
    
      <text class="id" width="30" width="30" x="150" y="40">#A</text>
        
      <svg id="A" width="210" height="150" xmlns="http://www.w3.org/2000/svg">
         
        <polygon class="shape" points="100,10 40,198 190,78 10,78 160,198" transform="scale(0.3)"/>
      
        <circle class="shape" r="25" cx="100" cy="70"/> 
      
        <rect class="shape" width="50" height="50" x="150" y="90"/>
    
      </svg>
    
      <text class="id" width="30" width="30" x="360" y="40">#B</text>
    
      <svg id="B" width="210" height="150" x="210" y="0" xmlns="http://www.w3.org/2000/svg">
    
        <polygon class="shape" points="100,10 40,198 190,78 10,78 160,198" transform="scale(0.3)"/>
      
        <circle class="shape" r="25" cx="100" cy="70"/> 
      
        <rect class="shape" width="50" height="50" x="150" y="90"/>
    
      </svg>
    
    </svg>

    Demo 2

    :root {
      font: 10px/1 "Palatino Linotype"
    }
    
    #area2 {
      background: linear-gradient(to right, black 0%, black 50%, navy 50%);
    }
    
    .id {
      fill: #fff;
      font-size: 3.6rem;
    }
    
    /**
     * Flattened Selector
     * #C:nth-child(odd) 💩
     * INCORRECT
     * #C is parent to both .shape and :nth-child
     */
    #C {
      .shape {
        fill: gold;
      }
    
      &:nth-child(odd) {
        fill: cyan;
      }
    }
    
    /**
     * Flattened Selector
     * #D .shape:nth-child(odd) ⭐
     * CORRECT
     * Both .shape and :nth-child are children of #D
     */
    #D {
      .shape {
        fill: gold;
      }
      
      :nth-child(odd) {
        fill: cyan;
      }
    }
    <svg id="area2" width="420" height="150" xmlns="http://www.w3.org/2000/svg">
    
      <text class="id" width="30" width="30" x="150" y="40">#C</text>
        
      <svg id="C" width="210" height="150" xmlns="http://www.w3.org/2000/svg">
         
        <polygon class="shape" points="100,10 40,198 190,78 10,78 160,198" transform="scale(0.3)"/>
      
        <circle class="shape" r="25" cx="100" cy="70"/> 
      
        <rect class="shape" width="50" height="50" x="150" y="90"/>
    
      </svg>
    
    <text class="id" width="30" width="30" x="360" y="40">#D</text>
    
    <svg id="D" width="210" height="150" x="210" y="0" xmlns="http://www.w3.org/2000/svg">
    
        <polygon class="shape" points="100,10 40,198 190,78 10,78 160,198" transform="scale(0.3)"/>
      
        <circle class="shape" r="25" cx="100" cy="70"/> 
      
        <rect class="shape" width="50" height="50" x="150" y="90"/>
    
      </svg>
    
    </svg>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search