HTML Tutorial 0/139 lessons ~6 min read Lesson 48

    HTML SVG

    html svg svg is the production choice for icons, logos, and moderate data viz when access inline svg is vector

    Course progress0%
    Focus
    18 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Inline SVG is vector markup in the DOM — every <path> is a node with geometry, style, and event targets. Staff engineers prefer SVG for icons and data viz under ~500 interactive elements because it scales crisply at any DPR, participates in the accessibility tree (with correct roles), and compresses well in sprite systems like GitHub's Octicons and Google's Material Symbols pipeline.

    Business problem

    Business pressure: Design systems ship thousands of icons across Airbnb, Google, and Shopify surfaces. Raster sprites blur on retina; icon fonts fail WCAG and FOIT. Inline SVG in HTML — or external sprites with <use href="#id"> — is the enterprise default, but bloated path data from design exports can inflate HTML TTFB and parser cost.

    • Conversion: Broken or missing icons on checkout erode trust — SVG must degrade to text labels, not empty boxes.
    • Compliance: Decorative SVG needs aria-hidden="true"; informative icons need <title> or aria-label — lawsuit targets include missing form field icons.
    • SEO: SVG text nodes are indexable; logo SVGs with embedded company names beat canvas logos for brand queries.

    Why this feature exists

    Platform motivation: SVG predates HTML5 canvas as an W3C vector format. Browsers integrated it into HTML parsing so authors could embed scalable graphics without Flash. When Apple banned Flash on iOS, SVG + CSS animation replaced swf banners on major publishers.

    • History: SVG 1.1 (2003); HTML5 allows inline SVG without XML prolog — parser switches to foreign content namespace.
    • Alternative rejected: PNG @2x/@3x asset matrices explode CMS storage and CDN invalidation complexity.
    • Modern role: Icons, maps (Mapbox GL outputs canvas; static map pins often SVG), charts (D3), animated loaders — complements canvas for retained graphics.

    Browser internals

    Inside the engine: The HTML parser enters SVG "foreign content" adjustment when it sees <svg>. Elements become SVG DOM nodes (SVGPathElement, etc.) mixed in the HTML document. Style calculation applies SVG presentation attributes + CSS; layout uses SVG viewport and viewBox mapping — not always the CSS box model for inner coordinates.

    • Parser: Tag names and attributes are case-sensitive in foreign content; self-closing rules differ from HTML.
    • DOM: Each shape is a node — 500 paths = 500 layout/style objects; memory scales with complexity.
    • Script impact: getBBox() and getTotalLength() force geometry recalc — batch after DOM inserts.
    html
    <!-- Parser builds mixed tree -->
    <div class="card">
    <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2L2 7v10l10 5 10-5V7z"/></svg>
    <span>Shipped</span>
    </div>
    // DevTools: path is SVGPathElement, participates in hit-testing

    Rendering workflow

    Rendering path: SVG generates a render object subtree. Simple fills are rasterized at display resolution; complex filters (<feGaussianBlur>) trigger offscreen passes. CSS transforms on <svg> promote compositor layers — Airbnb map pin bounce animations use transform, not top/left, to avoid layout.

    • Critical path: Inline hero SVG in HTML adds to document weight — external sprite + <use> caches across pages.
    • Layout: Missing width/height or viewBox causes intrinsic size 300×150 default — classic CLS on icon-only buttons.
    • Paint: Long dashed strokes and filters are paint-heavy — simplify paths exported from Figma (SVGO in CI).

    Feature deep dive

    SVG production model: Retained-mode vector graphics in DOM. Use viewBox for responsive scaling, <symbol> + <use> for sprites, CSS currentColor for themeable icons — GitHub's pattern for light/dark mode without duplicate assets.

    • Shapes: <rect>, <circle>, <path d="..."> — paths are most compact for icons.
    • Accessibility: <title> first child for SR; decorative icons aria-hidden="true" focusable="false".
    • Animation: CSS @keyframes on transform or SMIL (deprecated — avoid for new work).
    html
    <svg class="icon" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
    <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-4H8l4-4 4 4h-3v4h-2z"/>
    </svg>
    <!-- Informative -->
    <svg role="img" aria-labelledby="status-title" viewBox="0 0 24 24" width="24" height="24">
    <title id="status-title">Order shipped</title>
    <circle cx="12" cy="12" r="10" fill="#22c55e"/>
    </svg>

    Accessibility analysis

    A11y architecture: SVG can expose name via <title>, aria-label, or aria-labelledby. Role img maps to graphic on accessibility tree. Interactive SVG buttons need role="button", tabindex, and keyboard handlers — Google Maps custom controls pattern.

    • Screen readers: IE legacy required focusable="false" on decorative SVG — still best practice for Firefox SVG focus quirks.
    • Keyboard: Clickable paths need visible focus — outline on <a> wrapper preferred over raw path click targets.
    • WCAG: 1.4.11 Non-text Contrast — icon strokes must meet 3:1 against adjacent colors, not just brand palette approval.

    SEO impact

    SEO architecture: Text inside <svg><text> is crawlable. Logo markup with company name aids brand SERP. Over-large inline SVG in <body> above fold increases HTML bytes — hurts TTFB and parser time; Google Search Console HTML size alerts are common on icon-heavy SPAs.

    • Crawl: Prefer external SVG for decorative complexity; keep critical textual content in HTML headings.
    • Rich results: Organization logo structured data should reference PNG/JPG URL — many validators reject inline SVG URLs.
    • Core Web Vitals: 200KB inline SVG sprite in HTML delays FCP — use cached external resource or HTTP/2 push sparingly.

    Security considerations

    Security boundary: SVG is XML — can embed <script>, onload, and foreignObject with HTML. User-uploaded SVG avatars are XSS vectors — Slack and GitHub sanitize with allowlists. Never serve raw user SVG with Content-Type: image/svg+xml inline in DOM without DOMPurify.

    • XSS: <svg><script>alert(1)</script> executes if injected via innerHTML — sanitize in CMS pipelines.
    • CSP: Restrict inline script; SVG use elements fetching external fragments need script-src and URL policy review.
    • Clickjacking: Full-screen transparent SVG hit regions over iframe embeds — audit z-index in ad slots.

    Performance impact

    Performance: SVG scales O(nodes) for DOM and style recalc. D3 charts with 5k circles lag INP — canvas or WebGL for that scale. SVGO in CI (Shopify theme pipeline) typically cuts path data 30–60%.

    • LCP: Large inline SVG logo competes with hero image bytes — use compact path or PNG WebP for LCP logo if >10KB.
    • INP: Hover handlers on hundreds of SVG map regions need event delegation on parent <g>, not per-path listeners.
    • CLS: Always set explicit width/height or aspect-ratio on <svg> container.

    Real production example

    GitHub Octicons pattern: Icons ship as optimized SVG strings in React components; currentColor inherits text color; decorative by default with opt-in aria-label prop. Sprite sheet alternative for static sites: one cached icons.svg + <svg><use href="/icons.svg#check"></use></svg>.

    • SVGO config: Remove metadata, merge paths, precision 2 — run on every design handoff PR.
    • Theme: CSS variables on stroke/fill — no duplicate dark mode files.
    • Testing: Visual regression per icon size 16/20/24px — subpixel blur catches missing pixel-alignment.
    html
    <!-- Airbnb-style map pin — semantic wrapper -->
    <button type="button" class="map-pin" aria-label="View listing, $120 per night">
    <svg viewBox="0 0 32 42" width="32" height="42" aria-hidden="true">
    <path fill="#ff385c" d="M16 0C7.2 0 0 7.2 0 16c0 11 16 26 16 26s16-15 16-26C32 7.2 24.8 0 16 0z"/>
    <circle cx="16" cy="16" r="6" fill="#fff"/>
    </svg>
    </button>

    Enterprise usage

    Enterprise: Design tokens packages export SVG React/Vue components; CMS blocks reference icon ID, not raw path. Regulated industries block user SVG upload entirely — PDF-to-SVG conversion disabled in banking portals.

    • Design system: Icon lint: max 1KB gzipped per glyph, mandatory viewBox, no embedded fonts.
    • CMS: Sanitize SVG with allowlist tags: svg, path, circle, rect, g, title — strip script and foreignObject.
    • CI gates: svgo + custom rule rejecting <script> in staged SVG assets.

    Common production failures

    What breaks in prod: SVG failures are usually export bloat, XSS in uploads, or a11y omissions — not invalid path syntax.

    • Incident: Marketing uploaded 800KB Illustrator SVG inline — mobile FCP +2.4s, rollback after RUM alert.
    • SEO regression: N/A for icons, but replaced <img alt="Company"> logo with untitled SVG — brand accessibility complaints.
    • Security: Profile photo SVG with embedded script — XSS in admin panel; fix: sanitize + CSP + serve raster fallback.

    Architecture review questions

    • Is each icon decorative (aria-hidden) or named (title/aria-label)?
    • Did SVGO run — any path over 1KB?
    • Are width/height or aspect-ratio set to prevent CLS?
    • Could user-supplied SVG reach the DOM unsanitized?
    • Does stroke/fill meet non-text contrast on all themes?
    • At what node count would you migrate this chart to canvas?

    Hands-on project

    Project: Build a design-system icon component: SVGO-optimized path, currentColor, decorative/informative modes, sprite fallback, axe verification.

    • Deliverable: 10 icons with consistent viewBox, React/HTML variants, dark mode via CSS only.
    • Verify: Total sprite <15KB; axe passes; no focus trap on decorative icons.
    • Stretch: Document XSS test cases for rejected SVG uploads.

    Interview questions

    SVG sprite vs inline SVG vs icon font — production trade-offs?(Advanced)

    Icon fonts: one request but FOIT, poor a11y, blurry subpixel. Inline: best styling, worst cache duplication. External sprite + use: best cache, HTTP/2 multiplex; watch CSP and cross-origin fragment IDs. GitHub inlines in components for tree-shaking.

    Follow-up: How does currentColor help theming?

    Why is user-uploaded SVG dangerous?(Advanced)

    SVG allows script, event handlers, and foreignObject HTML. A 'logo upload' can steal session cookies when rendered inline. Mitigate: server-side sanitize, rasterize, CSP, serve from separate origin.

    Follow-up: What tags would your allowlist include?

    SVG vs canvas for a live dashboard?(Advanced)

    Under ~500 interactive DOM nodes with a11y requirements — SVG/D3. Beyond that or needing pixel shaders — canvas/WebGL. Hybrid: SVG axes, canvas data layer (Observable plot pattern).

    Follow-up: How do you test screen reader experience for SVG charts?

    Try it yourself

    Edit the HTML, CSS, or JS panels — the preview updates as you type.

    Try it yourself

    Preview

    Summary

    SVG is the production choice for icons, logos, and moderate data viz when accessibility and CSS theming matter — with SVGO discipline, XSS-safe uploads, explicit dimensions for CLS, and a clear handoff threshold to canvas for high-node workloads.

    Ready to mark this lesson complete?Track your journey across the entire course.