SVG Viewer and Editor
See any SVG render beside its markup — viewBox and aspect ratio resolved, every script, handler and external reference named, entirely on this device.
The rendered image appears here when the markup parses.
The preview is a neutralized copy rendered as an image: scripts never run and external references never load. Every readout on this page is computed from your original text.
Press ? for shortcuts
Do it offline:$ xmllint --format icon.svg
How to use it
- Paste your markup into the code pane, or load the sample.
- Read the stage: switch the backdrop between checker, light and dark, and zoom from 25% to 800%.
- Open the rail for the element tally, or the risk list with its lines.
- Switch to Format or Minify to re-serialize the same buffer, then copy the markup or save it.
Paste SVG markup and watch it draw beside the code: the viewBox and the size attributes read out as numbers, the element tally in a rail, and any script, inline handler or off-file reference named with its line. Reformat or minify the same buffer, then copy it back out. Nothing is uploaded — the drawing is rendered in this tab.
How it works
A viewBox is a window, not a size. Its four numbers — min-x, min-y, width, height — declare which rectangle of the drawing's own coordinate space is shown, and every coordinate in the file is measured in those units. The width and height attributes answer a different question: how much room the drawing asks for.
The proportion follows from whichever pair is usable. A width and height in pixels or in an absolute unit win, millimetres and points resolved at 96 pixels to the inch; with neither, the viewBox's third and fourth numbers stand in, which is why a viewBox-only file still scales. A percentage, or a unit relative to text or the viewport, is reported and kept out of that arithmetic.
The drawing on the stage is not your buffer. Scripts, handler attributes and off-file references are dropped from a copy, the copy becomes a blob URL, and an image element draws it — the mode browsers keep static and network-quiet. Every removal is listed beside the stage; copied markup comes from your characters.
Examples
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360"><rect width="640" height="360" fill="#0f172a"/><circle cx="320" cy="180" r="120" fill="#38bdf8"/></svg>viewBox 0 0 640 360
width absent
height absent
size 640 × 360 user units
ratio 1.778
structure 3 elements, 9 attributes, depth 1
elements circle × 1, rect × 1, svg × 1
N_SVG_NO_DIMENSIONS This <svg> has no width or height attribute — it has no intrinsic pixel size, so whatever contains it decides how large it is drawn.A viewBox with no size attributes: the proportion comes from the window's own 640 by 360, printed to the same three decimals the rail shows, and the note says why no pixel figure appears.
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g fill="none" stroke="#111827" stroke-width="2">
<path d="M4 12h16"/>
<path d="M12 4v16"/>
</g>
</svg>
format 208 B in, 199 B out
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g fill="none" stroke="#111827" stroke-width="2">
<path d="M4 12h16"/>
<path d="M12 4v16"/>
</g>
</svg>
minify 208 B in, 182 B out
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" stroke="#111827" stroke-width="2"><path d="M4 12h16"/><path d="M12 4v16"/></g></svg>One buffer, two serializations of one tree. Ragged indentation settles onto two spaces; dropping it saves 26 bytes here, and every d value crosses untouched.
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" onload="alert(1)"><script>fetch("https://x.example/log")</script><use xlink:href="https://evil.example/s.svg#icon"/></svg>census
W_SVG_EVENT_HANDLER Event handler onload="…" on <svg> at line 1 — it is reported here and never executed or emitted.
W_SVG_SCRIPT_PRESENT <script> at line 1 contains script — it is reported here and never executed or emitted.
W_SVG_EXTERNAL_REF xlink:href="https://evil.example/s.svg#icon" on <use> at line 1 points outside this file.
preview source
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><use/></svg>
W_SVG_STRIPPED Removed onload attribute from <svg>.
W_SVG_STRIPPED Removed <script> element and its content.
W_SVG_STRIPPED Removed xlink:href attribute from <use> — only same-document "#id" references are kept.A file that carries behaviour. Three constructs are named with their lines and none is altered in the code pane; the stage draws the shorter copy printed underneath.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
SVG is XML, so sloppy markup is refused, not repaired
An unclosed tag, a bare ampersand or an unquoted value stops the read with a position and a probable cause, and your characters are kept as typed. Browsers are no more forgiving here.
Without xmlns nothing draws, however valid the shapes are
The root needs xmlns="http://www.w3.org/2000/svg" before a browser treats these element names as SVG at all. Copying a fragment out of a page loses it, which is why a drawing that looked fine there arrives here blank.
A percentage is not a size; a millimetre is one, at 96 dpi
width="100%" and width="8mm" are both legal and they part company here: the percentage defers to the box holding the drawing and yields no figure at all, while the millimetre is an absolute length and reads as 30.2362 pixels. Both are reported.
Fonts and off-file references are missing from the stage
A reference pointing anywhere but into the same document is dropped before the copy is drawn, so a linked sprite or an external stylesheet shows as a gap, and text falls back to a local font.
Minify keeps the whitespace that a text element counts on
Space between characters and a nested tspan is content, not layout, so a mixed-content region is emitted byte for byte, as is any subtree marked xml:space="preserve". Indentation between shapes is what goes.
Common errors
Input is larger than the 4 MB limit for this tool.- Past four megabytes the paste is declined whole rather than truncated, because half a document draws as a broken picture. Use the printed command on the file instead.
The root element is <SVG>, not <svg> — this tool needs SVG markup.- XML is case-sensitive, so an uppercase root is a different name and no browser draws it either — a real defect, not a strictness setting. The same message names <html> when a page was pasted.
Closing tag '</svg>' at line 4, column 1 — '<g>' opened at line 2, column 3 is still open; did you forget '</g>'?- The read stops at the first tag that cannot be reconciled and names both positions: where the close appeared, and where the element it should have closed began. Jump to error goes there.
FAQ
Why does my drawing look different in the preview than in my editor?
Three causes cover nearly all of it: a font the file names but does not embed, a reference to something outside it, or behaviour only a script performs. The first two are listed beside the stage, the third in the rail.
Can I edit the markup here, or only look at it?
The code pane is editable and the stage follows what you type. There are no drag handles — paths are edited as characters, which is why every message carries a position.
Is a script inside an SVG file actually dangerous?
It can be, which is why it is reported. Opened as a document an SVG can run script with that page's privileges; through an image element it cannot. The stage uses that path, script dropped.
Does Minify change how my drawing renders?
Not here. Only meaningless whitespace goes: no attribute is rewritten, no coordinate rounded, no element merged or deleted.
Does my file leave this browser?
No. Reading, re-serializing and drawing all happen in this tab, nothing is sent anywhere, and the stage renders from a blob URL only this tab can address.