SVG in HTML
SVG (Scalable Vector Graphics) is XML markup for shapes, icons, and illustrations that stay sharp at any size. How to put SVG on a web page – inline in the HTML, referenced from an <img>, or bundled as icons – and how to keep it accessible.
Three common ways to use SVG
- Inline SVG – paste the
<svg>...</svg>markup directly into your HTML. - External file via
<img>– treat it like any other image withsrc="icon.svg". - CSS background or sprite – reference the file from a stylesheet or an SVG sprite sheet.
Each approach has trade-offs. Inline SVG is the most flexible for styling and scripting. An external file is simpler to cache and reuse. Pick based on how you need to control the graphic.
Inline SVG
When the SVG lives in your HTML, you can style it with CSS and reach inside it with JavaScript. Colours often respond to currentColor, which inherits the element’s text colour – handy for icons that should match link or button styling.
<a href="/courses/" class="nav-link">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path fill="currentColor" d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"/>
</svg>
Courses
</a>
Key attributes on the root <svg> element:
viewBox– defines the coordinate system (think of it as the SVG’s internal canvas).widthandheight– displayed size (can also be set in CSS).xmlns– required when inline in HTML5.
SVG as an image
For logos, diagrams, or icons you do not need to style from CSS, an external file keeps the HTML tidy:
<img src="logo.svg" alt="Codeskill logo" width="180" height="40">
The browser treats this like a raster image for accessibility purposes – you get one alt string and that is it. You cannot change individual paths with CSS from the parent page (there are security reasons for that). If you need hover colours or animations on parts of the graphic, inline SVG or a CSS mask is usually the better fit.
Icons: decorative vs meaningful
Icons beside visible text labels are often decorative – the text already conveys the meaning. Hide the icon from assistive tech so it is not read twice:
<button type="button">
<svg aria-hidden="true" focusable="false" ...></svg>
Save draft
</button>
focusable="false" stops Internet Explorer from letting users tab into the SVG. Still worth including for older markup patterns.
When an icon is the only content – a close button with an X, a social link with just a logo – it needs an accessible name. Options:
<!-- Option 1: visible text, visually hidden if needed -->
<button type="button">
<span class="visually-hidden">Close dialog</span>
<svg aria-hidden="true" ...></svg>
</button>
<!-- Option 2: aria-label on the button -->
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" ...></svg>
</button>
<!-- Option 3: title inside the SVG (less common for UI icons) -->
<svg role="img" aria-labelledby="close-title">
<title id="close-title">Close dialog</title>
...
</svg>
Prefer naming the interactive element (<button> or <a>) rather than the SVG alone. Users activate the button, not the path data.
Informative inline SVG
Charts, maps, and diagrams may need more than a one-line alt. Inline SVG can include <title> and <desc> elements for a short name and a longer description:
<figure>
<svg role="img" aria-labelledby="chart-title chart-desc" viewBox="0 0 400 200">
<title id="chart-title">Monthly sign-ups</title>
<desc id="chart-desc">Bar chart showing sign-ups rising from 12 in January to 48 in June.</desc>
<!-- bars and axes -->
</svg>
<figcaption>Sign-ups increased after the spring campaign.</figcaption>
</figure>
Wrap complex graphics in <figure> when a visible caption helps everyone, not just screen reader users.
SVG sprite sheets
Sites with dozens of icons sometimes store them in one SVG file and reference each icon with <svg><use href="icons.svg#icon-name"></use></svg>. That cuts HTTP requests and keeps icons consistent. The accessibility rules are the same – name the control, hide decorative duplicates.
<svg aria-hidden="true" focusable="false" width="20" height="20">
<use href="/assets/icons.svg#search"></use>
</svg>
Optimising SVG files
SVG exported from design tools often carries cruft – editor metadata, empty groups, overly precise decimals. Run files through an optimiser (SVGO is the usual choice) before production. Smaller files load faster, and leaner markup is easier to read when you need to edit something by hand.
Quick decision guide
- UI icon next to text – inline or sprite,
aria-hidden="true", name the button or link. - Logo in the header –
<img src="logo.svg" alt="Site name">is often enough. - Icon-only control –
aria-labelor visually hidden text on the control. - Complex diagram – inline SVG with
<title>,<desc>, and possibly a figcaption. - Need CSS colour on hover – inline SVG with
currentColoror direct path fills.
SVG is just markup. Treat it with the same care as the rest of your HTML – semantic wrapper, correct labelling, and no redundant noise for assistive tech.

