Логотип Workflow

Article

Structuring Grouping Reusing

Structuring, Grouping & Reusing

The larger your SVG file becomes, the harder it is to navigate. If you are drawing a complex illustration or creating an icon system, just throwing <path> after <path> is a bad idea.

In this lesson, we will look at the DRY (Don't Repeat Yourself) principle in SVG: how to group elements, create templates and reuse them without duplicating code.


1. The <g> tag: Grouping

The <g> (group) tag is the equivalent of a <div> in HTML or a "Folder" in graphics editors. It does not render anything by itself, but it combines nested elements.

Why you need it:

  1. Code organization: Logical separation (e.g., <g id="head">, <g id="arm">).
  2. Mass transformation: You can move, rotate, or scale the entire group at once.
  3. Style inheritance: Attributes set for a group (e.g., fill or stroke) are applied to all nested elements (unless they have their own).
<svg width="200" height="200" viewBox="0 0 200 200">
  <!-- "Face" group: all elements inside will be red and shifted -->
  <g id="face" fill="crimson" transform="translate(50, 50)">
    <!-- Eyes (color is inherited from the group) -->
    <circle cx="20" cy="20" r="10" />
    <circle cx="80" cy="20" r="10" />
    <!-- Mouth (override the color to white) -->
    <rect x="20" y="60" width="60" height="10" fill="white" />
  </g>
</svg>

2. The <defs> tag: Resource warehouse

<defs> (definitions) is a special area for storing objects. Everything inside <defs> is not automatically displayed on the canvas. This is a "warehouse" of templates, gradients, filters, or shapes that we plan to use later.

This is the basis for optimization: you define a complex object once, and then just refer to it.

<svg width="0" height="0">
  <defs>
    <!-- This circle is not visible until we call it -->
    <circle id="my-template" cx="10" cy="10" r="10" fill="teal" />
  </defs>
</svg>

3. The <use> tag: Cloning

The <use> tag gets an object from <defs> (or any other place by id) and renders a copy of it in the right place.

Advantages:

  • Reduced file size (the shape code is not duplicated).
  • A single source of truth (if you change the shape in <defs>, all copies change).
<svg width="300" height="100" viewBox="0 0 300 100">
  <defs>
    <circle id="coin" r="20" fill="gold" stroke="orange" stroke-width="2" />
  </defs>

  <!-- Use the coin 3 times in different places -->
  <use href="#coin" x="50" y="50" />
  <use href="#coin" x="150" y="50" />
  <!-- You can add a transformation to a copy -->
  <use href="#coin" x="250" y="50" transform="scale(0.8)" />
</svg>

Note: In older code examples, you may see xlink:href. In modern SVG, it is enough to write just href.


4. The <symbol> tag: The gold standard for icons

<symbol> is an advanced version of a group, created specifically for reuse.

Main differences from <g> and <defs>:

  • Like <defs>, the content of <symbol> is not displayed by itself.
  • Killer feature: <symbol> has its own viewBox attribute.

This allows you to create SVG sprites (icon systems). No matter how the icon is drawn inside the symbol, you can insert it via <use> and give it any size (width and height), and it will fit perfectly thanks to its viewBox.

SVG sprite example

<svg style="display: none;">
  <!-- "Home" icon definition -->
  <symbol id="icon-home" viewBox="0 0 24 24">
    <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
  </symbol>

  <!-- "Settings" icon definition -->
  <symbol id="icon-settings" viewBox="0 0 24 24">
    <path d="M19.14 12.94c.04-.3.06-.61.06-.94... (long path) ..."/>
  </symbol>
</svg>

Usage on the page

<!-- Large home icon -->
<svg class="icon"><use href="#icon-home" width="50" height="50"/></svg>

<!-- Small settings icon -->
<svg class="icon"><use href="#icon-settings" width="20" height="20"/></svg>

5. Shadow DOM and styling problems

When you use <use>, the browser creates a Shadow DOM. This means that the copy of the element is isolated from the rest of the page.

Problem:

You cannot use CSS to access the internals of a clone.

For example, this CSS will not work to change the color of a path inside <use>:

/* Will not work */
use path {
  fill: blue;
}

Solution 1: Inheritance

Styles set on the <use> tag itself are inherited into the Shadow DOM.

For this to work, there should be no fill attribute inside the original symbol (or it should be currentColor).

Source:

<symbol id="star" viewBox="0 0 24 24">
  <!-- Remove fill="black", set fill="currentColor" or remove it altogether -->
  <path d="..." fill="currentColor" /> 
</symbol>

Usage:

<svg class="icon-red"><use href="#star" /></svg>
<svg class="icon-blue"><use href="#star" /></svg>

CSS:

.icon-red { color: red; } /* currentColor will take this value */
.icon-blue { fill: blue; } /* Or so */

Solution 2: CSS Variables

CSS variables (Custom Properties) penetrate the Shadow DOM boundary.

<symbol id="robot">
  <rect fill="var(--main-color, black)" />
</symbol>
svg { --main-color: purple; }

Summary

  • <g> - for grouping parts of a single drawing (move together, paint together).
  • <defs> - for storing gradients and masks.
  • <symbol> + <use> - the standard for icon systems. Allows you to control the viewBox of each icon separately.
  • Use currentColor in icon paths to easily recolor them via CSS when using <use>.

Quiz

Check what you learned

Please login to pass quizzes.