Chapter 28: SVG Scripting
SVG Scripting, one of the most powerful (and sometimes intimidating) ways to make SVG graphics truly interactive and dynamic.
Imagine I’m your patient web-development teacher sitting right next to you with the code editor open. We’ll go slowly, step by step, with clear explanations and many small, copy-paste examples you can try immediately.
What does “SVG Scripting” actually mean?
SVG Scripting = using JavaScript (or sometimes other scripting languages in very old contexts) to:
- read / change SVG elements after the page has loaded
- react to user events (click, hover, drag, scroll, keyboard…)
- animate things in ways that are hard or impossible with pure CSS/SMIL
- generate or modify SVG content dynamically
- connect SVG to data (charts, maps, dashboards)
- create games, interactive illustrations, data visualisations, custom controls…
In short: SVG + JavaScript = living, breathing, interactive vector graphics.
Two main ways people do scripting with SVG in 2025–2026
| Approach | When people use it | Pros | Cons |
|---|---|---|---|
| Inline <script> inside <svg> | Small demos, self-contained SVGs, quick prototypes | Very simple, no external files needed | Not recommended for production (security, caching, reusability issues) |
| External JavaScript file | Almost every real website / application | Clean code, better organisation, caching, security policies | Slightly more setup |
Most common & recommended way in 2026: Write normal JavaScript in a <script> tag outside the SVG (or in a separate .js file) and select SVG elements with document.querySelector(), getElementById(), etc.
Important facts before examples (2026 reality)
- Modern browsers fully support manipulating every SVG element and attribute via the DOM
- SVG elements live in the SVG namespace — but in practice you almost never need to worry about namespaces when using createElementNS or setAttributeNS (most methods work transparently)
- You can mix SVG + HTML freely (inline SVG, <object>, <img src=”file.svg”> with limitations)
- Security: inline scripts inside SVG files loaded via <img> are blocked in modern browsers (CORS + Content Security Policy reasons)
Example 1 – Very first script: Change fill color on click
|
0 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 26 27 28 29 30 31 32 33 34 35 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>SVG Scripting – Hello</title> </head> <body> <svg width="220" height="220"> <circle id="myCircle" cx="110" cy="110" r="90" fill="orange" stroke="darkorange" stroke-width="6"/> <text x="110" y="120" font-size="28" text-anchor="middle" fill="white">Click me!</text> </svg> <script> const circle = document.getElementById('myCircle'); circle.addEventListener('click', () => { // Toggle between two colors if (circle.getAttribute('fill') === 'orange') { circle.setAttribute('fill', '#2196F3'); circle.setAttribute('stroke', '#0D47A1'); } else { circle.setAttribute('fill', 'orange'); circle.setAttribute('stroke', 'darkorange'); } }); </script> </body> </html> |
→ Click the circle → it changes color back and forth. Very simple, but already real interactivity!
Example 2 – Hover effect with scale + shadow (CSS + JS hybrid)
|
0 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 26 27 28 29 30 31 |
<style> .grow { transition: transform 0.4s ease, filter 0.4s ease; transform-origin: center; } .grow:hover { transform: scale(1.15); filter: drop-shadow(0 10px 20px rgba(0,0,0,0.4)); } </style> <svg width="180" height="180"> <g class="grow" id="heartGroup"> <path id="heart" d="M90,30 C120,0 160,30 160,70 C160,110 120,150 90,170 C60,150 20,110 20,70 C20,30 60,0 90,30 Z" fill="#E91E63" stroke="#C2185B" stroke-width="5"/> </g> </svg> <script> const heart = document.getElementById('heart'); heart.addEventListener('click', () => { heart.setAttribute('fill', '#' + Math.floor(Math.random()*16777215).toString(16)); }); </script> |
→ Hover → grows + shadow (pure CSS) → Click → random color (JavaScript)
Example 3 – Animate drawing a path on click (classic reveal)
|
0 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 26 27 |
<svg width="400" height="200" viewBox="0 0 400 200"> <path id="myPath" d="M 50 100 Q 200 20, 350 100 T 350 100" fill="none" stroke="#4CAF50" stroke-width="10" stroke-linecap="round" stroke-dasharray="1000" stroke-dashoffset="1000"/> </svg> <button onclick="drawPath()">Draw the Curve!</button> <script> function drawPath() { const path = document.getElementById('myPath'); const length = path.getTotalLength(); // Reset path.style.strokeDashoffset = length; // Animate path.style.transition = 'stroke-dashoffset 3s ease-in-out'; path.style.strokeDashoffset = '0'; } </script> |
Click the button → path draws itself smoothly.
Example 4 – Generate SVG dynamically (create circles from data)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<svg id="chart" width="600" height="300"></svg> <script> const data = [30, 80, 45, 120, 90, 60]; const svg = document.getElementById('chart'); data.forEach((value, index) => { const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); circle.setAttribute("cx", 60 + index * 90); circle.setAttribute("cy", 250 - value); circle.setAttribute("r", value / 3); circle.setAttribute("fill", `hsl(${index * 60}, 80%, 60%)`); svg.appendChild(circle); }); </script> |
→ Creates a simple bar-like chart made of circles — dynamically from an array.
Quick 2026 Cheat Sheet – SVG Scripting Starting Points
| Goal | Best starting approach | Key methods / properties |
|---|---|---|
| Change color / stroke on click/hover | element.setAttribute(‘fill’, ‘…’) | addEventListener, getAttribute, setAttribute |
| Animate stroke drawing | stroke-dasharray + stroke-dashoffset | getTotalLength() |
| Move / scale / rotate element | CSS transform + transition / keyframes | classList.add(), style.transform |
| Create elements dynamically | document.createElementNS(svgNS, ‘circle’) | appendChild, setAttributeNS (rarely needed) |
| Read mouse position inside SVG | addEventListener(‘mousemove’, e => …) | e.offsetX, e.offsetY, getBoundingClientRect() |
| Drag an SVG shape | pointerdown → pointermove → pointerup | track e.clientX/Y differences |
Common beginner mistakes (2026 edition)
- Using element.style.fill = ‘red’ → doesn’t work on SVG presentation attributes (use setAttribute)
- Inline <script> inside standalone .svg file loaded via <img> → blocked by security policies
- Forgetting namespace when creating elements → createElement(‘circle’) fails silently
- Animating r / width / height directly in CSS → many SVG attributes are not animatable via CSS (use SMIL or JS)
- Not handling high-DPI / zoom → use viewBox properly
Mini practice challenges
- Make five colored circles — clicking any one changes all circles to random colors
- Create a path that redraws itself every 4 seconds automatically
- Make an SVG star that rotates slowly forever (CSS) and changes color on click (JS)
Paste your code here if you want feedback — I’ll review it like we’re pair-programming together 😄
SVG scripting is where your static drawings become real applications — interactive maps, live charts, games, custom UI controls, data visualisations…
Next we can go deeper into:
- Dragging shapes
- Mouse-follow effects
- Real-time data binding
- Using libraries (GSAP, D3.js, Three.js + SVG)
Which direction sounds most interesting to you? Or is any example still fuzzy? Just tell me — we’ll keep building until it feels natural and exciting! 🚀
