SVG 2 Support

SVG 2 and What Browsers Actually Support in 2026

SVG 1.1 (Second Edition, August 2011) is still the last finished Recommendation. SVG 2 reached Candidate Recommendation on 4 October 2018 and has not moved since, so browsers adopt it feature by feature. Ask "is this feature supported?", not "is SVG 2 supported?"

SVG 2 features and their browser support
Feature Status in September 2026
href without the xlink: prefix Baseline; 96.9% of browsers
paint-order (stroke under fill) Baseline since March 2024
non-scaling-stroke; geometry (r, cx) in CSS Baseline since July 2020
d as a CSS property Chromium 4,389 and Firefox 555 only
Mesh gradients, other vector-effect values Not implemented
SVG fonts (<font>, <glyph>) Removed from SVG 2; Safari 10 only
Four SVG 2 features that are safe to use today, each drawn liveHTMLLive
<!doctype html>
<style>
  body { margin: 0; font: 14px system-ui, sans-serif; background: #fafaf7; color: #222; }
  svg { width: 100%; max-width: 600px; display: block; }
  .tile { fill: #fff; stroke: #d8d4c8; }
  .label { font-size: 13px; font-weight: 600; }
  .note { font-size: 11px; fill: #6b665c; }
  /* SVG 2: geometry properties such as r can be set from CSS */
  .dot { r: 14px; fill: #e07a5f; transition: r 0.3s; }
  .dot:hover { r: 22px; }
</style>
<svg viewBox="0 0 600 400">
  <defs>
    <!-- a book spine reused below with plain href (no xlink: prefix) -->
    <g id="spine">
      <rect width="26" height="90" rx="3" fill="#3d5a80"/>
      <rect y="12" width="26" height="6" fill="#f2cc8f"/>
    </g>
  </defs>

  <!-- 1. href without xlink -->
  <rect class="tile" x="10" y="10" width="285" height="185" rx="10"/>
  <text class="label" x="25" y="35">href without xlink:</text>
  <use href="#spine" x="40" y="60"/>
  <use href="#spine" x="72" y="60"/>
  <use href="#spine" x="104" y="60"/>
  <text class="note" x="25" y="180">Baseline · &lt;use href="#spine"&gt;</text>

  <!-- 2. paint-order: stroke drawn under the fill -->
  <rect class="tile" x="305" y="10" width="285" height="185" rx="10"/>
  <text class="label" x="320" y="35">paint-order</text>
  <g font-size="30" font-weight="800" font-family="system-ui, sans-serif" stroke="#3d5a80" stroke-width="8" fill="#f2cc8f" stroke-linejoin="round">
    <text x="320" y="92">BookNest</text>
    <text x="320" y="150" paint-order="stroke">BookNest</text>
  </g>
  <text class="note" x="320" y="108">default: fill, then stroke on top</text>
  <text class="note" x="320" y="166">paint-order="stroke": stroke underneath</text>
  <text class="note" x="470" y="35">Baseline 2024</text>

  <!-- 3. non-scaling-stroke -->
  <rect class="tile" x="10" y="205" width="285" height="185" rx="10"/>
  <text class="label" x="25" y="230">vector-effect</text>
  <g id="scaled" transform="translate(30 250) scale(2.2 1)">
    <rect width="50" height="60" fill="none" stroke="#81b29a" stroke-width="3"/>
    <rect x="60" width="50" height="60" fill="none" stroke="#81b29a" stroke-width="3"
          vector-effect="non-scaling-stroke"/>
  </g>
  <text class="note" x="30" y="330">scaled ×2.2 horizontally: left stroke stretches,</text>
  <text class="note" x="30" y="345">right one stays 3px (non-scaling-stroke)</text>
  <text class="note" x="25" y="375">Baseline since July 2020</text>

  <!-- 4. geometry in CSS (hover the dots) and d as a CSS property -->
  <rect class="tile" x="305" y="205" width="285" height="185" rx="10"/>
  <text class="label" x="320" y="230">r and d in CSS</text>
  <circle class="dot" cx="345" cy="280"/>
  <circle class="dot" cx="400" cy="280"/>
  <circle class="dot" cx="455" cy="280"/>
  <path id="morph" d="M500 300 L540 250 L580 300 Z" fill="#3d5a80"/>
  <text class="note" x="320" y="340">hover the dots: r transitions in CSS</text>
  <text class="note" x="320" y="355" id="dNote"></text>
  <text class="note" x="320" y="375">r: Baseline · d: Chromium, Firefox</text>
</svg>
<script>
  // Feature-detect d as a CSS property before animating it.
  const morph = document.getElementById('morph');
  const supportsD = CSS.supports('d', 'path("M0 0 L1 1")');
  document.getElementById('dNote').textContent =
    supportsD ? 'd is a CSS property here: the triangle morphs' : 'd in CSS not supported here';
  if (supportsD) {
    morph.animate([
      { d: 'path("M500 300 L540 250 L580 300 Z")' },
      { d: 'path("M500 300 L500 250 L580 250 Z")' }
    ], { duration: 1500, iterations: Infinity, direction: 'alternate', easing: 'ease-in-out' });
  }
</script>