Introduction to SVG
Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics. Unlike raster image formats (like JPEG, PNG, and GIF) that store image data as a grid of pixels, SVG defines images using mathematical descriptions of geometric shapes.
Think of the difference between vector and raster graphics this way: a raster image is like a mosaic made of tiny tiles (pixels), while a vector image is like a set of instructions for drawing shapes. When you zoom in on a mosaic, you eventually see the individual tiles. But with vector graphics, the shapes are redrawn at any size using the same mathematical instructions, always maintaining crisp edges.
The key advantages of SVG include:
- Scalability: SVGs look crisp at any size, from tiny icons to large banners
- Small file size: Complex graphics often have smaller file sizes than equivalent raster images
- Accessibility: SVG elements can include text descriptions and are searchable
- Animation: Elements can be animated with CSS or JavaScript
- Interactivity: Users can interact with individual parts of an SVG
- Styling: SVG elements can be styled with CSS, just like HTML elements
- Programmability: SVGs can be generated and manipulated with JavaScript
SVG vs. Raster Graphics
To understand the value of SVG, it's important to compare it with raster-based alternatives:
| Feature | SVG (Vector) | PNG/JPEG/GIF (Raster) |
|---|---|---|
| Scaling | Perfect at any size | Becomes pixelated when enlarged |
| File Size | Often smaller for logos, icons, diagrams | Often smaller for photographs, complex textures |
| Complexity | Better for geometric shapes and illustrations | Better for photographs and complex images |
| Animation | Native support via CSS/JS | Requires multiple frames (GIF) or video formats |
| Transparency | Full alpha channel support | Varies (PNG: yes, JPEG: no, GIF: binary) |
| Interactivity | Individual elements can have events | Only the entire image can have events |
| Accessibility | Can include semantic information | Requires alt text only |
| Browser Support | All modern browsers | Universal |
When selecting between SVG and raster formats, consider your specific needs:
- Use SVG for logos, icons, illustrations, diagrams, and interactive graphics
- Use raster formats for photographs, textures, and highly detailed images
A common approach is to combine both: use SVG for UI elements and icons, while using raster formats for content images and photos.
Basic SVG Structure
An SVG document is an XML file that defines vector-based graphics. Here's the simplest possible SVG containing a single circle:
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
Let's break down the essential structure:
- The
<svg>root element defines the SVG canvas - The
widthandheightattributes set the dimensions - The
xmlnsattribute specifies the XML namespace (required) - Inside the SVG element, we define shapes like
<circle> - Each shape has its own specific attributes (
cx,cy,rfor circles) - Styling attributes like
stroke,stroke-width, andfillcontrol appearance
The coordinate system in SVG starts from the top-left corner (0,0) and increases right and down. This is similar to the coordinate system used in HTML elements, but different from the Cartesian coordinate system you might remember from math class.
Basic SVG Shapes
SVG provides several basic shape elements that can be combined to create complex graphics:
| Shape | Element | Key Attributes | Example |
|---|---|---|---|
| Rectangle | <rect> |
x, y, width, height, rx, ry | <rect x="10" y="10" width="80" height="60" rx="5" ry="5" /> |
| Circle | <circle> |
cx, cy, r | <circle cx="50" cy="50" r="40" /> |
| Ellipse | <ellipse> |
cx, cy, rx, ry | <ellipse cx="100" cy="50" rx="80" ry="30" /> |
| Line | <line> |
x1, y1, x2, y2 | <line x1="10" y1="10" x2="90" y2="90" /> |
| Polyline | <polyline> |
points | <polyline points="10,10 30,30 10,50 70,50" /> |
| Polygon | <polygon> |
points | <polygon points="50,10 90,90 10,90" /> |
| Path | <path> |
d | <path d="M10,30 L90,30 L50,90 Z" /> |
Let's visualize these shapes with a practical example:
The Path Element
The <path> element is the most powerful and flexible shape in SVG. It can create any shape using a series of commands in the d (data) attribute:
| Command | Description | Parameters | Example |
|---|---|---|---|
| M/m | Move to | x y | M10,10 (absolute) or m5,5 (relative) |
| L/l | Line to | x y | L50,50 (absolute) or l10,10 (relative) |
| H/h | Horizontal line | x | H50 (absolute) or h10 (relative) |
| V/v | Vertical line | y | V50 (absolute) or v10 (relative) |
| C/c | Cubic Bézier curve | x1 y1 x2 y2 x y | C10,10 20,20 30,30 |
| S/s | Smooth cubic Bézier | x2 y2 x y | S20,20 30,30 |
| Q/q | Quadratic Bézier curve | x1 y1 x y | Q10,10 20,20 |
| T/t | Smooth quadratic Bézier | x y | T20,20 |
| A/a | Elliptical arc | rx ry angle large-arc sweep x y | A30,50 0 0 1 100,100 |
| Z/z | Close path | none | Z (connect to start point) |
Path commands use uppercase letters for absolute coordinates and lowercase for relative coordinates. Think of absolute coordinates as GPS coordinates (go to a specific location), while relative coordinates are like directions (move forward 10 steps).
Here's a heart shape created with a path:
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M100,30
C60,10 10,50 10,90
C10,130 50,150 100,180
C150,150 190,130 190,90
C190,50 140,10 100,30 Z"
fill="red" />
</svg>
The path syntax takes practice to master, but it offers incredible flexibility. For complex shapes, you'll typically use a graphic design tool like Adobe Illustrator, Inkscape, or Figma to create them, then export the SVG code.
Styling SVG Elements
SVG elements can be styled using attributes directly in the elements or with CSS. This dual approach provides flexibility and separation of concerns.
<!-- Styling with attributes (inline) -->
<circle cx="50" cy="50" r="40" fill="blue" stroke="black" stroke-width="2" opacity="0.7" />
<!-- Styling with CSS -->
<style>
.styled-circle {
fill: blue;
stroke: black;
stroke-width: 2;
opacity: 0.7;
}
</style>
<circle class="styled-circle" cx="50" cy="50" r="40" />
Common styling properties include:
| Property | Description | Example |
|---|---|---|
| fill | Interior color of the shape | fill="red" or fill="rgba(255,0,0,0.5)" |
| fill-opacity | Transparency of the fill | fill-opacity="0.5" |
| stroke | Outline color of the shape | stroke="blue" |
| stroke-width | Thickness of the outline | stroke-width="2" |
| stroke-opacity | Transparency of the stroke | stroke-opacity="0.8" |
| stroke-linecap | End style of lines (butt, round, square) | stroke-linecap="round" |
| stroke-linejoin | Join style of lines (miter, round, bevel) | stroke-linejoin="round" |
| stroke-dasharray | Pattern of dashes and gaps | stroke-dasharray="5,5" |
| opacity | Overall transparency of the element | opacity="0.7" |
Using CSS to style SVG offers several advantages:
- Separation of structure and presentation
- Reuse of styles across multiple elements
- Easier dynamic changes with JavaScript
- Support for advanced selectors and media queries
- Animations and transitions
<style>
/* Target SVG elements with CSS */
circle:hover {
fill: red;
transition: fill 0.3s ease;
}
/* Use classes for grouped styling */
.chart-bar {
fill: #2196f3;
}
.chart-bar:nth-child(odd) {
fill: #1565c0;
}
</style>
SVG Organization and Reuse
SVG provides several elements for organizing and reusing content, making complex graphics more manageable:
The <g> Element (Group)
The group element allows you to combine related shapes and apply transformations or styles to them collectively:
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<g fill="blue" transform="translate(20, 20)">
<rect x="0" y="0" width="60" height="60" />
<circle cx="100" cy="30" r="30" />
</g>
</svg>
The <defs> and <use> Elements
These elements enable you to define shapes once and reuse them multiple times:
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="shape">
<rect x="0" y="0" width="50" height="50" />
<circle cx="25" cy="25" r="20" fill="red" />
</g>
</defs>
<use href="#shape" x="10" y="10" />
<use href="#shape" x="100" y="10" />
<use href="#shape" x="190" y="10" />
</svg>
The <symbol> Element
Similar to <defs> but better for creating reusable icon libraries as it supports viewBox:
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-star" viewBox="0 0 100 100">
<polygon points="50,10 61,35 90,40 70,60 75,90 50,75 25,90 30,60 10,40 39,35" />
</symbol>
<use href="#icon-star" x="10" y="10" width="50" height="50" fill="gold" />
<use href="#icon-star" x="70" y="10" width="30" height="30" fill="silver" />
</svg>
This approach is conceptually similar to creating reusable components in modern web development frameworks. It promotes efficiency and consistency across your graphics.
Integrating SVG in Web Pages
There are multiple ways to include SVG in web pages, each with different characteristics:
| Method | Code Example | Advantages | Limitations |
|---|---|---|---|
| Inline SVG | <svg>...</svg> directly in HTML |
|
|
| IMG tag | <img src="image.svg" alt="Description" /> |
|
|
| CSS Background | background-image: url('image.svg'); |
|
|
| Object tag | <object data="image.svg" type="image/svg+xml"></object> |
|
|
| Iframe | <iframe src="image.svg"></iframe> |
|
|
For most interactive applications, inline SVG is the recommended approach:
<!-- Inline SVG Example -->
<div class="chart-container">
<h2>Monthly Sales</h2>
<svg width="500" height="300" viewBox="0 0 500 300">
<rect class="bar" x="50" y="50" width="50" height="200" />
<rect class="bar" x="120" y="100" width="50" height="150" />
<rect class="bar" x="190" y="80" width="50" height="170" />
<rect class="bar" x="260" y="30" width="50" height="220" />
<rect class="bar" x="330" y="70" width="50" height="180" />
<!-- X-axis labels -->
<text x="75" y="270" text-anchor="middle">Jan</text>
<text x="145" y="270" text-anchor="middle">Feb</text>
<text x="215" y="270" text-anchor="middle">Mar</text>
<text x="285" y="270" text-anchor="middle">Apr</text>
<text x="355" y="270" text-anchor="middle">May</text>
</svg>
</div>
<style>
.bar {
fill: #2196f3;
transition: fill 0.3s;
}
.bar:hover {
fill: #ff9800;
}
</style>
SVG Transformations
SVG elements can be transformed in various ways using the transform attribute:
| Transformation | Syntax | Description |
|---|---|---|
| translate | transform="translate(x, y)" |
Moves an element by x units horizontally and y units vertically |
| rotate | transform="rotate(angle [cx cy])" |
Rotates an element by angle degrees, optionally around point (cx, cy) |
| scale | transform="scale(x [y])" |
Resizes an element by x horizontally and y vertically (if y is omitted, it equals x) |
| skewX | transform="skewX(angle)" |
Skews an element along the x-axis by angle degrees |
| skewY | transform="skewY(angle)" |
Skews an element along the y-axis by angle degrees |
| matrix | transform="matrix(a b c d e f)" |
Applies a custom transformation matrix for advanced transformations |
Multiple transformations can be combined in a single attribute:
transform="translate(100, 50) rotate(45) scale(1.5)"
The order of transformations matters! Each transformation is applied to the result of the previous one.
Transformations are essential for creating complex graphics, animations, and interactive elements. They're conceptually similar to CSS transforms but operate within the SVG coordinate system.
Text in SVG
SVG allows for precise control over text positioning and appearance:
<svg width="400" height="100" xmlns="http://www.w3.org/2000/svg">
<text x="20" y="50" font-family="Arial" font-size="24" fill="blue">
Basic SVG Text
</text>
<text x="20" y="80" font-family="Arial" font-size="16">
Text with <tspan fill="red" font-weight="bold">styled</tspan> segments
</text>
</svg>
Key text-related elements and attributes include:
<text>: The main element for displaying text<tspan>: For styling spans of text within a text element<textPath>: For rendering text along a pathx,y: Positioning coordinatesdx,dy: Relative position adjustmentstext-anchor: Text alignment (start, middle, end)dominant-baseline: Vertical alignment
Text in SVG is particularly useful for:
- Chart labels and annotations
- Captions and titles that need precise positioning
- Creative typography and text effects
- Logos and branding elements
- Internationalized content (SVG supports Unicode)
Practical Example: Creating an Interactive Chart
Let's combine what we've learned to create a simple interactive bar chart:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SVG Interactive Chart Example</title>
<style>
.chart-container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.bar {
fill: #2196f3;
transition: all 0.3s ease;
}
.bar:hover {
fill: #ff9800;
cursor: pointer;
}
.bar-label {
font-size: 12px;
text-anchor: middle;
fill: #333;
}
.axis {
stroke: #ccc;
stroke-width: 1;
}
.axis-label {
font-size: 14px;
fill: #666;
}
.chart-title {
font-size: 18px;
font-weight: bold;
text-anchor: middle;
fill: #333;
}
.tooltip {
position: absolute;
padding: 8px;
background: #333;
color: white;
border-radius: 4px;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
}
</style>
</head>
<body>
<div class="chart-container">
<svg width="600" height="350" viewBox="0 0 600 350">
<!-- Chart title -->
<text x="300" y="30" class="chart-title">Monthly Sales Data (2025)</text>
<!-- X and Y axes -->
<line x1="50" y1="300" x2="550" y2="300" class="axis" />
<line x1="50" y1="50" x2="50" y2="300" class="axis" />
<!-- Y-axis labels -->
<text x="45" y="300" text-anchor="end" class="axis-label">0</text>
<text x="45" y="225" text-anchor="end" class="axis-label">25K</text>
<text x="45" y="150" text-anchor="end" class="axis-label">50K</text>
<text x="45" y="75" text-anchor="end" class="axis-label">75K</text>
<!-- Horizontal grid lines -->
<line x1="50" y1="225" x2="550" y2="225" stroke="#eee" />
<line x1="50" y1="150" x2="550" y2="150" stroke="#eee" />
<line x1="50" y1="75" x2="550" y2="75" stroke="#eee" />
<!-- Bars -->
<g id="bars">
<rect class="bar" x="80" y="200" width="40" height="100" data-value="25000" data-month="January" />
<rect class="bar" x="140" y="160" width="40" height="140" data-value="35000" data-month="February" />
<rect class="bar" x="200" y="120" width="40" height="180" data-value="45000" data-month="March" />
<rect class="bar" x="260" y="80" width="40" height="220" data-value="55000" data-month="April" />
<rect class="bar" x="320" y="100" width="40" height="200" data-value="50000" data-month="May" />
<rect class="bar" x="380" y="140" width="40" height="160" data-value="40000" data-month="June" />
<rect class="bar" x="440" y="180" width="40" height="120" data-value="30000" data-month="July" />
<rect class="bar" x="500" y="220" width="40" height="80" data-value="20000" data-month="August" />
</g>
<!-- X-axis labels -->
<text x="100" y="320" text-anchor="middle" class="axis-label">Jan</text>
<text x="160" y="320" text-anchor="middle" class="axis-label">Feb</text>
<text x="220" y="320" text-anchor="middle" class="axis-label">Mar</text>
<text x="280" y="320" text-anchor="middle" class="axis-label">Apr</text>
<text x="340" y="320" text-anchor="middle" class="axis-label">May</text>
<text x="400" y="320" text-anchor="middle" class="axis-label">Jun</text>
<text x="460" y="320" text-anchor="middle" class="axis-label">Jul</text>
<text x="520" y="320" text-anchor="middle" class="axis-label">Aug</text>
</svg>
<div id="tooltip" class="tooltip"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const bars = document.querySelectorAll('.bar');
const tooltip = document.getElementById('tooltip');
bars.forEach(bar => {
bar.addEventListener('mouseover', function(e) {
// Get data values from attributes
const value = this.getAttribute('data-value');
const month = this.getAttribute('data-month');
// Format value with comma separators
const formattedValue = parseInt(value).toLocaleString();
// Update and position tooltip
tooltip.innerHTML = `${month}: $${formattedValue}`;
tooltip.style.left = (e.pageX + 10) + 'px';
tooltip.style.top = (e.pageY - 40) + 'px';
tooltip.style.opacity = 1;
});
bar.addEventListener('mousemove', function(e) {
// Update tooltip position as mouse moves
tooltip.style.left = (e.pageX + 10) + 'px';
tooltip.style.top = (e.pageY - 40) + 'px';
});
bar.addEventListener('mouseout', function() {
// Hide tooltip
tooltip.style.opacity = 0;
});
bar.addEventListener('click', function() {
// Example of responding to clicks
alert(`${this.getAttribute('data-month')} sales: $${parseInt(this.getAttribute('data-value')).toLocaleString()}`);
});
});
});
</script>
</body>
</html>
This example demonstrates several key SVG concepts:
- Creating a structured, semantic diagram with axes and labels
- Using data attributes to store information with each visual element
- Applying CSS styling and transitions for visual appeal
- Adding JavaScript interactivity for tooltips and click events
- Combining SVG with HTML/CSS for enhanced functionality
The result is a professional-looking, interactive chart that scales perfectly at any size and provides rich user interaction.
SVG Optimization
Before deploying SVG in production, consider optimizing for performance:
Manual Optimization Tips:
- Remove unnecessary elements, comments, and metadata
- Simplify paths by reducing the number of points
- Round decimal values to fewer places (e.g., 10.3456 to 10.35)
- Use compact syntax (e.g., hex colors #000 instead of #000000)
- Remove default attributes that aren't needed
- Group similar elements with shared styles
Automated Optimization Tools:
- SVGO: Command line tool and Node.js library for optimization
- SVGOMG: Web-based UI for SVGO
- Inkscape: "Save as Optimized SVG" option
- SVG Optimizer in Adobe Illustrator
Example of optimization results:
/* Before optimization */
/* Before optimization */
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100" viewBox="0 0 100 100" version="1.1" id="svg8">
<defs id="defs2">
<linearGradient id="linearGradient1">
<stop style="stop-color:#0000ff;stop-opacity:1;" offset="0" id="stop1"/>
<stop style="stop-color:#00ffff;stop-opacity:1.0000000" offset="1.0000000" id="stop2"/>
</linearGradient>
</defs>
<!-- This is a blue circle -->
<circle style="fill:url(#linearGradient1);fill-opacity:1.0;stroke:#000000;stroke-width:2.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000" id="path10" cx="50.000000" cy="50.000000" r="40.000000"/>
</svg>
/* After optimization */
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<defs>
<linearGradient id="a">
<stop offset="0" stop-color="#00f"/>
<stop offset="1" stop-color="#0ff"/>
</linearGradient>
</defs>
<circle cx="50" cy="50" r="40" fill="url(#a)" stroke="#000" stroke-width="2"/>
</svg>
The optimized version is about 65% smaller but renders identically in the browser. For large, complex SVGs, optimization can make a significant difference in loading times and performance.
SVG Accessibility
Making SVG accessible ensures that your graphics are usable by everyone, including people using assistive technologies:
- Title and Description: Add
<title>and<desc>elements - ARIA attributes: Use
roleandaria-*attributes - Focus management: Make interactive elements focusable
- Keyboard navigation: Support keyboard interaction
- Text alternatives: Include fallback content for complex graphics
<svg role="img" aria-labelledby="chartTitle chartDesc" viewBox="0 0 100 100">
<title id="chartTitle">Annual Sales Growth</title>
<desc id="chartDesc">Bar chart showing 15% growth in sales from 2024 to 2025</desc>
<!-- Chart content... -->
<g role="button" tabindex="0" aria-label="View sales details"
onkeydown="if(event.key==='Enter')showDetails();"
onclick="showDetails();">
<!-- Interactive element content... -->
</g>
</svg>
Following these practices makes SVG content perceivable and operable for users with disabilities, similar to how proper signage and ramps make physical buildings accessible to everyone.
Practice Activities
Basic Exercise: Create a Logo
Design a simple logo using basic SVG shapes. Include at least three different shape types and use gradients or solid colors. Make sure the SVG is properly structured with appropriate viewBox settings.
Intermediate Exercise: Interactive Icon Set
Create a set of 4-6 related icons (e.g., social media icons, weather symbols, or UI controls) using the <symbol> and <use> elements. Add hover effects with CSS and basic click interactions with JavaScript.
Advanced Exercise: Data Visualization
Build a data visualization (pie chart, line graph, or bar chart) using SVG. Use real or sample data, implement proper labeling, and add interactive features like tooltips on hover.
Challenge Project: Animated Infographic
Create an animated infographic that tells a story with data. Use multiple SVG techniques, including paths, text, and groups. Implement animations with CSS or JavaScript and ensure the infographic is accessible with appropriate ARIA attributes and text alternatives.
Exploration Activity: SVG Filters
Research and experiment with SVG filters (not covered in this lecture). Try implementing effects like drop shadows, blurs, or color transformations on SVG elements. Document your findings and share examples of the effects.
Additional Resources
- MDN Web Docs: SVG - Comprehensive reference and tutorials
- W3C SVG Working Group - Official specifications
- CSS-Tricks: SVG Properties and CSS - In-depth styling techniques
- SVGOMG - Online SVG optimization tool
- Inkscape - Free and open-source SVG editor
- D3.js - JavaScript library for creating data visualizations with SVG
- Snap.svg - JavaScript library for SVG manipulation