13.4 Scripting SVG

13.4.4 Changing Attributes of Multiple Objects

Claude Opus 4.5 about scripting inside or outside svg
When to put script inside vs outside SVG
Scenario Script Location Reason
SVG inline in HTML Outside SVG Cleaner, better IDE support, standard HTML practice
Standalone .svg file Inside SVG The .svg file needs to be self-contained
SVG loaded via <object> or <iframe> Inside SVG Script must be in the SVG file itself
Benefits of script outside SVG
  • No IDE syntax errors — JavaScript is recognized properly
  • No CDATA needed — simpler code
  • Easier debugging — browser dev tools work better
  • Can use modern JS features — modules, const/let, etc.
  • Separation of concerns — markup and logic are separate

Since the SVG is inline in HTML, the external script can access all SVG elements via document.getElementById() just like any other DOM element. There's no difference in functionality.

S M L
<svg id="shirtSvg" width="300" height="250" viewBox="0 0 300 250"
             xmlns="http://www.w3.org/2000/svg"
             xmlns:xlink="http://www.w3.org/1999/xlink">
                <defs>
                    <style type="text/css">
                      svg { /* default values */
                        stroke: black;
                        fill: white;
                      }
                      g.selected rect {
                        fill: #ffc; /* light yellow */
                      }
                      text {
                        stroke: none;
                        fill:black;
                        text-anchor: middle;
                      }
                    </style>
    
                    <path id="shirt-outline"
                        d="M -6 -30 -32 -19 -25.5 -13 -22 -14 -22 30 23 30
                          23 -14 26.5 -13 33 -19 7 -30
                          A 6.5 6 0 0 1 -6 -30"/>
                  </defs>
                  <g id="shirt" >
                     <use xlink:href="#shirt-outline" x="0" y="0"/>
                  </g>
                  <g id="scale0" >
                      <rect x="100" y="10" width="30" height="30" />
                      <text x="115" y="30">S</text>
                  </g>
                  <g id="scale1" class="selected">
                      <rect x="140" y="10" width="30" height="30" />
                      <text x="155" y="30">M</text>
                  </g>
                  <g id="scale2" >
                      <rect x="180" y="10" width="30" height="30" />
                      <text x="195" y="30">L</text>
                  </g>
                </svg>

<script>
  var scaleChoice = 1;
  var scaleFactor = [2, 2.5, 3];
  function init() {
    var obj;
    for (var i = 0; i < 3; i++) {
      obj = document.getElementById("scale" + i);
      obj.addEventListener("click", clickButton, false);
    }
    transformShirt();
  }
  function clickButton(evt) {
    var choice = evt.target.parentNode;
    var name = choice.getAttribute("id");
    var old = document.getElementById("scale" + scaleChoice);
    old.removeAttribute("class");
    choice.setAttribute("class", "selected");
    scaleChoice = parseInt(name[name.length - 1]);
    transformShirt();
  }
  function transformShirt() {
    var factor = scaleFactor[scaleChoice];
    var obj = document.getElementById("shirt");
    obj.setAttribute("transform",
      "translate(150, 150) " +
      "scale(" + factor + ")");
    obj.setAttribute("stroke-width",
      1 / factor);
  }
  // Initialize when DOM is ready
  document.addEventListener("DOMContentLoaded", init);
</script>