The Size Field And The Rendered Box Never Talk
Take a single <svg viewBox="0 0 24 24"> into the preview. The field labelled 原始尺寸, the original size panel, prints 24 × 24 px, yet the shapes drawn inside the preview frame swell far past that reading. Rewrite the same markup with its width and height written as 480: the reading follows it to 480 × 480 px, while the frame does not move at all. The two numbers travel on separate tracks: this page runs two independent size systems.
The Original Size Field Only Walks A Fallback Chain
The page is the SVG Image Preview tool, and its renderSvg splits the work into two branches. One hands the string to DOMParser only for the original size reading: it reads the width and height attributes on the root tag first, falls back to the third and fourth segments of viewBox when those are missing, writes a hard 300 when there is no viewBox either, then pushes the result through parseFloat and Math.round to assemble a phrase of the form N × M px. The other branch takes the node into the preview box, rewrites its width and height to 100% first, and then calls removeAttribute('viewBox'). No value passes between the two branches, so the reading in the panel and the box that gets drawn disagree often.
| Root tag written as | Original size reading | Actual rendered box |
|---|---|---|
| width=200 height=100 | 200 × 100 px | 600×400 |
| viewBox 0 0 24 24 only | 24 × 24 px | 600×400 |
| width=480 clashing with viewBox | 480 × 480 px | 600×400 |
| Neither size nor viewBox present | 300 × 300 px | 600×400 |
| Only style width:200px height:150px | 300 × 300 px | 200×150 |
In the first four rows it makes no difference whether the source file says 200, says 24 or says 480: once viewBox has been deleted and both size attributes forced to 100%, the bounding rect of the real node equals the preview container, and the probe container here is fixed at 600.00×400.00, where every row lands. Only the last row breaks the pattern. When width and height live in an inline style, the 200px and 150px written there override the 100% that renderSvg paints over them, and the measured box really is 200.00×150.00. The original size field is not the rendered box size at all; it is a fallback reading, and the two are different quantities sharing one label.
Figure 1: the original size reading beside the box that renders
With viewBox Removed, A Circle Of r=1 Is Always 2 Pixels
The viewBox attribute normally maps user coordinates onto the viewport. Once removeAttribute takes it away, user coordinates and CSS pixels land one onto one, and a shape is only as large as the numbers inside it. The same <circle r="1"> was pushed through five sources: one declaring 24 user units, one declaring 480, the clashing pair, one declaring nothing, and one nested inside another svg element. After renderSvg every one of them measured 2.00×2.00 in diameter. Leave viewBox untouched and render the same markup natively inside the same 600×400 box, and that r=1 circle measures 33.33×33.33 under viewBox="0 0 24 24" while under viewBox="0 0 480 480" it measures only 1.67×1.67, a gap of roughly 20 times between two files describing the same circle. Removing viewBox flattens that 20 times gap into a single repeated 2.00.
Zoom Steps By 0.2, Clamps Between 20% And 500%, And Fit Is A Reset
zoomSvg adds or subtracts 0.2 on every press and then clamps svgZoom, so the scale parks between 20% and 500%. From 1, the plus button walks through 1.2, 1.4, 1.6 until it reaches 500%, after which another press changes nothing; the minus button stops at 20%. The button labelled 适应 in that same control row, which reads as Fit, ignores the current scale in its fit branch and assigns svgZoom straight back to the neutral value: that resets the view to 100%, and it is not a fit to the window or to the frame border. The percentage reads Math.round(svgZoom*100), so the float 1.5999… shows 160% where truncation would show 159%, and 4.999… shows 500% where truncation would show 499%: the readout rounds rather than truncates.
The Indent In The SVG Source Tab Is Only A Line Break
The SVG 源码 tab, the second tab under the drawing, is the product of formatSourceCode, and its name advertises indentation. It inserts exactly one line break before each opening tag and applies a three colour highlight: no indent spaces added, no attribute reordered, no self closing tag rewritten. That one line sample of 121 characters becomes 6 lines and 129 characters at the line break stage, and once escaping and highlight markup are added its innerHTML reaches 950 characters. Only line structure and colours change; the markup itself is untouched.
A Half Megabyte SVG Meets No Guard Rail In The Code
Feed in one oversized SVG of 498635 bytes, roughly 0.47MB, with 12000 rect elements along a single line, and renderSvg finishes in 308 milliseconds, the element count is reported as 12001, and the box is still 600×400. That 12001 is not a DOM query: it comes from the regex /<\w+/g matching the shape of an opening tag across the raw string, meaning one svg element plus 12000 rect elements, closing tags and comments excluded. There is no byte ceiling and no element ceiling in the code, so a file of that bulk is never stopped, warned about, or trimmed.
Failure Paths And The Copy Underneath Them
Every failing submit returns before the preview area is ever cleared, so whatever was on screen stays there. An empty textarea raises the toast 请上传 SVG 文件或粘贴代码; a block of text with no tags at all, or an unclosed <svg width="10" height="10", yields no svg node and raises 未找到有效的 SVG 标签. A leading BOM is stripped by trim and parsing proceeds. A genuine GBK byte file was not measured end to end, so this run confirms only that readAsText is called without an encoding argument, decodes as UTF-8 by default, and still parses the ASCII tags. The inline script comparison: a <script> pushed in through innerHTML does have its node inserted, counted once, but it never executes. For <image> only two href forms were probed, a data: URI and a local relative path; the node survives, no claim is made about whether its pixels actually decode, and nothing in the run resolves toward an external host.
Against the page's own copy, the config introduction yields 6 judgements. Uploading for preview and browser only processing both match. Code highlighting, basic information and zoom viewing match only in part, because the highlight is only line breaks, the size shown is a fallback reading, and the zoom is clamped between 20% and 500%. The claim that does not survive is real time rendering: no input, paste or keyup listener in the code calls renderSvg, only the render button and the readAsText callback do, so pasting code changes nothing on screen until that button is pressed.
FAQ
Q: Why does the size in the information panel differ from the preview box?
Because they are two unrelated numbers. The original size field walks the width/height → viewBox → 300 fallback chain, while the box you are looking at has been rewritten to 100% and had its viewBox deleted, so it always equals the container. To learn how large the drawing really is, measure the preview box itself.
Q: Does the Fit button stretch the drawing across the window?
It does not. The fit branch only resets the scale to 100% no matter where it stood, and it never fits the window or hugs the frame border: nothing there is measured against the viewport at all. Zooming in adds 0.2 per press and stops climbing at 500%.
Q: The circle in the preview keeps changing size, is viewBox written wrong?
viewBox is not written wrong. The preview deletes viewBox before it injects the node, coordinates land one onto one, and a circle with r=1 stays 2 pixels wide whatever file it came from. Turning an SVG into a picture, and how external fonts or linked images behave in that pipeline, are two separate topics this article leaves open; the older notes SVG To PNG Export Sizes and External Fonts And Linked Images In SVG cover them instead.