SVG File Documentation


Summary

An SVG (Scalable Vector Graphics) file is a two-dimensional vector image stored as XML text: shapes, paths, and type are described with maths instead of pixels, so the picture stays sharp at any size. It is an open W3C standard, first published in 2001, and every modern browser opens a .svg file natively. Its MIME type is image/svg+xml. To edit one, use the free Inkscape; to place it where SVG is not accepted, export to PNG.

Technical details

FeatureValue
Full nameScalable Vector Graphics
File extension.svg (gzip-compressed: .svgz)
MIME typeimage/svg+xml
Format type2D vector image, XML text
DeveloperWorld Wide Web Consortium (W3C)
Introduced2001 (SVG 1.0 Recommendation); work began 1999
Latest versionsSVG 1.1 (2011); SVG 2 in development
StandardW3C SVG Recommendation (open, royalty-free)
Open standardYes — W3C web standard, not vendor-owned
Base formatXML 1.0, UTF-8 text
Magic numberNone (plain text; root <svg> element). .svgz is gzip 1F 8B
Editable in text editorsYes — it is human-readable XML
ScalabilityResolution-independent; no quality loss at any size
Graphic elements<path>, <rect>, <circle>, <ellipse>, <polygon>, <text>
StylingPresentation attributes and CSS (fills, strokes, gradients)
Filter effectsSupported (blur, lighting, colour matrix)
Text on pathSupported; text stays real and selectable
ScriptingCan embed JavaScript (also the main security concern)
AnimationSupported via SMIL, CSS, or JavaScript
CompressionOptional gzip as .svgz
AccessibilityText nodes and <title>/<desc> are screen-reader readable
Related extensions.svgz, .ai, .eps, .pdf, .png, .dxf
Specificationw3.org/TR/SVG2/
Syntax at a glance

An SVG is plain UTF-8 XML text with no binary signature. A document is a single root <svg> element, sometimes preceded by an <?xml ?> declaration. The viewBox="min-x min-y width height" attribute sets the coordinate system, which is what lets the image scale to any pixel size without loss. Geometry is drawn with shape elements (<rect>, <circle>, <path>) whose fill, stroke, and other properties can be set as attributes or in a <style> block using CSS. Because it is XML, an SVG can also hold a <script> element and event handlers, so a browser may run code when it renders the file. The compressed variant .svgz is the same XML wrapped in gzip (magic bytes 1F 8B at offset 0).

What is an SVG file?

SVG stands for Scalable Vector Graphics. It is a two-dimensional image format that stores a picture as XML text: instead of a grid of coloured pixels, an SVG describes lines, curves, shapes, and text with numbers and coordinate geometry. The format is an open standard from the World Wide Web Consortium (W3C), not a proprietary Adobe format. SVG 1.0 became a W3C Recommendation in September 2001, SVG 1.1 was published in 2011 (Second Edition), and SVG 2 is still a Candidate Recommendation. The MIME type is image/svg+xml, and the file is normally UTF-8 encoded plain text with no binary header.

Because the drawing is defined by geometry rather than pixels, an SVG has no intrinsic resolution. The renderer recomputes every line and curve at whatever size the image occupies on screen, so one logo file stays sharp on a watch face and on a billboard. The document is a live DOM: it can be styled with CSS, animated, scripted, and inspected node by node. That same programmability is why an SVG is closer to an HTML page than to a PNG or JPG, and it is the root of the security section further down.

The XML document: prolog and namespaces

An SVG is a well-formed XML 1.0 document. It may begin with an XML prolog, <?xml version="1.0" encoding="UTF-8"?>, though a browser will parse a file that opens directly with the <svg> root. An optional DOCTYPE was common in the SVG 1.0 era but is now discouraged; SVG 2 defines no DTD, and leaving the DOCTYPE out avoids validation and entity-expansion problems.

The critical piece is the namespace declaration on the root element. Every SVG element lives in the SVG namespace, declared with the default xmlns="http://www.w3.org/2000/svg". Without that exact URI a browser treats the markup as unknown XML and renders nothing. A second namespace, xmlns:xlink="http://www.w3.org/1999/xlink", was required in SVG 1.1 for the xlink:href attribute used by <use>, gradients, and image references. SVG 2 replaced xlink:href with a plain href, but the xlink form is still parsed for backward compatibility, so many files carry both namespaces.

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     width="240" height="120"
     viewBox="0 0 240 120"
     preserveAspectRatio="xMidYMid meet">
  <defs>
    <linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0%"  stop-color="#2b7de9"/>
      <stop offset="100%" stop-color="#c0e0ff"/>
    </linearGradient>
  </defs>
  <rect x="0" y="0" width="240" height="120" fill="url(#sky)"/>
  <circle cx="60" cy="55" r="34" fill="#fff" stroke="#c0392b" stroke-width="4"/>
  <path d="M120 90 C150 40 190 40 220 90" fill="none" stroke="#333" stroke-width="3"/>
  <text x="120" y="112" text-anchor="middle" font-size="12">SVG</text>
</svg>

The root svg element: width, height and preserveAspectRatio

The <svg> element establishes the outermost viewport. Its width and height give the displayed size of that viewport; a bare number means user units (CSS pixels), and you may also use explicit units such as px, pt, mm, cm, in, or percentages relative to the containing block. If both are omitted, the viewport defaults to 100% of the available space.

The viewBox attribute is the piece that makes SVG resolution-independent. Its four numbers are min-x min-y width height: they define a rectangle in the internal user coordinate system that is mapped onto the viewport. A viewBox="0 0 240 120" sets up an internal grid 240 units wide and 120 tall; the renderer scales that grid to fill the viewport, so changing width/height never forces you to touch a single shape coordinate.

When the viewBox aspect ratio differs from the viewport aspect ratio, preserveAspectRatio decides what happens. It takes an alignment token and a meet-or-slice keyword. The alignment (xMinYMin, xMidYMid, xMaxYMax, and the mixed forms) picks which edge or centre the content anchors to. meet scales the viewBox uniformly until it fits entirely inside the viewport, letterboxing any spare space; slice scales uniformly until the viewport is fully covered, cropping the overflow, which is the behaviour you want for a full-bleed background. The value none disables uniform scaling and stretches the content to fill, distorting it.

The viewBox and the coordinate system

Inside the viewBox the drawing happens in the user coordinate system. The origin (0,0) is the top-left corner; x increases to the right and y increases downward, which is the opposite of a mathematics graph and catches out newcomers. One user unit equals one pixel only at 1:1 scale; after the viewBox transform, a user unit is whatever size the mapping makes it. Lengths written without a unit are user units. Lengths given a unit (10mm, 2pt) are resolved to user units through the standard 96-pixels-per-inch CSS mapping, and percentages resolve against the width, height, or diagonal of the viewport depending on the property.

Any element can further transform its own coordinate system with the transform attribute: translate(tx ty), scale(sx sy), rotate(a cx cy), skewX(a), skewY(a), or an explicit matrix(a b c d e f). Transforms nest, so a group's transform multiplies with each child's, letting you build and reposition whole assemblies without recomputing coordinates.

The basic shapes and their attributes

SVG defines six primitive shape elements, each a shorthand for geometry that a path could also express. <rect> takes x, y, width, height, and optional rx/ry for rounded corners. <circle> takes a centre cx, cy and radius r. <ellipse> adds separate rx and ry radii. <line> draws a segment between x1,y1 and x2,y2. <polyline> and <polygon> both take a points list of coordinate pairs; the polyline stays open while the polygon closes back to its first point. Every shape accepts the presentation attributes fill, stroke, stroke-width, stroke-linecap, stroke-linejoin, stroke-dasharray, and opacity. The fill-rule (nonzero or evenodd) decides how self-intersecting outlines and holes are filled.

The path d grammar

The <path> element is the workhorse: everything else can be built from it. Its geometry lives entirely in one attribute, d, whose value is a string of single-letter commands followed by numeric parameters. An uppercase letter takes absolute coordinates in the user coordinate system; the lowercase form of the same letter takes coordinates relative to the current point. Whitespace and commas between numbers are interchangeable, and a repeated command letter can be dropped for subsequent coordinate sets.

CommandNameParametersEffect
M / mmovetox yStart a new subpath at (x,y); sets the current point without drawing.
L / llinetox yStraight line from the current point to (x,y).
H / hhorizontal linetoxHorizontal line to a new x, keeping y.
V / vvertical linetoyVertical line to a new y, keeping x.
C / ccubic Bézierx1 y1 x2 y2 x yCubic curve using two control points to the endpoint (x,y).
S / ssmooth cubicx2 y2 x yCubic whose first control point mirrors the previous one.
Q / qquadratic Bézierx1 y1 x yQuadratic curve using one control point.
T / tsmooth quadraticx yQuadratic whose control point mirrors the previous one.
A / aelliptical arcrx ry rot large sweep x yArc of an ellipse to (x,y); see the seven parameters below.
Z / zclosepath(none)Straight line back to the subpath's start point.

A subpath begins with a moveto. The line commands are self-explanatory; the interesting ones are the curves. A cubic Bézier (C) is defined by the current point, two control points, and the endpoint, giving the smooth, tunable curves used for most outlines. The smooth form S omits the first control point and reflects the previous curve's second control point through the current point, which keeps a chain of curves visually continuous. Quadratic Béziers (Q) use a single control point and are cheaper; T is their smooth counterpart. The default control-point reflection only applies when the preceding command was the matching curve type, otherwise the control point coincides with the current point.

The elliptical arc A is the one that surprises people, because it carries seven parameters: rx ry x-axis-rotation large-arc-flag sweep-flag x y. The first two are the ellipse radii; the third rotates the ellipse relative to the x-axis. Two given points and two radii admit four possible arcs, so two boolean flags disambiguate: the large-arc-flag chooses the longer (1) or shorter (0) of the two arc segments, and the sweep-flag chooses clockwise (1) or counter-clockwise (0) direction. The final pair is the endpoint. If the radii are too small to span the endpoints, they are scaled up automatically. Finally, Z closes the current subpath with a straight segment back to its moveto point; you can start another subpath afterward without leaving the same d string.

Reusable content: defs, use and symbol

Definitions that are referenced rather than drawn directly go in <defs>, which renders nothing itself. Anything with an id there, or anywhere in the document, can be instantiated with <use href="#id">, which clones the referenced element (or subtree) at a given x, y offset. This is how an icon system reuses one glyph many times without duplicating its path data. The <symbol> element is a template that is never drawn until a <use> references it, and it can carry its own viewBox and preserveAspectRatio, making it the standard container for a sprite sheet of icons where each symbol scales independently.

Gradients, clipPath and mask

Paint servers let a fill or stroke be something richer than a flat colour. A <linearGradient> blends colours along the line from (x1,y1) to (x2,y2); a <radialGradient> blends outward from a focal point across a circle defined by cx, cy, r. Both hold a list of <stop> children, each with an offset (0 to 1 or a percentage), a stop-color, and an optional stop-opacity. You reference a gradient by id: fill="url(#sky)". The gradientUnits attribute chooses whether stop coordinates are relative to the shape's bounding box or to user space.

Two clipping mechanisms exist. A <clipPath> defines a hard-edged region from shapes or paths; pixels outside it are simply not drawn, so clipping is a binary in-or-out test. A <mask> is soft: it multiplies the element's alpha by the luminance (or alpha) of the mask content, so a grey area produces partial transparency and you can fade edges. Clips are cheap and crisp; masks handle gradients and soft vignettes.

Filters and the filter region

The <filter> element applies raster image processing to vector content. A filter contains a pipeline of primitive elements whose names all begin with fe (filter effect). <feGaussianBlur> blurs its input by a stdDeviation; <feColorMatrix> multiplies each pixel's RGBA by a 4×5 matrix, which is how you desaturate, tint, or shift hue and how the common "make transparent PNG-style" alpha tricks are done; <feOffset>, <feBlend>, <feMerge>, and <feFlood> combine to build drop shadows and glows. Each primitive names its input with in and its output with result, so primitives chain like a small dataflow graph, with SourceGraphic and SourceAlpha as the initial inputs.

Filters operate inside a filter region, the bounding rectangle set by the filter's x, y, width, and height. That region defaults to 10% beyond the element's bounding box on each side (-10% -10% 120% 120%), which matters because a blur or shadow that spreads past the region gets clipped. Enlarging a drop shadow therefore often means enlarging the filter region, not just the blur radius. Because filters rasterise their input, applying one gives up some of SVG's resolution independence at very large scales.

Presentation attributes versus CSS styling

Appearance can be set three ways, and they follow a defined precedence. Presentation attributes such as fill="#2b7de9" and stroke-width="4" sit directly on the element and act as the lowest-priority styling, below any CSS. CSS can target the same properties from an internal <style> block, from the style attribute, or, when the SVG is inlined in an HTML page, from the page's own stylesheet, which is how one external stylesheet recolours a whole set of inline icons. Many SVG-specific properties (fill, stroke, stroke-dasharray, stop-color) are usable as CSS properties, not only as attributes. The rule of thumb: presentation attributes give defaults, CSS overrides them, and an inline style attribute or !important wins.

Animation: SMIL versus CSS and JavaScript

SVG carries its own declarative animation from the SMIL family. <animate> tweens a single attribute or property over a duration; <animateTransform> animates a transform (rotate, scale, translate); <animateMotion> moves an element along a path. These elements sit inside the shape they animate and run with no script, driven by attributes like attributeName, from, to, dur, repeatCount, and begin. SMIL is broadly supported in browsers but was for years marked as at-risk, so many authors prefer alternatives. CSS animations and transitions work on SVG elements exactly as they do on HTML and are the usual modern choice for hover and loop effects. For data-driven or interactive graphics, JavaScript manipulates the SVG DOM directly, which is how libraries such as D3.js build live charts as SVG nodes.

How an SVG runs script

Because an SVG is a document with a DOM, it can hold executable content. The <script> element embeds JavaScript exactly as in HTML, and almost every SVG element accepts event-handler attributes: onload, onclick, onmouseover, and the rest. An onload on the root <svg> fires as soon as the document is parsed, so a file needs no user interaction to run code. References such as <a xlink:href="javascript:..."> or href="javascript:..." can also execute code on click. This is by design, so that standalone SVG can be interactive, but it turns any untrusted .svg into a live program rather than a passive picture.

SVG as active content: the safety model

The consequences are concrete. When an SVG is opened as its own document (double-clicked into a browser) or, worse, inlined into another site's HTML with <svg>...</svg>, its scripts and on* handlers run in that page's origin. A crafted upload can therefore steal cookies, rewrite the DOM, or draw a pixel-perfect fake login form, which is why malicious SVGs are a documented cross-site-scripting and phishing vector, including in e-mail attachment campaigns where a "picture" carries a script or an HTML form. Note that an SVG referenced through an HTML <img> tag or a CSS background is sandboxed: browsers block script execution in that mode. The danger is inline rendering and direct document opening.

The defence is sanitisation. A server that accepts user-uploaded SVG should parse it and strip <script> elements, every on* attribute, <foreignObject>, external href references, and javascript: URIs before serving the file to other users; libraries such as DOMPurify in SVG mode do exactly this. Inspecting an SVG's XML in a code editor, or viewing it through a non-scripting viewer, does not run the embedded code, because nothing evaluates the script. Treat an unsolicited .svg the way you would treat a web page, not a JPEG.

SVG shares its geometry-as-instructions model with several other formats this site documents. Adobe Illustrator's native AI format is PDF-compatible and exports cleanly to SVG. EPS is the older PostScript vector interchange used in legacy print workflows, and PDF is itself a vector page format, so SVG-to-PDF is a lossless conversion because both describe paths rather than pixels. Where SVG cannot go is photographs: a photo has no clean geometry to describe, so it stays a raster format such as PNG or JPG. The full element and attribute reference lives in the W3C SVG 2 specification.

References