<svg> : The SVG Canvas Container
The <svg> element is the root container for Scalable Vector Graphics (SVG) content in PDF documents. It creates a self-contained graphics canvas that can contain shapes, paths, text, images, and other SVG elements. The SVG canvas supports coordinate systems, viewports, transformations, and reusable definitions.
Usage
The <svg> element creates a vector graphics container that:
- Defines a coordinate system and viewport for vector graphics rendering
- Supports all SVG shape elements (rect, circle, path, line, etc.)
- Can be embedded inline in HTML content or used as a standalone graphic
- Scales perfectly in PDF output without quality loss
- Supports the
<defs>element for reusable graphics definitions - Handles transformations, gradients, and patterns
- Can be data-bound for dynamic graphics generation
<svg width="200pt" height="100pt" viewBox="0 0 200 100">
<rect x="10" y="10" width="180" height="80"
fill="#336699" stroke="#000" stroke-width="2"/>
<text x="100" y="55" text-anchor="middle" fill="white" font-size="20">
SVG in PDF
</text>
</svg>
Supported Attributes
Dimensional Attributes
| Attribute | Type | Description |
|---|---|---|
width |
Unit | Width of the SVG canvas. Default: 300pt (when not embedded) |
height |
Unit | Height of the SVG canvas. Default: 150pt (when not embedded) |
x |
Unit | Horizontal position when SVG is nested or positioned |
y |
Unit | Vertical position when SVG is nested or positioned |
Viewport Attributes
| Attribute | Type | Description |
|---|---|---|
viewBox |
string | Defines the coordinate system: “min-x min-y width height”. Controls scaling and aspect ratio. |
preserveAspectRatio |
string | Controls how the viewBox is scaled to fit the viewport. Values: none, xMinYMin, xMidYMid (default), xMaxYMax, etc. |
Standard Attributes
| Attribute | Type | Description |
|---|---|---|
id |
string | Unique identifier for the SVG canvas. Required for internal references. |
class |
string | CSS class name(s) for styling. Multiple classes separated by spaces. |
style |
string | Inline CSS/SVG styles applied to the canvas and inherited by children. |
title |
string | Title for accessibility and outline/bookmark generation. |
hidden |
string | Controls visibility. Set to “hidden” to hide, or omit to show. |
xmlns |
string | XML namespace (typically “http://www.w3.org/2000/svg”). Usually auto-applied. |
Graphics Attributes (Inherited by Children)
| Attribute | Type | Description |
|---|---|---|
fill |
color | Default fill color for child shapes. Values: color names, hex (#RGB, #RRGGBB), none |
fill-opacity |
number | Opacity for fills (0.0 to 1.0). Default: 1.0 |
stroke |
color | Default stroke color for child shapes |
stroke-width |
Unit | Default stroke width. Default: 1pt |
stroke-opacity |
number | Opacity for strokes (0.0 to 1.0). Default: 1.0 |
stroke-linecap |
string | Line cap style: butt, round, square |
stroke-linejoin |
string | Line join style: miter, round, bevel |
stroke-dasharray |
string | Dash pattern for strokes: “5,5” for dashed, “10,5,2,5” for complex patterns |
Content Elements
| Element | Description |
|---|---|
<defs> |
Container for reusable definitions (gradients, patterns, symbols, shapes) |
| Content | Any SVG shape, text, group, or container elements |
Notes
SVG Canvas Behavior
- Default Size: When used inline in HTML, defaults to 300pt x 150pt if no dimensions specified
- Inline Display: Renders as
inline-blockby default, flows with surrounding content - Coordinate System: Uses its own coordinate space, independent of PDF page coordinates
- Clipping: Content outside the SVG bounds is automatically clipped
- Never Splits: SVG canvases never split across pages (overflow-split: never)
ViewBox and Coordinate Systems
The viewBox attribute defines the user coordinate system:
<!-- viewBox="min-x min-y width height" -->
<svg width="200pt" height="100pt" viewBox="0 0 400 200">
<!-- Canvas is 200pt wide, but coordinates use 0-400 scale -->
<!-- Graphics are scaled down 2x to fit -->
</svg>
Key concepts:
- The
width/heightdefine the canvas size in the document - The
viewBoxdefines the internal coordinate system - Content is scaled to map viewBox coordinates to canvas dimensions
- Useful for creating resolution-independent graphics
Preserve Aspect Ratio
The preserveAspectRatio attribute controls scaling behavior:
none: Stretch to fill, ignoring aspect ratioxMidYMid meet(default): Scale uniformly, centered, entire viewBox visiblexMidYMid slice: Scale uniformly, centered, fill entire viewport- Alignment:
xMin,xMid,xMaxwithYMin,YMid,YMax - Meet/Slice:
meet(show all),slice(fill viewport)
Definitions Container
The <defs> element inside <svg> holds reusable content:
<svg width="200pt" height="200pt">
<defs>
<linearGradient id="grad1">
<stop offset="0%" stop-color="blue"/>
<stop offset="100%" stop-color="red"/>
</linearGradient>
<circle id="dot" r="5" fill="black"/>
</defs>
<rect width="200" height="200" fill="url(#grad1)"/>
<use href="#dot" x="50" y="50"/>
</svg>
Nested SVG
SVG elements can be nested for complex compositions:
<svg width="400pt" height="200pt">
<svg x="0" y="0" width="200" height="200" viewBox="0 0 100 100">
<!-- First graphic -->
</svg>
<svg x="200" y="0" width="200" height="200" viewBox="0 0 100 100">
<!-- Second graphic -->
</svg>
</svg>
Style Application
Styles defined on the <svg> element cascade to children:
<svg width="200pt" height="100pt" fill="blue" stroke="black" stroke-width="2">
<!-- All child shapes inherit these styles unless overridden -->
<circle cx="50" cy="50" r="30"/>
<rect x="120" y="20" width="60" height="60" fill="red"/>
</svg>
Class Hierarchy
In the Scryber codebase:
SVGCanvasextendsCanvasimplementsIResourceContainer,ICanvas,INamingContainer- Maintains its own resource list for gradients, patterns, etc.
- Acts as naming container for ID-based references within the SVG
- Uses specialized
LayoutEngineSVGfor rendering
Data Binding
Dynamic SVG Generation
SVG content can be generated dynamically using data binding:
<!-- Model: { items: [{x:50, y:50, r:20, color:"red"}, {x:150, y:50, r:30, color:"blue"}] } -->
<svg width="300pt" height="150pt" viewBox="0 0 300 150">
<template data-bind="">
<circle cx="" cy="" r="" fill=""/>
</template>
</svg>
Parameterized Graphics
<!-- Model: { chartData: { width: 400, height: 200, bars: [...] } } -->
<svg width="pt" height="pt">
<template data-bind="">
<rect x="" y="" width="" height=""
fill="" opacity=""/>
</template>
</svg>
Conditional SVG Content
<svg width="200pt" height="200pt">
<rect width="200" height="200" fill="#f0f0f0"/>
<g hidden="">
<circle cx="100" cy="100" r="50" fill="blue"/>
<text x="100" y="105" text-anchor="middle">Details</text>
</g>
</svg>
Data-Driven Styling
<!-- Model: { status: "warning", bgColor: "#ff9900", message: "Alert" } -->
<svg width="300pt" height="100pt">
<rect width="300" height="100" fill="" rx="5"/>
<text x="150" y="55" text-anchor="middle" fill="white" font-size="20">
</text>
</svg>
Examples
Basic SVG with Shapes
<svg width="200pt" height="200pt" viewBox="0 0 200 200">
<rect x="10" y="10" width="180" height="180"
fill="none" stroke="#336699" stroke-width="2"/>
<circle cx="100" cy="100" r="60" fill="#ff6347" opacity="0.7"/>
<line x1="40" y1="40" x2="160" y2="160"
stroke="black" stroke-width="2"/>
</svg>
SVG with ViewBox Scaling
<!-- Canvas is 150pt square, but uses 0-100 coordinate system -->
<svg width="150pt" height="150pt" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="45" fill="#336699" stroke="white" stroke-width="2"/>
<text x="50" y="55" text-anchor="middle" fill="white"
font-size="12" font-family="Arial">
Scaled
</text>
</svg>
SVG with Gradient Definitions
<svg width="250pt" height="150pt" viewBox="0 0 250 150">
<defs>
<linearGradient id="blueGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#4a90e2"/>
<stop offset="100%" stop-color="#0066cc"/>
</linearGradient>
<radialGradient id="sunGradient" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#ffff00"/>
<stop offset="100%" stop-color="#ff9900"/>
</radialGradient>
</defs>
<rect width="250" height="150" fill="url(#blueGradient)"/>
<circle cx="200" cy="40" r="30" fill="url(#sunGradient)"/>
</svg>
Nested SVG Canvases
<svg width="400pt" height="200pt">
<svg x="10" y="10" width="180" height="180" viewBox="0 0 100 100">
<rect width="100" height="100" fill="#e8f4f8"/>
<circle cx="50" cy="50" r="40" fill="#336699"/>
</svg>
<svg x="210" y="10" width="180" height="180" viewBox="0 0 100 100">
<rect width="100" height="100" fill="#fff4e8"/>
<rect x="20" y="20" width="60" height="60" fill="#ff9900"/>
</svg>
</svg>
SVG with Reusable Symbols
<svg width="300pt" height="200pt">
<defs>
<g id="star">
<path d="M 0,-10 L 2,-2 L 10,-2 L 4,2 L 6,10 L 0,5 L -6,10 L -4,2 L -10,-2 L -2,-2 Z"
fill="gold" stroke="#cc9900" stroke-width="0.5"/>
</g>
</defs>
<use href="#star" x="50" y="50"/>
<use href="#star" x="150" y="50" transform="scale(1.5)"/>
<use href="#star" x="250" y="50" transform="scale(2)"/>
</svg>
SVG with Inherited Styles
<svg width="300pt" height="100pt" fill="none" stroke="#336699" stroke-width="3">
<!-- All children inherit the stroke settings -->
<circle cx="50" cy="50" r="30"/>
<circle cx="150" cy="50" r="30" fill="red"/>
<circle cx="250" cy="50" r="30" fill="blue" stroke="red"/>
</svg>
Responsive SVG (PreserveAspectRatio)
<!-- Different scaling behaviors -->
<svg width="200pt" height="100pt" viewBox="0 0 100 100"
preserveAspectRatio="none">
<!-- Stretches to fill container, distorts aspect ratio -->
<circle cx="50" cy="50" r="40" fill="#336699"/>
</svg>
<svg width="200pt" height="100pt" viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid meet">
<!-- Maintains aspect ratio, centered, all visible -->
<circle cx="50" cy="50" r="40" fill="#336699"/>
</svg>
SVG Chart with Data Binding
<!-- Model: { chartData: [
{label: "Q1", value: 75, color: "#4a90e2"},
{label: "Q2", value: 120, color: "#50c878"},
{label: "Q3", value: 95, color: "#ff9900"}
]} -->
<svg width="400pt" height="250pt" viewBox="0 0 400 250">
<rect width="400" height="250" fill="#f9f9f9"/>
<text x="200" y="30" text-anchor="middle" font-size="20" font-weight="bold">
Quarterly Results
</text>
<template data-bind="">
<g transform="translate(50, 200)">
<rect x="0" y="1" width="60" height=""
fill="" stroke="black" stroke-width="1"/>
<text x="30" y="20" text-anchor="middle" font-size="12"></text>
<text x="30" y="1" text-anchor="middle" font-size="10">
</text>
</g>
</template>
</svg>
SVG with Patterns
<svg width="300pt" height="200pt">
<defs>
<pattern id="dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="3" fill="#336699"/>
</pattern>
<pattern id="stripes" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse">
<rect width="5" height="10" fill="#ff6347"/>
</pattern>
</defs>
<rect x="10" y="10" width="130" height="180" fill="url(#dots)"/>
<rect x="160" y="10" width="130" height="180" fill="url(#stripes)"/>
</svg>
Icon Library with Defs
<svg width="300pt" height="100pt">
<defs>
<g id="checkIcon">
<circle r="15" fill="#50c878" stroke="#2d7d4d" stroke-width="2"/>
<path d="M -6,0 L -2,5 L 8,-8" stroke="white" stroke-width="3"
fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<g id="errorIcon">
<circle r="15" fill="#ff4444" stroke="#cc0000" stroke-width="2"/>
<line x1="-6" y1="-6" x2="6" y2="6" stroke="white" stroke-width="3"
stroke-linecap="round"/>
<line x1="6" y1="-6" x2="-6" y2="6" stroke="white" stroke-width="3"
stroke-linecap="round"/>
</g>
</defs>
<use href="#checkIcon" x="75" y="50"/>
<use href="#errorIcon" x="225" y="50"/>
</svg>
SVG Logo with Title
<svg width="200pt" height="80pt" viewBox="0 0 200 80" title="Company Logo">
<defs>
<linearGradient id="logoGradient">
<stop offset="0%" stop-color="#336699"/>
<stop offset="100%" stop-color="#6699cc"/>
</linearGradient>
</defs>
<rect width="200" height="80" fill="url(#logoGradient)" rx="10"/>
<text x="100" y="45" text-anchor="middle" fill="white"
font-size="28" font-family="Arial" font-weight="bold">
COMPANY
</text>
<text x="100" y="65" text-anchor="middle" fill="white"
font-size="12" font-family="Arial">
Making PDFs Better
</text>
</svg>
Dynamic Gauge Chart
<!-- Model: { percentage: 75, status: "good" } -->
<svg width="200pt" height="200pt" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="80" fill="none"
stroke="#e0e0e0" stroke-width="20"/>
<circle cx="100" cy="100" r="80" fill="none"
stroke=""
stroke-width="20"
stroke-dasharray=", 502.4"
transform="rotate(-90 100 100)"/>
<text x="100" y="105" text-anchor="middle" font-size="40" font-weight="bold">
%
</text>
</svg>
SVG Map with Interactive Elements
<svg width="400pt" height="300pt" viewBox="0 0 400 300">
<defs>
<filter id="shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="2" dy="2" result="offsetblur"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<rect width="400" height="300" fill="#e8f4f8"/>
<g id="location1" filter="url(#shadow)">
<circle cx="100" cy="100" r="20" fill="#ff6347"/>
<text x="100" y="140" text-anchor="middle" font-size="12">Location A</text>
</g>
<g id="location2" filter="url(#shadow)">
<circle cx="300" cy="150" r="20" fill="#336699"/>
<text x="300" y="190" text-anchor="middle" font-size="12">Location B</text>
</g>
</svg>
SVG Timeline
<!-- Model: { events: [{year: "2020", title: "Founded", x: 50}, ...] } -->
<svg width="500pt" height="150pt" viewBox="0 0 500 150">
<line x1="50" y1="75" x2="450" y2="75"
stroke="#336699" stroke-width="4"/>
<template data-bind="">
<g>
<circle cx="" cy="75" r="8" fill="#336699" stroke="white" stroke-width="2"/>
<text x="" y="55" text-anchor="middle" font-size="12" font-weight="bold">
</text>
<text x="" y="105" text-anchor="middle" font-size="10">
</text>
</g>
</template>
</svg>
SVG Status Badge
<!-- Model: { count: 5, type: "error" } -->
<svg width="80pt" height="30pt" viewBox="0 0 80 30">
<rect width="80" height="30"
fill=""
rx="5"/>
<text x="40" y="20" text-anchor="middle" fill="white"
font-size="14" font-weight="bold">
:
</text>
</svg>
Complex Dashboard Panel
<svg width="600pt" height="400pt" viewBox="0 0 600 400">
<defs>
<linearGradient id="headerGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#336699"/>
<stop offset="100%" stop-color="#254a70"/>
</linearGradient>
</defs>
<!-- Header -->
<rect width="600" height="60" fill="url(#headerGrad)"/>
<text x="20" y="40" fill="white" font-size="24" font-weight="bold">
Dashboard Overview
</text>
<!-- Grid panels -->
<rect x="20" y="80" width="270" height="140" fill="white"
stroke="#ddd" stroke-width="2" rx="5"/>
<rect x="310" y="80" width="270" height="140" fill="white"
stroke="#ddd" stroke-width="2" rx="5"/>
<rect x="20" y="240" width="270" height="140" fill="white"
stroke="#ddd" stroke-width="2" rx="5"/>
<rect x="310" y="240" width="270" height="140" fill="white"
stroke="#ddd" stroke-width="2" rx="5"/>
<!-- Panel content placeholders -->
<text x="155" y="155" text-anchor="middle" font-size="16" fill="#999">
Chart A
</text>
<text x="445" y="155" text-anchor="middle" font-size="16" fill="#999">
Chart B
</text>
<text x="155" y="315" text-anchor="middle" font-size="16" fill="#999">
Chart C
</text>
<text x="445" y="315" text-anchor="middle" font-size="16" fill="#999">
Chart D
</text>
</svg>
See Also
- g - Group container for organizing SVG elements
- defs - Definitions container for reusable elements
- use - Reference and reuse defined elements
- a - SVG anchor/link element
- SVG Shapes - rect, circle, ellipse, line, polyline, polygon, path
- SVG Text - Text rendering in SVG
- Canvas Component - Base canvas component
- Data Binding - Data binding and expressions
- Gradients - Linear and radial gradients
- Patterns - Pattern fills