SVG: A Beginner-to-Advanced Guide to Vector Graphics
This guide explains SVG from first principles and builds toward practical browser examples.
If you're a front-end developer, or a designer with a bit of code OCD, you definitely have a love-hate relationship with SVG (Scalable Vector Graphics).
You love it because it's crisp, sharp, tiny in file size, and you can mess with it however you want using CSS and JS;
You hate it because when you open an SVG file, a screen full of <path d="M... C... Z"> looks like alien hieroglyphics — one glance and your hair starts falling out.
But today, we're going to end this fear! We'll use the most intuitive code and real browser-rendered results to conquer SVG step by step.
Chapter 1: What is SVG? (Why Don't We Just Use PNG?)
SVG isn't some mysterious high-tech thing — it's essentially just an XML file.
Yes, just like HTML, you can open it in any text editor and use tags to describe graphics.
Why not PNG?
PNG is a raster image (bitmap). When you zoom into a PNG, it's like a mosaic puzzle — the more you zoom, the more obvious the mosaic becomes.
SVG, on the other hand, is a vector image. It records mathematical formulas: "Draw a circle with radius 5 at coordinate (10,10)." So no matter how much you zoom in, the browser recalculates and re-renders the circle — it never blurs!
Let's look at the most intuitive example.
1.1 Your First SVG
Let's hand-code the simplest possible SVG. We need a canvas.
<svg width="200" height="200" style="background: #f0f4f8; border-radius: 12px;">
<!-- We'll draw here -->
</svg>
[Live Front-End Rendering]
This is a blank canvas. Nothing on it, but it represents infinite possibilities.
Chapter 2: Basic Shapes — Becoming a Geometry Master
SVG provides some preset "brushes" that let you easily draw basic geometric shapes.
2.1 Rectangle <rect>
The <rect> tag draws rectangles. You need to tell it:
x,y: The coordinates of the top-left corner (in SVG, the top-left corner is (0,0))width,height: Width and heightfill: Fill colorrx,ry: Corner radius (for rounded corners)
<svg width="300" height="150" style="background: #f0f4f8; border-radius: 12px;">
<rect x="50" y="25" width="200" height="100" rx="20" fill="#FF7F50" />
</svg>
[Live Front-End Rendering]
See! With just one line of code, you've drawn an orange rectangle with rounded corners! Isn't that so much simpler than using Canvas?
2.2 Circle <circle>
Drawing a circle is even simpler. You need to specify:
cx,cy: The center coordinates (Center X, Center Y)r: The radius
<svg width="200" height="200" style="background: #f0f4f8; border-radius: 12px;">
<circle cx="100" cy="100" r="60" fill="#4169E1" stroke="#FFD700" stroke-width="10" />
</svg>
Note: I added stroke (outline) and stroke-width (outline thickness) here.
[Live Front-End Rendering]
The feeling you get when you hand-code a perfect circle for the first time — it's practically transcendent!
2.3 Ellipse <ellipse>, Polygon <polygon>, and Line <line>
These siblings work pretty much the same way:
ellipse— just splits the radius into horizontalrxand verticalry.line— just specifies a start point(x1, y1)and an end point(x2, y2).polygon— takes a bunch ofpoints="x,y x,y x,y"and connects them into a closed shape.
Let's bring them all together for a meeting:
<svg width="400" height="200" style="background: #1e1e2f; border-radius: 12px;">
<!-- Ellipse -->
<ellipse cx="80" cy="100" rx="50" ry="80" fill="#00FF7F" />
<!-- Line -->
<line x1="160" y1="20" x2="240" y2="180" stroke="#FF1493" stroke-width="8" stroke-linecap="round" />
<!-- Polygon (a triangle) -->
<polygon points="320,20 270,180 370,180" fill="#00BFFF" />
</svg>
[Live Front-End Rendering]
Congratulations, you've already mastered 80% of everyday SVG usage!
But what really makes developers lose their hair is the legendary final boss — <path>.
Chapter 3: The Final Boss <path> — Fully Decrypted
When you export a complex icon from Figma, you almost never see rect or circle — it's all <path>.<path> is the universal brush in SVG; it can draw any shape. Its core is the d attribute (short for "data").
That string of gibberish inside the d attribute is actually a series of drawing commands. Remember these rules:
- Uppercase letters: Absolute coordinates (relative to the canvas origin
0,0) - Lowercase letters: Relative coordinates (relative to the current pen position)
3.1 Move (M/m) and Line (L/l)
M x y(Move to): Lift the pen and move to coordinate(x,y)without leaving a trace.L x y(Line to): Draw a straight line from the current point to coordinate(x,y).H x/V y: Draw a horizontal line / vertical line.Z/z(Close path): Connect the current point back to the starting point, closing the shape.
Let's hand-code a "house" icon:
<svg width="200" height="200" style="background: #282c34; border-radius: 12px;">
<!--
1. M 100 30 -> Move to the peak
2. L 170 100 -> Draw line to the right eave
3. L 150 100 -> Step back to the right wall corner
4. L 150 170 -> Draw down the right wall
5. L 50 170 -> Draw left across the floor
6. L 50 100 -> Draw up the left wall
7. L 30 100 -> Extend out to the left eave
8. Z -> Close back to the peak
-->
<path d="M 100 30 L 170 100 L 150 100 L 150 170 L 50 170 L 50 100 L 30 100 Z"
fill="#E06C75" stroke="#ABB2BF" stroke-width="4" stroke-linejoin="round" />
</svg>
[Live Front-End Rendering]
Wow! This is practically sketching with code!
3.2 Bezier Curves (C/Q) and Arcs (A)
Straight lines are too rigid — we need graceful curves. This is where you need to understand Bezier curves.
C x1 y1, x2 y2, x y(Cubic Bezier): Requires two control points.Q x1 y1, x y(Quadratic Bezier): Requires just one control point.A rx ry x-axis-rotation large-arc-flag sweep-flag x y(Arc): The parameters for this one are insanely complex.
Let's use Q (Quadratic Bezier) to draw a leaf:
<svg width="200" height="200" style="background: #f0f4f8; border-radius: 12px;">
<!--
M 50 150: Start at bottom-left
Q 50 50, 150 50: Control point at top-left (50,50), end at top-right (150,50)
Q 150 150, 50 150: Control point at bottom-right (150,150), end back at start (50,150)
-->
<path d="M 50 150 Q 50 50, 150 50 Q 150 150, 50 150"
fill="#98C379" stroke="#3E4451" stroke-width="4" />
</svg>
[Live Front-End Rendering]
3.3 Hands-On: Drawing a Complete Logo
Combining paths, shapes, and transforms, let's look at a slightly more complex real-world example: drawing our site's beautiful logo!
<svg width="120" height="120" viewBox="0 0 120 120" style="background: #f0f4f8; border-radius: 12px; display: block; margin: 20px auto;">
<!-- Main connecting line (Bezier curve) -->
<path d="M 22 58 C 45 90, 65 15, 95 35" fill="none" stroke="#1e293b" stroke-width="4.5" stroke-linecap="round"></path>
<!-- Orange center module -->
<rect x="42" y="65" width="12" height="12" rx="2" fill="#f97316" stroke="#1e293b" stroke-width="3"></rect>
<!-- Blue nodes on both ends -->
<circle cx="22" cy="58" r="6" fill="#818cf8" stroke="#1e293b" stroke-width="3"></circle>
<circle cx="95" cy="35" r="6" fill="#818cf8" stroke="#1e293b" stroke-width="3"></circle>
<!-- Cursor pointer icon (grouped, transformed, and rotated) -->
<g transform="translate(68, 48) scale(2.4) rotate(-8)">
<path d="M 0,0 L 0,14 L 3.5,10.5 L 6.5,17 L 9,15.5 L 6,9 L 10.5,9 Z" fill="#2dd4bf" stroke="#1e293b" stroke-width="1.8" stroke-linejoin="round"></path>
</g>
</svg>
[Live Front-End Rendering]
Once you master Path and composition, it's like wielding magic — you can conjure anything out of thin air in the browser!
Chapter 4: SVG's Cosmic Coordinate System — viewBox Fully Illustrated
If you've ever tried copying someone else's SVG code into your own project, you might have found: Why is the graphic suddenly huge? Why is half of it cut off? Why has everything disappeared?
The culprit behind all of this is your lack of understanding of SVG's coordinate system — especially the epic viewBox attribute.
4.1 width/height vs viewBox
On the outermost <svg> tag, we usually write width and height. These represent the physical space (Viewport) that the SVG occupies on the browser page.
You can think of it as the size of your window at home.
And viewBox="min-x min-y width height" represents SVG's internal virtual coordinate universe.
You can think of it as the zoom level and field of view of the scenery you see through that window.
<!-- Physical space is 200x200, but the internal coordinate system is mapped to 0 through 100 -->
<svg width="200" height="200" viewBox="0 0 100 100" style="background: #e2e8f0; border-radius: 12px; display: block; margin: 20px auto;">
<!-- In this internal coordinate system, draw a rectangle 50 units wide and tall -->
<!-- Since the max internal coordinate is 100, this rectangle takes up half the physical window! -->
<rect x="0" y="0" width="50" height="50" fill="#3b82f6" />
</svg>
[Live Front-End Rendering]
See that? Even though we set the rect width to 50, it visually occupies 100 pixels! That's the magic of viewBox scaling. Once you master it, your icons can be truly responsive.
Chapter 5: Code Reuse Master — <g>, <defs>, and <use>
When writing HTML, we extract repeated code into components. SVG has the same code reuse mechanisms. Stop copying and pasting long strings of <path> over and over!
5.1 The <g> Group Tag
<g> stands for Group. It not only keeps your code cleaner, but more importantly, you can apply transforms (transform), colors, opacity, and other properties to the entire group at once. When we drew the logo earlier, we used <g> to uniformly apply rotation and scaling to the cursor icon.
5.2 <defs> and <use>: "Componentization" in SVG
<defs> (Definitions) is like a warehouse. Any graphics you put inside it won't be rendered directly — not until you "summon" them with <use>.
This is an absolute godsend for drawing repeating patterns (like grids, starry skies, forests)!
<svg width="300" height="150" style="background: #1e1e2f; border-radius: 12px; display: block; margin: 20px auto;">
<!-- Define a star component -->
<defs>
<g id="star">
<polygon points="10,0 13,7 20,7 15,12 17,20 10,15 3,20 5,12 0,7 7,7" fill="#FCD34D" />
</g>
</defs>
<!-- Summon stars like crazy, placing them at different positions -->
<use href="#star" x="30" y="30" transform="scale(1.5)" />
<use href="#star" x="100" y="80" transform="scale(0.8)" />
<use href="#star" x="150" y="20" transform="scale(2)" />
<use href="#star" x="220" y="60" transform="scale(1.2)" />
<use href="#star" x="260" y="100" />
</svg>
[Live Front-End Rendering]
This not only drastically reduces code volume, but also significantly optimizes rendering performance!
Chapter 6: The Art of Text — <text> and <textPath>
Did you think SVG could only draw geometric shapes? Wrong! SVG's text support is mind-blowingly powerful. The text it renders can not only be crawled by search engines and selected/copied by users, but also supports all kinds of fancy tricks.
6.1 Basic Text Rendering
<svg width="300" height="100" style="background: #f0f4f8; border-radius: 12px; display: block; margin: 20px auto;">
<!-- Note: the text's y coordinate is the baseline of the text -->
<text x="150" y="55" font-size="32" font-family="sans-serif" font-weight="bold" fill="#ec4899" text-anchor="middle">
Hello SVG Text!
</text>
</svg>
[Live Front-End Rendering]
6.2 Text on Path (TextPath)
This is a uniquely powerful SVG technique! You can make text follow any arbitrarily complex <path> for typesetting — something that's incredibly hard to achieve in CSS, but takes just two lines of code in SVG!
<svg width="300" height="150" style="background: #1e293b; border-radius: 12px; display: block; margin: 20px auto;">
<defs>
<!-- Define a curved path and give it an ID -->
<path id="curve" d="M 30 100 Q 150 20, 270 100" fill="transparent" stroke="#334155" />
</defs>
<!-- Draw the curve so you can see the path -->
<use href="#curve" />
<!-- Make text follow the curve -->
<text font-size="18" fill="#38bdf8" font-weight="bold">
<textPath href="#curve" startOffset="50%" text-anchor="middle">
Sensuous text flowing along a curve
</textPath>
</text>
</svg>
[Live Front-End Rendering]
Chapter 7: Color and Texture — Gradients and Filters
SVG with only solid-color fills has no soul. Modern web design demands texture, shadows, and gradients. All of these can be perfectly achieved in SVG.
7.1 Linear Gradient <linearGradient>
Just like components, gradients need to be defined inside <defs> tags and then applied to graphics via url(#id).
<svg width="300" height="120" style="background: #f8fafc; border-radius: 12px; display: block; margin: 20px auto;">
<defs>
<linearGradient id="cyberGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ec4899" />
<stop offset="100%" stop-color="#8b5cf6" />
</linearGradient>
</defs>
<!-- Apply the gradient to a rounded rectangle's fill attribute -->
<rect x="20" y="20" width="260" height="80" rx="40" fill="url(#cyberGradient)" />
<text x="150" y="65" font-size="24" font-weight="bold" fill="#ffffff" text-anchor="middle">
Cyberpunk Gradient
</text>
</svg>
[Live Front-End Rendering]
7.2 Advanced Glow Filter <filter>
Now we're entering the big leagues. We'll use <feGaussianBlur> and <feMerge> to create a stunning neon glow effect!
<svg width="300" height="150" style="background: #0f172a; border-radius: 12px; display: block; margin: 20px auto;">
<defs>
<!-- Define the glow filter -->
<filter id="neonGlow" x="-50%" y="-50%" width="200%" height="200%">
<!-- Apply Gaussian blur to the graphic -->
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur1" />
<feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur2" />
<!-- Merge the original graphic with the blur results -->
<feMerge>
<feMergeNode in="blur2" />
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- Draw a glowing text -->
<text x="150" y="85" font-size="36" font-weight="900" font-family="monospace" fill="#22d3ee" text-anchor="middle" filter="url(#neonGlow)">
NEON
</text>
</svg>
[Live Front-End Rendering]
Chapter 8: Bringing SVG to Life — Advanced SMIL Animation
If you think CSS animations aren't enough, SVG's built-in SMIL (Synchronized Multimedia Integration Language) will absolutely blow your mind.
8.1 Basic Property Animation
Let's look at an example: we'll draw a sun that not only rotates automatically but also changes color when you hover over it! This time we're using SVG's native <animateTransform> and <set> tags — no CSS required at all:
<svg width="200" height="200" style="background: #1e1e2f; border-radius: 12px; display: block; margin: 20px auto;">
<g>
<path d="M 100 20 L 100 180 M 20 100 L 180 100 M 45 45 L 155 155 M 45 155 L 155 45"
stroke="#FFD700" stroke-width="8" stroke-linecap="round" />
<circle cx="100" cy="100" r="40" fill="#FFD700">
<set attributeName="fill" to="#FF4500" begin="mouseover" end="mouseout" />
</circle>
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" dur="10s" repeatCount="indefinite" />
</g>
</svg>
[Live Front-End Rendering (try hovering over the center of the sun)]
Isn't that awesome?! Complex interactive states implemented entirely within SVG — no external JS libraries or CSS stylesheets needed at all.
8.2 Ultimate Flex: Stroke Dasharray Animation
If there's one SVG animation technique that's the most iconic, it's definitely "stroke animation." It creates a highly futuristic effect of "a line being drawn in real time."
The core principle comes down to two properties:
stroke-dasharray: Turns a solid line into a dashed line. If you set it extremely large — large enough to cover the entire path — it becomes one full-length solid dash followed by one full-length gap.stroke-dashoffset: Shifts the starting offset of the dashes. By dynamically changing this offset, you create the drawing animation.
<svg width="300" height="150" style="background: #000; border-radius: 12px; display: block; margin: 20px auto;">
<!-- A sensuous sine wave curve -->
<path d="M 20 75 Q 70 20, 150 75 T 280 75" fill="transparent" stroke="#00FFFF" stroke-width="6" stroke-linecap="round" stroke-dasharray="600" stroke-dashoffset="600">
<animate attributeName="stroke-dashoffset" values="600;0;600" dur="4s" repeatCount="indefinite" />
</path>
</svg>
[Live Front-End Rendering]
8.3 Path Motion Animation <animateMotion>
If you want an object to move along a specific trajectory, in the past you might have needed hundreds of lines of JS to calculate the physics. But in SVG, one line of <animateMotion> gets the job done!
<svg width="300" height="150" style="background: #f0fdf4; border-radius: 12px; display: block; margin: 20px auto;">
<!-- Draw the motion path as a reference -->
<path id="motionPath" d="M 20 75 Q 150 -50, 280 75 Q 150 200, 20 75" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="5,5" />
<!-- This dot will follow the trajectory -->
<circle r="8" fill="#10b981">
<animateMotion dur="3s" repeatCount="indefinite">
<mpath href="#motionPath" />
</animateMotion>
</circle>
</svg>
[Live Front-End Rendering]
Chapter 9: Conclusion — Mastering the Vector Magic
From a simple blank canvas to complex Bezier curves; from static color fills to stunning neon glows; from monotonous shapes to infinitely looping SMIL native animations... If you've read and practiced every piece of code in this article from start to finish, without a doubt, you've crossed beyond the fear stage of "I can't read SVG alien hieroglyphics."
You see, none of these interactive effects, drawing animations, or light-shadow filters have strayed from the most native DOM APIs and the most basic mathematical matrix operations. Ditch those third-party animation libraries that weigh dozens or hundreds of KB! By deeply understanding SVG's underlying logic, you alone can hand-code a miniature Figma right in the browser.
Go give it a try — you will be absolutely blown away by how powerful native web technologies truly are.