How to style SVG <g> element?

123,581

Solution 1

You actually cannot draw Container Elements

But you can use a "foreignObject" with a "SVG" inside it to simulate what you need.

http://jsfiddle.net/VBmbP/4/

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
      <foreignObject id="G" width="300" height="200">
        <svg>
          <rect fill="blue" stroke-width="2" height="112" width="84" y="55" x="55" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke="#000000"/>
          <ellipse fill="#FF0000" stroke="#000000" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" cx="155" cy="65" id="svg_7" rx="64" ry="56"/>     
        </svg>
          <style>
              #G {
                background: #cff; border: 1px dashed black;
              }
              #G:hover {
                background: #acc; border: 1px solid black;
              }
          </style>
      </foreignObject>
    </svg>

Solution 2

You cannot add style to an SVG <g> element. Its only purpose is to group children. That means, too, that style attributes you give to it are given down to its children, so a fill="green" on the <g> means an automatic fill="green" on its child <rect> (as long as it has no own fill specification).

Your only option is to add a new <rect> to the SVG and place it accordingly to match the <g> children's dimensions.

Solution 3

I know its long after this question was asked and answered - and I am sure that the accepted solution is right, but the purist in me would rather not add an extra element to the SVG when I can achieve the same or similar with straight CSS.

Whilst it is true that you cannot style the g container element in most ways - you can definitely add an outline to it and style that - even changing it on hover of the g - as shown in the snippet.

It not as good in one regard as the other way - you can put the outline box around the grouped elements - but not a background behind it. Sot its not perfect and won't solve the issue for everyone - but I would rather have the outline done with css than have to add extra elements to the code just to provide styling hooks.

And this method definitely allows you to show grouping of related objects in your SVG's.

Just a thought.

g {
    outline: solid 3px blue;
    outline-offset: 5px;
  }

g:hover {
 outline-color: red
}
<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
  <g>
    <rect fill="blue" stroke-width="2" height="112" width="84" y="55" x="55" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke="#000000"/>
    <ellipse fill="#FF0000" stroke="#000000" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" cx="155" cy="65" id="svg_7" rx="64" ry="56"/>     
  </g>
</svg>

Solution 4

The style that you give the "g" element will apply the child elements, not the "g" element itself.

Add a rectangle element and position around the group you wish to style.

See: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g

EDIT: updated wording and added fiddle in comments.

Share:
123,581
Sudarshan
Author by

Sudarshan

I started programming in last year of my graduation(2011). Well, so far there is not really more to say but that i simply began to love writing code. It simply makes me happy =) In general, writing abstract or complex code snippets is what satisfies me the most. The more of a brain ache, the better If you didn't see me around on SO today... I am on a secret mission! ☻

Updated on July 08, 2022

Comments

  • Sudarshan
    Sudarshan almost 2 years

    I have some SVG elements grouped together in a <g> element. I just want to style that <g> element to show grouping of elements. Like I want to give some background-color and a border to it. How it would be achieved?

    I tried fill and stroke attribute to <g> element, but it doesn't work. How it would be possible? Thanks in advance!

    Sample Here

    <svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
        <g fill="blue" stroke="2">
                <rect id="svg_6" height="112" width="84" y="105" x="136" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="5" stroke="#000000" fill="#00ff00"/>
            <ellipse fill="#FF0000" stroke="#000000" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" cx="271" cy="156" id="svg_7" rx="64" ry="56"/>
        </g>
    </svg>
    
  • Boldewyn
    Boldewyn almost 11 years
    The <rect> is not allowed to have shapes or <g> as chidlren (not even in SVG2). It will therefore not simply span to meet its children's dimensions.
  • Andrew Grothe
    Andrew Grothe almost 11 years
    @Boldewyn I meant graphically, not literally, but I will rephrase to make that clear. As seen here: jsfiddle.net/VBmbP/2
  • Erik Dahlström
    Erik Dahlström almost 11 years
    That's mostly true, but there are some properties such as e.g opacity that apply to the <g> element itself.
  • e18r
    e18r about 8 years
    Yes, you can, but a foreignObject is not intended for this: developer.mozilla.org/en/docs/Web/SVG/Element/foreignObject In that sense it is no more appropriate than a rect object.
  • rafaelcastrocouto
    rafaelcastrocouto about 8 years
    But you can't nest elements inside a rect, can you?
  • Thomas Kimber
    Thomas Kimber about 5 years
    Will children of a <g> element inherit its class attributes? (tests suggest they do, meaning you can apply a css-sensitive class to a <g> element and have all the children inherit that class' styling attributes)
  • Luchux
    Luchux about 5 years
    And foreignObject browser support is supper limited yet at this date.
  • rafaelcastrocouto
    rafaelcastrocouto over 4 years
    Support has increased a lot after all this time caniuse.com/#feat=mdn-api_svgforeignobjectelement
  • Lucas Janon
    Lucas Janon over 3 years
    Worked perfectly for my use-case (just needed a visual clue of what was the content of a group)
  • gavgrif
    gavgrif over 3 years
    Thanks - glad I could help. Happy coding 😄