Tips & Tricks (Updated: 6/2/2026)

SVG Manipulation with Claude Code: Practical Guide

Use Claude Code for SVG icons, viewBox, accessibility, currentColor theming, animation, and SVGO optimization with safe examples.

SVG Manipulation with Claude Code: Practical Guide

What to Decide Before Asking Claude Code

SVG is useful for icons, logos, diagrams, and small data visuals because it stays sharp at any size and can be styled from CSS. Claude Code can read the existing codebase, edit files, and run checks, so it is a good fit for turning raw SVG into maintainable UI components.

The risk is that a vague prompt such as “make an SVG icon” often misses the boring parts that matter in production: viewBox, accessible names, theme colors, reduced motion, and safe handling of untrusted SVG. Masa ran into this on a small ClaudeCodeLab UI experiment. The first icon looked fine, but it could not be reused across a text button, an icon-only button, and dark mode without manual edits.

This guide gives Claude Code a safer implementation pattern. We will cover inline SVG basics, viewBox, accessible icons, currentColor and CSS variables, simple animation, SVGO optimization, use cases, layout mistakes, and security pitfalls.

Official references worth keeping open are MDN <svg>, MDN viewBox, MDN ARIA img role, MDN aria-hidden, SVGO usage, and the Claude Code overview.

The Workflow

Treat SVG work as a UI workflow, not as a drawing task. The coordinate system, color strategy, accessibility behavior, optimization step, and final review all affect the quality of the result.

flowchart LR
  A["Define the purpose"] --> B["Lock the viewBox"]
  B --> C["Use currentColor"]
  C --> D["Choose aria-label or aria-hidden"]
  D --> E["Embed in HTML or React"]
  E --> F["Optimize with SVGO"]
  F --> G["Review layout and safety"]

A better Claude Code prompt is specific: “Create a 24px SVG icon component with viewBox="0 0 24 24", stroke="currentColor", decorative icons hidden with aria-hidden, meaningful standalone icons labeled with role="img" and title, and an SVGO config that preserves viewBox.”

Inline SVG and viewBox Basics

Inline SVG means the <svg> markup lives directly inside HTML or JSX instead of being loaded through an <img> tag. It is useful when the icon must inherit color, react to hover state, or animate lightly.

The viewBox is the internal coordinate system. MDN defines it as four numbers, min-x min-y width height, that describe the SVG viewport in user space. For beginners, it is easiest to think of it as a drawing grid. viewBox="0 0 24 24" means the icon is drawn on a 24 by 24 grid, even if it is displayed at 16px, 24px, or 48px.

<button class="icon-button" type="button" aria-label="Search">
  <svg
    class="icon"
    viewBox="0 0 24 24"
    width="24"
    height="24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    aria-hidden="true"
    focusable="false"
  >
    <circle cx="11" cy="11" r="7" />
    <path d="M20 20l-4.5-4.5" />
  </svg>
</button>

The button has the accessible name, so the icon is decorative. If the SVG were the only visible content and the button did not have aria-label, assistive technology users would not know what the control does.

Theme with currentColor and CSS Variables

Hard-coded SVG colors become maintenance debt. If paths contain fill="#111827" or stroke="#0ea5e9", Claude Code has to edit the SVG every time the theme changes. A better pattern is to let SVG inherit CSS color.

:root {
  --color-text: #172033;
  --color-muted: #667085;
  --color-accent: #0f766e;
  --color-danger: #b42318;
}

[data-theme="dark"] {
  --color-text: #eef2f7;
  --color-muted: #a9b4c3;
  --color-accent: #2dd4bf;
  --color-danger: #f97066;
}

.icon {
  color: var(--icon-color, var(--color-text));
  display: inline-block;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  flex: 0 0 auto;
}

.icon-button {
  color: var(--color-muted);
}

.icon-button:hover {
  color: var(--color-accent);
}

.icon-button[data-variant="danger"] {
  --icon-color: var(--color-danger);
}
<button class="icon-button" type="button" aria-label="Delete" data-variant="danger">
  <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
    <path d="M4 7h16" />
    <path d="M10 11v6" />
    <path d="M14 11v6" />
    <path d="M6 7l1 14h10l1-14" />
    <path d="M9 7V4h6v3" />
  </svg>
</button>

Ask Claude Code to search for fixed colors after the refactor. A useful review command is rg "fill=\"#|stroke=\"#" inside the component and asset folders.

A React Icon Component

Meaningful SVG needs an accessible name. Decorative SVG should be hidden from the accessibility tree. MDN recommends role="img" and a label for embedded SVG that represents an image, while aria-hidden="true" is appropriate for non-interactive decorative content.

import { useId } from "react";

type IconName = "search" | "check" | "close";

const paths: Record<IconName, string> = {
  search: "M10.5 18a7.5 7.5 0 1 1 5.3-12.8 7.5 7.5 0 0 1-5.3 12.8Zm5.3-2.2L21 21",
  check: "M5 12.5l4.5 4.5L19 7",
  close: "M6 6l12 12M18 6L6 18",
};

type SvgIconProps = {
  name: IconName;
  title?: string;
  decorative?: boolean;
  size?: number;
  className?: string;
};

export function SvgIcon({
  name,
  title,
  decorative = false,
  size = 24,
  className,
}: SvgIconProps) {
  const titleId = useId();
  const isMeaningful = !decorative && Boolean(title);

  return (
    <svg
      className={className}
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      role={isMeaningful ? "img" : undefined}
      aria-labelledby={isMeaningful ? titleId : undefined}
      aria-hidden={decorative ? true : undefined}
      focusable="false"
    >
      {isMeaningful ? <title id={titleId}>{title}</title> : null}
      <path d={paths[name]} />
    </svg>
  );
}
<button type="button">
  <SvgIcon name="check" decorative />
  Save
</button>

<SvgIcon name="search" title="Search" />

Do not put aria-hidden="true" on a focusable element. If an icon-only button needs a name, put aria-label on the button or provide visible text.

Simple Animation Without Layout Damage

SVG animation is best for small UI signals: loading, success, drawing attention to one chart value. Keep the element size stable and respect prefers-reduced-motion.

<svg class="spinner" viewBox="0 0 48 48" width="48" height="48" role="img" aria-label="Loading">
  <circle class="spinner-track" cx="24" cy="24" r="20" />
  <circle class="spinner-head" cx="24" cy="24" r="20" />
</svg>
.spinner {
  color: #0f766e;
  animation: spin 900ms linear infinite;
}

.spinner-track,
.spinner-head {
  fill: none;
  stroke-width: 4;
}

.spinner-track {
  stroke: #d0d5dd;
}

.spinner-head {
  stroke: currentColor;
  stroke-linecap: round;
  stroke-dasharray: 80 45;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation: none;
  }
}

For broader motion patterns, connect this with Claude Code CSS animation techniques. SVG should define shape. CSS should define state and motion.

Small Data SVG with Escaping

SVG can also render small charts. The important rule is to escape text before injecting labels into <text>.

type BarDatum = {
  label: string;
  value: number;
};

function escapeXml(value: string): string {
  return value.replace(/[<>&"']/g, (char) => {
    const entities: Record<string, string> = {
      "<": "&lt;",
      ">": "&gt;",
      "&": "&amp;",
      '"': "&quot;",
      "'": "&apos;",
    };
    return entities[char];
  });
}

export function createMiniBarChart(data: BarDatum[]): string {
  const width = 420;
  const height = 180;
  const padding = 32;
  const gap = 12;
  const maxValue = Math.max(...data.map((item) => item.value), 1);
  const barWidth = (width - padding * 2 - gap * (data.length - 1)) / data.length;

  const bars = data
    .map((item, index) => {
      const barHeight = (item.value / maxValue) * 100;
      const x = padding + index * (barWidth + gap);
      const y = height - padding - barHeight;

      return `
        <rect x="${x}" y="${y}" width="${barWidth}" height="${barHeight}" rx="6" fill="currentColor" />
        <text x="${x + barWidth / 2}" y="${height - 10}" text-anchor="middle" font-size="12">
          ${escapeXml(item.label)}
        </text>`;
    })
    .join("");

  return `<svg viewBox="0 0 ${width} ${height}" role="img" aria-label="Monthly inquiries" xmlns="http://www.w3.org/2000/svg">
    <g color="#0f766e">${bars}</g>
  </svg>`;
}

Use this for a tiny dashboard, an article illustration, or a landing-page proof point. Use a real chart library when you need axes, legends, tooltips, zooming, or a large data set.

Optimize with SVGO

Designer exports often include editor metadata and unnecessary precision. SVGO removes that noise. Start with a conservative config and inspect the diff.

// svgo.config.mjs
export default {
  multipass: true,
  plugins: [
    {
      name: "preset-default",
      params: {
        overrides: {
          cleanupIds: false
        }
      }
    },
    "removeDimensions",
    {
      name: "removeAttrs",
      params: {
        attrs: ["data-name"]
      }
    }
  ]
};
{
  "scripts": {
    "svg:optimize": "svgo --config svgo.config.mjs --folder src/assets/icons"
  },
  "devDependencies": {
    "svgo": "^4.0.0"
  }
}

SVGO documents preset-default, removeDimensions, and other plugins. Be careful with removeViewBox: the SVGO docs warn that it can prevent SVGs from scaling and may cause clipping. For responsive icons, preserving viewBox is usually the right default.

Use Cases and Pitfalls

Common use cases:

  • Product UI icons for search, close, save, warning, and external links.
  • Article diagrams that explain a workflow without requiring a screenshot.
  • Landing-page visuals near pricing, checklists, and purchase CTAs.
  • Small dashboard charts for article completion, CTA clicks, or inquiry volume.
MistakeResultFix
Removing viewBoxIcons clip or stop scalingPreserve it in SVGO and review diffs
Fixed fill colorsDark mode and hover states failUse currentColor
Hiding meaningful SVGScreen readers miss the actionLabel the button or SVG
Reading decorative SVGRepeated names become noisyUse aria-hidden="true"
Inlining uploaded SVGScript or event-handler riskInline only trusted SVG
Ignoring reduced motionMotion may burden usersUse prefers-reduced-motion

MDN documents SVG <script>, so do not treat uploaded SVG text as harmless markup. Claude Code can help review diffs, but you should still restrict the target folder and inspect file changes. The Claude Code security page is also relevant when a tool is allowed to edit many files or run optimization commands.

Prompt to Reuse

Create an SVG icon system for this repository.
Requirements:
- Keep viewBox="0 0 24 24"
- Use currentColor for fill or stroke
- Hide decorative icons with aria-hidden=true
- Use role=img and title for meaningful standalone icons
- Add a reduced-motion friendly loading SVG
- Add an SVGO config that does not remove viewBox
- Report risks, changed files, and verification commands

Then run the usual checks. For this topic, Claude Code performance optimization is the natural next article because every icon, diagram, and animation eventually affects page weight and rendering.

CTA and Tested Result

If you want a reusable setup instead of one-off prompts, start with the ClaudeCodeLab products and templates or bring a real repository to Claude Code training and consultation. SVG work is a good first target because the changes are small but touch accessibility, design tokens, performance, and review discipline.

In Masa’s test UI, moving fixed SVG colors to currentColor made the same icons work across light mode, dark mode, and destructive buttons. The one real bug was accessibility: an icon-only search button lost its name when aria-hidden was applied mechanically. The fix was to label the button and reserve aria-hidden for decorative icons only.

#Claude Code #SVG #icons #animation #optimization
Free

Free PDF: Claude Code Cheatsheet

Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.

We handle your data with care and never send spam.

Level up your Claude Code workflow

Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.

Masa

About the Author

Masa

Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.