SVG from Zero to Senior · Part 1 — Foundations & the viewBox
Start SVG the right way: what SVG really is, the coordinate system, the basic shapes, and the one concept that confuses everyone — viewBox. With a live pan/zoom playground you can drag.
Welcome, young padawan. {Chào mừng, đồ đệ.} For the next ten parts the old master will take you from “I copy-paste SVG icons and pray” to “I can build, animate, and ship vector graphics like a senior.” {Trong mười phần tới, sư phụ già sẽ đưa con từ “tôi copy-paste icon SVG rồi cầu nguyện” lên “tôi dựng, animate, và ship đồ hoạ vector như một senior.”}
Here is the first truth: SVG is not an image format, it is a drawing language. {Sự thật đầu tiên: SVG không phải định dạng ảnh, nó là một ngôn ngữ vẽ.} A PNG is a grid of fixed pixels; an SVG is a set of instructions (“draw a circle here, this big”) that the browser re-draws at any size, perfectly sharp. {PNG là lưới pixel cố định; SVG là tập chỉ dẫn (“vẽ hình tròn ở đây, to cỡ này”) mà trình duyệt vẽ lại ở mọi kích thước, sắc nét tuyệt đối.} That is why your logo looks crisp on a 4K monitor and a smartwatch from the same file. {Vì thế logo của con sắc nét cả trên màn 4K lẫn smartwatch từ cùng một file.}
Play with the demo first — drag the viewBox sliders, feel how the window moves over the drawing, then read why. {Nghịch demo trước — kéo slider viewBox, cảm nhận cửa sổ di chuyển trên bản vẽ, rồi mới đọc lý do.}
Open the full demo {Mở demo đầy đủ}: /tools/svg-shapes-demo/.
The skeleton of every SVG {Bộ xương của mọi SVG}
You can write SVG straight into HTML — no <img> needed. {Con có thể viết SVG thẳng vào HTML — không cần <img>.} This is inline SVG, and it is what unlocks styling and scripting later. {Đây là inline SVG, và nó mở khoá việc style và scripting sau này.}
<svg viewBox="0 0 100 100" width="200" height="200">
<circle cx="50" cy="50" r="40" fill="#c8ff00" />
</svg>
Read it like a sentence: {Đọc nó như một câu:} “In a coordinate space 100×100, draw a circle centred at (50,50) with radius 40, painted lime, and display it 200×200 pixels on the page.” {“Trong không gian toạ độ 100×100, vẽ hình tròn tâm (50,50) bán kính 40, tô màu lime, và hiển thị 200×200 pixel trên trang.”}
The coordinate system — graph paper, but Y points down {Hệ toạ độ — giấy kẻ ô, nhưng Y hướng xuống}
The single most important picture to burn into your mind: {Bức tranh quan trọng nhất phải khắc vào đầu:}
(0,0) ───────────► +X
│
│ • (50,30)
│
▼
+Y
- The origin
(0,0)is the top-left, not the centre. {Gốc(0,0)ở góc trên-trái, không phải tâm.} - X grows to the right — same as maths. {X tăng sang phải — giống toán.}
- Y grows downward — the opposite of school maths, the same as every screen. {Y tăng xuống dưới — ngược với toán phổ thông, giống mọi màn hình.}
Every cx, cy, x, y you ever write lives in this space. {Mọi cx, cy, x, y con từng viết đều sống trong không gian này.}
viewBox — the idea that confuses everyone {viewBox — khái niệm làm ai cũng rối}
Beginners think width/height and viewBox are the same. They are not, and understanding the difference is the whole point of Part 1. {Người mới tưởng width/height và viewBox giống nhau. Không phải, và hiểu khác biệt này chính là trọng tâm Phần 1.}
width/height(or CSS) = how big the SVG box is on the page, in real pixels. {= cái khung SVG to cỡ nào trên trang, tính bằng pixel thật.}viewBox="min-x min-y width height"= which slice of the infinite drawing surface you crop out, in user units. {= con cắt ra lát nào của mặt vẽ vô hạn, tính bằng user unit.}
The browser then stretches that cropped slice to fill the box. {Trình duyệt rồi kéo lát cắt đó cho đầy cái khung.} So viewBox gives you free pan and zoom: {Nên viewBox cho con pan và zoom miễn phí:}
<!-- Same drawing, two windows over it -->
<svg viewBox="0 0 200 200">...</svg> <!-- full scene -->
<svg viewBox="50 50 100 100">...</svg> <!-- zoomed into the middle -->
The mental model: viewBox is a camera frame floating over your graph paper. {Mô hình tư duy: viewBox là khung máy ảnh lơ lửng trên giấy kẻ ô.} Move min-x/min-y → the camera pans. Shrink width/height → fewer units fill the same pixels → zoom in. {Dịch min-x/min-y → máy ảnh lia. Thu nhỏ width/height → ít unit lấp đầy cùng số pixel → zoom vào.} The demo’s “world view” draws that camera frame as a dashed rectangle so you can see it. {“World view” trong demo vẽ khung máy ảnh đó thành hình chữ nhật nét đứt để con thấy được.}
Senior habit: set
viewBoxand let CSS control the rendered size. Drop hard-codedwidth/heightand the SVG becomes fluid. {Thói quen senior: đặtviewBoxrồi để CSS điều khiển kích thước hiển thị. Bỏwidth/heightcứng và SVG trở nên co giãn.}
preserveAspectRatio — what if the box and the viewBox disagree? {preserveAspectRatio — nếu khung và viewBox lệch tỉ lệ?}
If your box is 300×100 but your viewBox is square, something has to give. {Nếu khung 300×100 nhưng viewBox vuông, phải có cái gì nhường.} By default preserveAspectRatio="xMidYMid meet" keeps the aspect ratio and centres the drawing (letterboxing). {Mặc định xMidYMid meet giữ tỉ lệ và canh giữa (viền đen kiểu letterbox).} Use slice to fill-and-crop instead, or none to stretch (rarely what you want). {Dùng slice để lấp-đầy-rồi-cắt, hoặc none để kéo méo (hiếm khi con muốn).}
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice">…</svg>
The basic shapes — your vocabulary {Các hình cơ bản — vốn từ của con}
Before paths (Part 2), six primitives cover a surprising amount: {Trước khi tới path (Phần 2), sáu primitive đã làm được nhiều bất ngờ:}
<rect x="10" y="10" width="80" height="50" rx="6" /> <!-- rounded box -->
<circle cx="50" cy="50" r="40" /> <!-- center + radius -->
<ellipse cx="50" cy="50" rx="40" ry="25" /> <!-- two radii -->
<line x1="0" y1="0" x2="100" y2="100" /> <!-- a segment -->
<polyline points="0,40 20,10 40,40 60,10" /> <!-- open path of points -->
<polygon points="50,5 90,90 10,90" /> <!-- auto-closed shape -->
The one gotcha: a <line> or <polyline> is invisible without a stroke — it has no area to fill. {Một cái bẫy: <line> hay <polyline> vô hình nếu không có stroke — nó không có diện tích để fill.} And <polygon> silently closes itself back to the first point, while <polyline> stays open. {Và <polygon> tự lặng lẽ đóng về điểm đầu, còn <polyline> thì để hở.} Toggle them in the demo and compare. {Bật/tắt chúng trong demo và so sánh.}
The master’s warnings {Lời cảnh báo của sư phụ}
- Y points down. Half of all “my shape is in the wrong place” bugs are forgetting this. {Y hướng xuống. Phân nửa lỗi “hình của tôi sai chỗ” là quên điều này.}
viewBoxis unitless. Never writeviewBox="0 0 200px 200px"— numbers only. {viewBoxkhông có đơn vị. Đừng viết200px— chỉ con số.}- No
fillon a line. Lines and open polylines needstroke, notfill. {Khôngfillcho line. Line và polyline hở cầnstroke, không phảifill.}
Practice, or it didn’t happen {Luyện tập, không thì coi như chưa học}
- Draw your initials {Vẽ chữ cái đầu tên con} using only
<line>and<polyline>in aviewBox="0 0 100 100". {chỉ bằng<line>và<polyline>.} - Build a target {Dựng tấm bia}: three concentric
<circle>s. Then change only theviewBoxwidth/heightand watch it zoom without touching any circle. {ba<circle>đồng tâm. Rồi đổi chỉwidth/heightcủaviewBoxvà xem nó zoom mà không động vào circle nào.} - Break it on purpose {Phá nó có chủ đích}: set
preserveAspectRatio="none"on a square drawing inside a wide box and watch it distort. {đặtnonecho bản vẽ vuông trong khung rộng và xem nó méo.}
What’s next {Phần tiếp theo}
You can now place a camera over an infinite canvas and draw with six shapes. {Giờ con đã biết đặt máy ảnh trên canvas vô hạn và vẽ bằng sáu hình.} But real icons, logos, and charts are made of curves — and curves mean one element: <path>. {Nhưng icon, logo, biểu đồ thật được làm từ đường cong — và đường cong nghĩa là một element: <path>.} In Part 2 we decode the path language — M, L, the Bézier curves C/Q, and the dreaded elliptical arc A — with a builder that lets you drag control points and watch the d attribute write itself. {Ở Phần 2 ta giải mã ngôn ngữ path — M, L, các đường Bézier C/Q, và cung elip A đáng sợ — với một trình dựng cho con kéo control point và xem thuộc tính d tự viết.}