How To Structure Your SVG Code — The <g>, <title> And <desc> Elements

What’s the best way to organize your SVG code? If all you want to draw is a line or simple shape there’s not much to organize, but what about SVGs with multiple shapes and lines that combine to form a more complex whole?

Earlier in the year when I talked about SVG, I walked you through creating shapes, lines, polylines, polygons, and paths. In the examples for those posts, the graphics I created with these elements were all very simple. A circle here and a rectangle there, a line here and a curve there.

Let’s change that. Today I want to talk about how you can organize and structure your SVG code when working with more complex graphics and over the next few weeks I’ll share how you can group your code and even better, how you can reuse parts or the whole of any graphic elements you create.

A More Complex Example

Like I said the examples to this point have generally featured rectangles and circles. There’s not much to organize and structure when we have a single shape inside an <svg> element.

Since I’m not someone who gets mistaken for a graphics wizard, I took an easier path and used one of the standard shapes in iDraw and exported it as an .svg file.

Here’s the code after I removed the xmlns information and some automatic grouping iDraw added.

1
2
3
4
5
6
7
8
<svg x="0" y="0" width="300" height="300" viewBox="0, 0, 300, 300">
  <path d="M26.851,222.754 L0,222.754 L0,271.758 C0,286.751 14.555,299 32.443,299 L267.52,299 C285.408,299 300,286.751 300,271.758 L300,222.754 L273.112,222.754 L273.112,266.534 C273.112,272.067 267.816,276.484 261.27,276.484 L38.693,276.484 C32.147,276.484 26.851,272.058 26.851,266.534 L26.851,222.754 z" fill="#000000"/>
  <path d="M240.344,255.473 L240.344,216.874 L59.378,160.915 L59.378,199.513 z" fill="#000000"/>
  <path d="M101.138,160.949 C94.916,154.464 53.538,110.17 95.277,71.802 C130.054,39.868 135.137,13.003 123.434,-0 C123.434,-0 211.959,33.692 159.877,111.877 C150.998,125.163 128.702,140.843 140.369,173.129 L101.138,160.949 z" fill="#000000"/>
  <path d="M155.503,171.572 C153.624,165.019 145.142,150.746 171.021,122.303 C184.873,107.172 190.104,84.742 191.308,76.301 C191.308,76.301 237.167,100.662 191.576,160.215 L155.503,171.572 z" fill="#000000"/>
  <path d="M165.259,180.707 L240.321,157.488 L240.321,196.087 L227.627,199.99 z" fill="#000000"/>
  <path d="M134.519,235.715 L59.419,258.9 L59.419,220.301 L72.151,216.433 z" fill="#000000"/>
</svg>

The SVG is made up of six different paths inside an <svg> element. All the paths are filled with black (#000000). Both viewport and viewBox are aligned at their origins and each is 300px wide and 300px high.

Here’s the graphic produced by the code.

While you probably can’t look at the code and instantly determine which path is creating which shape in the campfire, it’s easy enough to see there are six distinct shapes in the campfire graphic and six different paths in the code. Logic would suggest each shape is created by one of the paths.

  • A single path creates the fire pit at the bottom
  • Three paths create the two logs in the campfire
  • Two paths create the flames of the fire

Wouldn’t it be nice to organize these three parts of the graphic and group the paths that created each in some way?

Document Structure — Grouping

You wouldn’t create an entire web page and place all your code inside a single <div> with no other structure. We build pages with divs inside divs. We use sections and headers and other block level elements to organize our code.

Like the content you place in different HTML elements, grouped SVG elements can be styled similarly and differently from the elements in other groups. Grouped elements can be animated independently for more realism and you can attach mouse events to groups for more interactivity.

Like HTML, SVG provides a number of elements such as such as <g>, <desc>, <defs>, <symbol>, and <use> to structure and organize your graphics. I’ll get to the first two in this post and the latter three in next week’s post.

The <g> Element

The <g> element is a generic container for grouping related graphic elements. You might think of it like a generic <div> or maybe similar to layers in a graphic editor.

In our campfire SVG you can probably guess how many groups we’ll create and what will be inside each. You’ll likely assign a class and possibly an id to any group you create to provide a hook to the group.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<svg width="300" height="300" viewBox="0 0 300 300">
 <g class="fire-pit">
   <path d="M26.851,222.754 L0,222.754 L0,271.758 C0,286.751 14.555,299 32.443,299 L267.52,299 C285.408,299 300,286.751 300,271.758 L300,222.754 L273.112,222.754 L273.112,266.534 C273.112,272.067 267.816,276.484 261.27,276.484 L38.693,276.484 C32.147,276.484 26.851,272.058 26.851,266.534 L26.851,222.754 z" fill="#000000"/>
 </g>

 <g class="flames">
   <path d="M101.138,160.949 C94.916,154.464 53.538,110.17 95.277,71.802 C130.054,39.868 135.137,13.003 123.434,-0 C123.434,-0 211.959,33.692 159.877,111.877 C150.998,125.163 128.702,140.843 140.369,173.129 L101.138,160.949 z" fill="#000000"/>
   <path d="M155.503,171.572 C153.624,165.019 145.142,150.746 171.021,122.303 C184.873,107.172 190.104,84.742 191.308,76.301 C191.308,76.301 237.167,100.662 191.576,160.215 L155.503,171.572 z" fill="#000000"/>
 </g>

 <g class="logs">
   <path d="M240.344,255.473 L240.344,216.874 L59.378,160.915 L59.378,199.513 z" fill="#000000"/>
   <path d="M165.259,180.707 L240.321,157.488 L240.321,196.087 L227.627,199.99 z" fill="#000000"/>
   <path d="M134.519,235.715 L59.419,258.9 L59.419,220.301 L72.151,216.433 z" fill="#000000"/>
 </g>
</svg>

Here I organized the six paths into three groups (after figuring out which path created which shape), one for the fire pit, one for the logs, and one for the flames. I placed the paths for each inside different group and added classes to each.

When you apply CSS styles to the group class all the elements inside the group will inherit those styles, though each element can also override the style of the group by having styles added directly to it.

The <title> and <desc> Elements

The <title> and <desc> elements are probably what you’d expect them to be based on their names. Either can be accessed by assistive devices like screen readers. Browsers will likely grab what’s inside the title element and use it as a tooltip when mousing over the graphic.

Think of them the way you would think about the <title> and <longdesc> attributes you place on an image. You should use the attributes to describe the SVG for anyone who can’t see it. Your outermost <svg> element should always have at least a title.

Here’s the previous example again, this time with titles and descriptions added.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<svg width="300" height="300" viewBox="0 0 300 300">
 <title>Campfire</title>
 <desc>A campfire burning in a fire pit</desc>

 <g class="fire-pit">
   <title>Fire Pit</title>
   <desc>The fire pit in which the campfire is burning</desc>
   <path d="M26.851,222.754 L0,222.754 L0,271.758 C0,286.751 14.555,299 32.443,299 L267.52,299 C285.408,299 300,286.751 300,271.758 L300,222.754 L273.112,222.754 L273.112,266.534 C273.112,272.067 267.816,276.484 261.27,276.484 L38.693,276.484 C32.147,276.484 26.851,272.058 26.851,266.534 L26.851,222.754 z" fill="#000000"/>
 </g>

 <g class="flames">
   <title>Flames</title>
   <desc>The crackling flames of a campfire</desc>
   <path d="M101.138,160.949 C94.916,154.464 53.538,110.17 95.277,71.802 C130.054,39.868 135.137,13.003 123.434,-0 C123.434,-0 211.959,33.692 159.877,111.877 C150.998,125.163 128.702,140.843 140.369,173.129 L101.138,160.949 z" fill="#000000"/>
   <path d="M155.503,171.572 C153.624,165.019 145.142,150.746 171.021,122.303 C184.873,107.172 190.104,84.742 191.308,76.301 C191.308,76.301 237.167,100.662 191.576,160.215 L155.503,171.572 z" fill="#000000"/>
 </g>

 <g class="logs">
   <title>Logs</title>
   <desc>The logs burning in the campfire</desc>
   <path d="M240.344,255.473 L240.344,216.874 L59.378,160.915 L59.378,199.513 z" fill="#000000"/>
   <path d="M165.259,180.707 L240.321,157.488 L240.321,196.087 L227.627,199.99 z" fill="#000000"/>
   <path d="M134.519,235.715 L59.419,258.9 L59.419,220.301 L72.151,216.433 z" fill="#000000"/>
 </g>
</svg>

Notice that each group now has a title and brief description. I gave the outermost SVG element both a title and description as well.

If you mouse over any of the graphics you should see a tool tip with the title of the group. If you mouse over any empty areas in the viewport, the tool tip will show the title on the SVG element.

CampfireA campfire burning in a fire pitFire PitThe fire pit in which the campfire is burningFlamesThe crackling flames of a campfireLogsThe logs burning in the campfire

Adding CSS to SVG Groups

I added a class to each of the different groups in order to style what’s inside each group similarly. For example here’s a little CSS to give the flames a different fill color along with a stroke color and width.

1
2
3
4
5
.flames {
  stroke: green;
  stroke-width: 5px;
  fill: #f00;
}

You can override a style given to the group by applying it to the elements in the group directly. For example I don’t think green is the right color to outline the flames. Orange will work better.

1
2
3
.flames path {
  stroke: orange;
}

Note: While I’m showing CSS from an external file in this section, I’m adding the CSS inline to the graphics to make things a little easier to display here.

CampfireA campfire burning in a pitFire PitThe fire pit in which the campfire is burningFlamesThe crackling flames of a campfireLogsThe logs burning in the campfire

While I’m at it, I might as well add some color to the other groups.

1
2
3
4
5
6
7
.logs {
  fill: #530;
}

.fire-pit {
  fill: #777;
}

Since you can add styles as inline or external css, or attributes directly on the elements, you have to be aware of the CSS cascade and CSS specificity. A fill added as an attribute to any of the paths will override a fill set on the group. The attribute can be overridden with more specific external CSS or inline CSS on the same element as the attribute. Know your CSS specificity rules.

CampfireA campfire burning in a pitFire PitThe fire pit in which the campfire is burningFlamesThe crackling flames of a campfireLogsThe logs burning in the campfire

One drawback to groups is they don’t allow for x and y attributes to change the group’s position. You can, however, use transforms on groups. For example I think the logs sit a little too high above the fire pit so I’ll move them down just a bit.

1
2
3
<g class="logs" transform="translate(0,10)">
  <!-- paths, title, desc for logs here -->
</g>

That means the flames will also need to come down a little too.

1
2
3
<g class="flames" transform="translate(0,10)">
  <!-- paths, title, desc for flames here -->
</g>

Here’s the entire SVG one last time with the transformations included. The graphic will look the same, though if you compare it to the rest, you can see the logs and flames are now a little lower and closer to the fire pit.

CampfireA campfire burning in a pitFire PitThe fire pit in which the campfire is burningFlamesThe crackling flames of a campfireLogsThe logs burning in the campfire

Hopefully you can see how easy it is to work with the generic group created by the <g> element. I trust you won’t have any issues with <title> or <desc> either.

Closing Thoughts

Organization is important once you start building up SVGs from multiple shapes, lines, paths, polylines, and polygons. It’ll help you style, animate, or interact with the different parts of your SVG independently of each other.

The <g> element is the most generic container you can use to group and organize your SVG elements. Elements like <title> and <desc> will help you communicate additional information to assistive devices and any other user agent that cares to make use of them.

The <g> element isn’t the only way to group elements, though. It’s just the first we’ve encountered. Next week I’ll show two more elements to help organize your SVG, <defs> and <symbol>, and then I’ll show you how you can define a graphic in one place and reuse it in another.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

Your email address will not be published. Required fields are marked *