ScreenshotNeo

BlogHow-to

How to Embed SVG in HTML

Learn when to use inline SVG, img, object, iframe, embed, or CSS backgrounds—with accessible, secure, runnable HTML examples.

By the ScreenshotNeo team1 October 20269 min read

Use inline <svg> when your page needs CSS or JavaScript access to individual SVG elements. Use <img src="graphic.svg"> for a normal external graphic that should be cacheable and accessible. Use <object>, <iframe>, or <embed> when the SVG should load as a separate document. Use a CSS background-image for decorative artwork that does not need DOM interaction.

The right method depends on whether the SVG is content or decoration, whether you need to style or animate its internal paths, whether scripts must run, and how much isolation you need. This guide covers each option, accessibility, sizing, security, troubleshooting, performance, and a hosted capture alternative.

Choose an SVG embedding method

Method Minimal pattern Best for Main trade-offs
Inline SVG <svg>...</svg> Icons, diagrams, CSS states, animation, DOM scripting Adds markup to the HTML; the SVG is not cached as a standalone image resource
External image <img src="graphic.svg"> Logos, illustrations, content images Easy alt text and browser caching; JavaScript and SVG links are unavailable
Object <object data="graphic.svg"> A separate SVG document with optional fallback Separate document context; interaction and scripting follow browser security rules
Iframe <iframe src="graphic.svg"> Isolated embedded documents and sandboxing Cross-origin DOM access is restricted; frame sizing and semantics need care
Embed <embed src="graphic.svg"> Legacy or general external-content embedding Document-context behavior differs from <img>; provide an accessible label
CSS background background-image: url(...) Decorative backgrounds No normal alternative text; image-mode restrictions apply

1. Embed an SVG inline

Inline SVG becomes part of the HTML document. Its shapes, groups, IDs, and attributes are available to page CSS and JavaScript. This is the most flexible option for interactive icons, diagrams, charts, theming, and animation.

<svg
  viewBox="0 0 100 100"
  role="img"
  aria-labelledby="chart-title chart-desc"
  width="200"
  height="200"
>
  <title id="chart-title">Quarterly sales trend</title>
  <desc id="chart-desc">A line rises from Q1 through Q4.</desc>
  <path
    d="M10 80 L35 60 L60 65 L90 20"
    fill="none"
    stroke="currentColor"
    stroke-width="3"
  />
</svg>

Use a viewBox so the artwork scales independently of its rendered dimensions. CSS can control the size and color:

.trend {
  width: 12rem;
  color: #2563eb;
}

.trend path {
  transition: stroke-width 160ms ease;
}

.trend:hover path {
  stroke-width: 5;
}

JavaScript can address an element by ID or class:

<button type="button" id="highlight">Highlight trend</button>

<script>
  document.querySelector('#highlight').addEventListener('click', () => {
    document.querySelector('.trend path').classList.toggle('active');
  });
</script>

Inline SVG sizing and viewBox rules

  • Keep the viewBox coordinates aligned with the artwork’s coordinate system.
  • Set CSS width and height or HTML dimensions to prevent layout shifts.
  • Use preserveAspectRatio when you need to control cropping or letterboxing.
  • Use currentColor when the SVG should inherit text color from its parent.

2. Embed an SVG with <img>

Use an external image for a non-interactive graphic. The browser can cache the SVG as its own resource, and the image gets a normal alternative-text attribute.

<img
  src="/assets/logo.svg"
  alt="Acme home page"
  width="160"
  height="40"
>

Use meaningful alt text when the image communicates information. If it is purely decorative, use an empty value:

<img src="/assets/sparkle.svg" alt="" width="24" height="24">

In image mode, scripts inside the SVG do not run and links inside it are not activated. Page JavaScript also cannot select the SVG’s internal paths. Choose inline SVG if you need those capabilities.

3. Load an SVG as a separate document

<object> with fallback content

<object> loads the SVG in a separate document context and allows fallback markup if loading fails.

<object
  type="image/svg+xml"
  data="/assets/process.svg"
  width="500"
  height="300"
>
  <img src="/assets/process-fallback.png" alt="Process diagram">
</object>

Interaction and scripting follow document and security rules. Same-origin content may be accessible through the object’s document after it loads; cross-origin content is restricted.

<iframe> for isolation

Use an iframe when the SVG should behave as an isolated browsing context or when sandboxing is useful.

<iframe
  src="/assets/process.svg"
  width="500"
  height="300"
  title="Process diagram"
  sandbox
></iframe>

The title labels the embedded document for assistive technology. Cross-origin iframe content cannot be manipulated directly by page JavaScript. A sandbox changes what the embedded context may do, so add permissions only when the SVG genuinely requires them.

<embed> for external content

<embed
  src="/assets/process.svg"
  type="image/svg+xml"
  width="500"
  height="300"
  title="Process diagram"
>

This is a general and older external-content mechanism. Provide a label and verify behavior in the browsers you support before choosing it for new work.

4. Use an SVG as a CSS background

Background SVGs are appropriate for decoration that does not need an alternative text equivalent or interaction.

.hero {
  min-height: 20rem;
  background: #0f172a url('/assets/mesh.svg') center / cover no-repeat;
}

A CSS background does not expose normal image alt text. If the artwork communicates information, include an equivalent text description in the page content. Background SVGs use image-mode behavior: scripts do not run and links are not activated.

Accessibility checklist

  • Give informative <img> elements meaningful alt text.
  • Use alt="" for decorative images so assistive technology skips them.
  • For an informative inline SVG, put <title> immediately after the opening <svg>.
  • Add <desc> when a longer explanation is needed.
  • Connect the SVG’s accessible name with aria-labelledby.
  • Give an iframe or other embedded document a useful title.
  • Provide an equivalent text description when a CSS background carries meaning.
<svg
  viewBox="0 0 320 160"
  role="img"
  aria-labelledby="map-title map-description"
>
  <title id="map-title">Server locations</title>
  <desc id="map-description">
    A world map with locations in North America, Europe, and Asia.
  </desc>
  <!-- paths and markers -->
</svg>

Styling and animation

Inline SVG supports normal CSS selectors and animations. Prefer classes and CSS variables over editing long path attributes in JavaScript.

<svg class="status-icon" viewBox="0 0 24 24" aria-hidden="true">
  <circle class="status-icon__ring" cx="12" cy="12" r="9" />
  <path class="status-icon__check" d="m7 12 3 3 7-7" />
</svg>

<style>
.status-icon { color: #16a34a; }
.status-icon__ring { fill: none; stroke: currentColor; }
.status-icon__check { fill: none; stroke: currentColor; stroke-linecap: round; }
</style>

External SVGs loaded through <img> cannot be restyled by the embedding page. If you need theme-aware colors, inline the markup, use an SVG sprite, or generate a variant.

Security and cross-origin behavior

Inline SVG shares the host HTML context, so treat inserted SVG markup as active document content and sanitize untrusted input before inserting it. SVG loaded through <img> or a CSS background is processed as an image; scripts do not run and links are not activated. <object>, <iframe>, and <embed> create separate document contexts where same-origin policy, sandboxing, content security policy, and browser restrictions determine what can execute or be accessed.

For untrusted third-party artwork, an image mode is usually simpler. If you use an iframe, consider sandbox and a restrictive Content-Security-Policy. Do not assume that an iframe can be queried from page JavaScript when its origin differs.

Complete decision checklist

  1. Need to query, style, or animate paths? Use inline SVG.
  2. Need a normal content image with caching and alt text? Use <img>.
  3. Need fallback markup or a separate SVG document? Use <object>.
  4. Need isolation or sandboxing? Use <iframe>.
  5. Supporting an older external-content integration? Consider <embed>.
  6. Is it purely decorative? Use a CSS background.

Common errors and fixes

Symptom Likely cause Fix
The SVG is invisible No usable viewBox, zero dimensions, or artwork outside the viewBox Set a correct viewBox and explicit width/height; inspect path coordinates
Inline CSS does nothing The SVG is loaded with <img> or as a background Inline the SVG or edit its source file
JavaScript cannot find paths The SVG is in an image or cross-origin iframe Inline it, use same-origin content, or communicate through a documented message channel
Screen readers announce nothing useful Missing alt, title, or ARIA association Add the appropriate accessible name and description
The image stretches Missing dimensions or an incorrect aspect ratio Set width and height, preserve the aspect ratio, and correct the viewBox
Fallback never appears The resource technically loaded even though its artwork is broken Validate the SVG and provide an explicit adjacent fallback when reliability matters
Iframe content is blocked Cross-origin restrictions, CSP, or sandbox permissions Use same-origin hosting, adjust an intentional policy, or choose <img>
SVG scripts do not run Image-mode embedding disables scripts Use inline SVG or a document embedding method only when trusted and required

Performance and reliability

  • External SVG files can be cached independently, reducing repeated HTML bytes.
  • Inline SVG avoids another request but increases document size and can duplicate bytes across pages.
  • Set dimensions on images and embedded documents to reserve layout space.
  • Use a shared SVG sprite or external files when the same artwork appears many times.
  • Keep decorative backgrounds out of the accessibility tree and avoid using them for essential information.
  • Validate SVG markup during your build so malformed paths or missing viewBox values are caught before deployment.
  • For critical content, provide a meaningful text alternative or a fallback image.

Or skip the browser setup

If your goal is to capture the rendered SVG or the whole page as an image, ScreenshotNeo provides a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP, or PDF. Cookie banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. An MCP server lets AI agents take screenshots, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for the complete option list.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', buffer));

ScreenshotNeo also supports full-page capture with lazy images loaded, CSS-selector element capture, custom CSS and JavaScript, dark mode, device presets, retina scale, waits, request blocking, custom headers and cookies, geolocation, transparent backgrounds, resizing, caching with a chosen TTL, signed links, asynchronous jobs, webhooks, bulk capture, and a usage API.

Free accounts include 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.

FAQ

Can I use an SVG file directly in HTML?

Yes. Use <img>, <object>, <iframe>, or <embed> with the file URL, or paste the SVG markup inline.

Which method is most accessible?

There is no single winner. Use meaningful alt text for informative images, a title and description for informative inline SVG, and a useful title for embedded documents.

Can an external SVG inherit my page’s CSS?

An SVG loaded with <img> or a background does not expose its internal elements to page CSS. Inline SVG does.

Should I use an iframe or object?

Use an iframe when an isolated, optionally sandboxed browsing context is the main requirement. Use object when you want a separate SVG document with fallback content.

Why does my SVG look blurry?

Check that the source has vector paths, a correct viewBox, and dimensions that preserve its aspect ratio. Raster images embedded inside an SVG can still look blurry when enlarged.