A set of tools to compute and to use a SVG bounding box you can trust (as opposed to the unreliable .getBBox() scourge)
npm install svg-bboxFinally, bounding boxes you can trust.
---
- The Problem with .getBBox()
- Visual Comparison: Oval Badge with Dashed Stroke
- Installation
- Platform Compatibility
- Browser Configuration
- What This Package Provides
- 1. Core Library: SvgVisualBBox.js
- 2. CLI Tools
- Quickstart
- Browser (CDN)
- Node.js / npm
- More Usage Examples
- Library API Reference
- Tools CLI Commands Usage
- Renaming Workflow with the HTML Viewer
- Troubleshooting
- Contributing
- License
---
.getBBox()The native SVG .getBBox() method is fundamentally broken:
| Feature | .getBBox() | SvgVisualBBox |
| --------------------------------------- | ------------ | ----------------------------- |
| Filters (blur, shadows, glows) | :x: Ignored | :white_check_mark: Measured |
| Stroke width | :x: Ignored | :white_check_mark: Included |
| Complex text (ligatures, RTL, textPath) | :x: Wrong | :white_check_mark: Accurate |
| , masks, clipping paths | :x: Fails | :white_check_mark: Works |
| Transformed elements | :x: Garbage | :white_check_mark: Correct |
| Cross-browser consistency | :x: Varies | :white_check_mark: Consistent |
Our approach: Measure what the browser actually paints, pixel by pixel. No
geometry guesswork, no lies.
Here's what happens when extracting an SVG element using three different bbox
methods:
| |
|
|
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| Inkscape BBox | Chrome .getBBox() | SvgVisualBBox |
| 
| 
| 
|
| ❌ WRONG | ❌ WRONG | ✅ CORRECT |
| _(svg file here)_ | _(svg file here)_ | _(svg file here)_ |
| Width: 554px
Height: 379px
_Undersized by ~48%_ | Width: 999px
Height: 301px
_Missing ~78px of stroke_ | Width: 1077px
Height: 379px
_Includes full visual bounds_ |
Source: test_oval_badge.svg
Generate this comparison yourself:
examples/bbox-comparison.js - Runnode examples/bbox-comparison.js assets/test_oval_badge.svg oval_badge to
create your own comparison with timestamped output directory.
Why the differences?
- Inkscape: Truncates half the image!
- .getBBox(): Ignores stroke width - bbox is wrong!
- SvgVisualBBox: Perfect!
---
You can run any svg-bbox tool directly without installing:
``bashSee all available commands
npx svg-bbox
$3
`bash
bun (recommended - fastest)
bun add -g svg-bboxnpm
npm install -g svg-bboxpnpm
pnpm add -g svg-bboxyarn
yarn global add svg-bboxAfter global install, run commands directly:
svg-bbox # Show all available commands
sbb-getbbox file.svg # Compute bounding box
sbb-svg2png file.svg output.png
`$3
`bash
bun (recommended - fastest)
bun add svg-bboxnpm
npm install svg-bboxpnpm
pnpm add svg-bboxyarn
yarn add svg-bboxThen use via bunx/npx or package.json scripts:
bunx sbb-getbbox file.svg
npx sbb-getbbox file.svg
`$3
For direct browser usage, use the minified UMD build from a CDN:
`html
`File sizes:
- Original: ~90 KB
- Minified (CDN): ~25 KB _(72% reduction)_
$3
`bash
git clone https://github.com/Emasoft/SVG-BBOX.git
cd SVG-BBOX
bun installRun tools directly from source
node sbb-getbbox.cjs myfile.svg
`> Note: In the documentation below, you'll see two command styles:
>
> -
bunx sbb-getbbox or npx sbb-getbbox - Use this when installed via
> package manager (recommended)
> - node sbb-getbbox.cjs - Use this when running from cloned source
>
> Both are equivalent. The bunx/npx style works after bun add svg-bbox or
> npm install svg-bbox.After installation, the following CLI commands are available:
Main Entry Point:
-
svg-bbox - Start here! Shows help and lists all available commandsCore Tools (Recommended):
-
sbb-getbbox - Compute visual bounding boxes
- sbb-chrome-getbbox - Get bbox using Chrome's native .getBBox() (for
comparison)
- sbb-chrome-extract - Extract using Chrome's native .getBBox() (for
comparison)
- sbb-extract - List, extract, and export SVG objects
- sbb-fix-viewbox - Fix missing viewBox/dimensions
- sbb-svg2png - Render SVG to PNG
- sbb-compare - Compare images visually (SVG/PNG, pixel-by-pixel)
- sbb-test - Test library functionsInkscape Integration Tools ⚠️ _(For comparison only - see warnings below)_:
-
sbb-inkscape-text2path - Convert text to paths using Inkscape
- sbb-inkscape-extract - Extract objects by ID using Inkscape
- sbb-inkscape-svg2png - SVG to PNG export using Inkscape> ⚠️ Accuracy Warning: Inkscape tools have known issues with font bounding
> boxes. Use core tools for production. Inkscape tools are for comparison
> purposes only.
$3
`bash
git clone https://github.com/Emasoft/SVG-BBOX.git
cd SVG-BBOX
bun install
`$3
> IMPORTANT: You need Node.js ≥ 24 and Chrome or Chromium installed.
>
> ⚠️ ONLY Chrome/Chromium are supported — other browsers have poor SVG
> support. This library uses headless Chrome via Puppeteer for measurements, and
> visual verification must use the same browser engine to match results.
After installing, Puppeteer will automatically download a compatible Chromium
browser. Alternatively, you can use your system Chrome by setting the
PUPPETEER_EXECUTABLE_PATH environment variable.---
Platform Compatibility
✅ Fully cross-platform compatible:
- Windows 10/11 - All CLI tools work natively (PowerShell, CMD, Git Bash)
- macOS - All versions supported (Intel and Apple Silicon)
- Linux - All major distributions (Ubuntu, Debian, Fedora, etc.)
Key features:
- All file paths use Node.js
path module (no hardcoded / or \ separators)
- Platform-specific commands handled automatically (Chrome detection, file
opening)
- Works with file paths containing spaces on all platforms
- Pure Node.js CLI tools (no bash scripts required)Platform-specific notes:
Windows
- Chrome/Chromium auto-detection works with default install locations
- File paths with spaces are properly handled
- Use PowerShell or CMD (no WSL required)
- Git Bash also supported
`powershell
PowerShell example
sbb-getbbox "C:\My Files\drawing.svg"
`
macOS
- Detects Chrome in
/Applications/
- Uses native open command for file viewing
- Works on both Intel and Apple Silicon Macs`bash
macOS example
chmod +x node_modules/.bin/sbb-* # Make executable (first time only)
sbb-getbbox ~/Documents/drawing.svg
`
Linux
- Auto-detects
google-chrome, chromium, chromium-browser
- All standard Linux file paths supported`bash
Linux example
chmod +x node_modules/.bin/sbb-* # Make executable (first time only)
sbb-getbbox /home/user/drawings/test.svg
`---
Browser Configuration
svg-bbox uses Chrome/Chromium for accurate SVG measurements via Puppeteer. By
default, it automatically detects and uses an available browser.
$3
| Variable | Purpose | Example |
| -------------------------------- | ---------------------------------------- | ------------------- |
|
SVG_BBOX_SKIP_BROWSER_DOWNLOAD | Disable automatic Chrome download | 1 or true |
| SVG_BBOX_BROWSER_PATH | Use a specific browser executable | /path/to/chrome |
| PUPPETEER_EXECUTABLE_PATH | Puppeteer's native browser path override | /path/to/chromium |$3
svg-bbox searches for browsers in this priority order:
1. User-specified path (
SVG_BBOX_BROWSER_PATH or
PUPPETEER_EXECUTABLE_PATH)
2. Puppeteer's bundled Chrome (most reliable, auto-downloaded on first use)
3. System Chrome (installed via package manager or download)
4. System Chromium (common on Linux distros like Debian/Ubuntu)If no browser is found and auto-download is enabled, Puppeteer's Chrome is
downloaded automatically.
$3
To prevent automatic browser downloads (useful for CI/CD, air-gapped systems, or
when you prefer system browsers):
`bash
Disable auto-download
export SVG_BBOX_SKIP_BROWSER_DOWNLOAD=1Then install a browser manually (see below)
`$3
macOS
`bash
Via Homebrew
brew install --cask google-chrome
or
brew install --cask chromiumSpecify custom path (if needed)
export SVG_BBOX_BROWSER_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
`
Linux (Debian/Ubuntu)
`bash
Chrome
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
sudo apt update && sudo apt install google-chrome-stableOr Chromium (often pre-installed)
sudo apt install chromium-browserSpecify custom path (if needed)
export SVG_BBOX_BROWSER_PATH="/usr/bin/google-chrome"
`
Linux (Fedora/RHEL)
`bash
Chrome
sudo dnf install google-chrome-stableOr Chromium
sudo dnf install chromiumSpecify custom path (if needed)
export SVG_BBOX_BROWSER_PATH="/usr/bin/google-chrome"
`
Linux (Arch)
`bash
Chrome (AUR)
yay -S google-chromeOr Chromium
sudo pacman -S chromiumSpecify custom path (if needed)
export SVG_BBOX_BROWSER_PATH="/usr/bin/chromium"
`
Windows
`powershell
Via Chocolatey
choco install googlechrome
or
choco install chromiumVia winget
winget install Google.ChromeSpecify custom path (if needed)
$env:SVG_BBOX_BROWSER_PATH = "C:\Program Files\Google\Chrome\Application\chrome.exe"
`Or download directly from https://www.google.com/chrome/
FreeBSD/OpenBSD
`bash
FreeBSD
pkg install chromiumOpenBSD
pkg_add chromiumSpecify custom path
export SVG_BBOX_BROWSER_PATH="/usr/local/bin/chromium"
`$3
If you prefer Puppeteer's bundled browser (recommended for consistency):
`bash
Download Chrome for Puppeteer
bunx puppeteer browsers install chrome
or with npx:
npx puppeteer browsers install chromeThis installs to ~/.cache/puppeteer/ and is auto-detected
`$3
`bash
Check which browser svg-bbox will use
node -e "console.log(require('svg-bbox/lib/ensure-browser.cjs').getBrowserStatus())"
`Output example:
`json
{
"installed": true,
"path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"source": "system-chrome",
"downloadDisabled": false
}
`---
What This Package Provides
$3
JavaScript library for accurate visual bounding box computation. Works in
browsers and Node.js (via Puppeteer).
Available Functions:
-
getSvgElementVisualBBoxTwoPassAggressive(target, options) - Compute accurate
visual bbox for any element
- getSvgElementsUnionVisualBBox(targets[], options) - Union bbox for multiple
elements
- getSvgElementVisibleAndFullBBoxes(target, options) - Get both clipped
(viewBox-respecting) and unclipped bounds
- showTrueBBoxBorder(target, options) - Visual debugging overlay
- waitForDocumentFonts(document, timeoutMs) - Wait for fonts before measuringCapabilities:
- Font-aware: Arabic, CJK, ligatures, RTL, textPath, custom fonts
- Filter-safe: Blur, shadows, masks, clipping
- Stroke-aware: Width, caps, joins, markers, patterns
$3
| Tool |
Source | Description | Example Usage |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------- |
| Core Tools (Our Visual BBox Algorithm) | | | |
| sbb-getbbox | | Get bbox info using our pixel-accurate visual algorithm | sbb-getbbox drawing.svg |
| sbb-extract | | List/rename/extract/export SVG objects with visual catalog | sbb-extract sprites.svg --list |
| sbb-svg2png | | Render SVG to PNG with accurate bbox | sbb-svg2png input.svg output.png |
| sbb-fix-viewbox | | Repair missing/broken viewBox using visual bbox | sbb-fix-viewbox broken.svg fixed.svg |
| sbb-compare | | Visual diff between images (SVG/PNG pixel comparison) | sbb-compare a.svg b.png --out-diff diff.png |
| sbb-test | | Test bbox accuracy across methods | sbb-test sample.svg |
| Chrome Comparison Tools (Chrome's .getBBox()) | | | |
| sbb-chrome-getbbox | | Get bbox info using Chrome's .getBBox() | sbb-chrome-getbbox drawing.svg |
| sbb-chrome-extract | | Extract using Chrome's .getBBox() | sbb-chrome-extract file.svg --id obj1 --output out.svg |
| Inkscape Comparison Tools (Inkscape CLI) | | | |
| sbb-inkscape-getbbox | | Get bbox info using Inkscape's query commands | sbb-inkscape-getbbox drawing.svg |
| sbb-inkscape-extract | | Extract by ID using Inkscape | sbb-inkscape-extract file.svg --id obj1 |
| sbb-inkscape-text2path | | Convert text to paths using Inkscape | sbb-inkscape-text2path input.svg output.svg |
| sbb-inkscape-svg2png | | SVG to PNG export using Inkscape | sbb-inkscape-svg2png input.svg output.png |Naming Convention:
-
sbb-[function] = Our reliable visual bbox algorithm
- sbb-chrome-[function] = Chrome's .getBBox() method (for comparison)
- sbb-inkscape-[function] = Inkscape tools (for comparison)Run
npx svg-bbox or any tool with --help for detailed usage.> Note: The
lib/cli-utils.cjs file is a library module, not a CLI
> launcher. Do not run it directly. Use the tools listed above instead.---
🚀 Quickstart
$3
`bash
npx svg-bbox
`This displays help with all available tools and usage examples.
---
$3
`bash
npx sbb-svg2png input.svg output.png --mode full --scale 4
`- Detects the full drawing extents.
- Sets an appropriate
viewBox.
- Renders to PNG at 4 px per SVG unit.---
$3
`bash
npx sbb-fix-viewbox broken.svg fixed/broken.fixed.svg
`- Computes the full visual drawing box.
- Writes a new SVG with:
-
viewBox="x y width height"
- Consistent width / height.---
$3
`bash
npx sbb-extract sprites.svg --list --assign-ids --out-fixed sprites.ids.svg
`This produces:
-
sprites.objects.html — a visual catalog.
- sprites.ids.svg — a version where all objects have IDs like
auto_id_path_3.Open
sprites.objects.html in a browser to see previews and define new ID
names.---
$3
`bash
npx sbb-extract sprites.renamed.svg \
--extract icon_save icon_save.svg \
--margin 5
`This creates
icon_save.svg sized exactly to the visual bounds of
#icon_save (with 5 units of padding).---
$3
`bash
npx sbb-extract sprites.renamed.svg \
--export-all exported \
--export-groups \
--margin 2
`Each object / group becomes its own SVG, with:
- Correct viewBox
- Includes
for filters, patterns, markers
- Ancestor transforms preserved---
$3
#### Installation
`html
`This library can be used in two ways:
1. Node.js/CLI Tools - Injected by Puppeteer in headless Chrome (used by all
CLI tools)
2. Browser/Web Applications - Loaded directly in webpages via
#### Advanced Example with the showTrueBBoxBorder() function
`html
`$3
`bash
bun add svg-bbox # recommended - fastest
npm install svg-bbox
``javascript
// Use with Puppeteer for server-side SVG processing
const puppeteer = require('puppeteer');const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(
${svgContent});
await page.addScriptTag({ path: 'node_modules/svg-bbox/SvgVisualBBox.js' });const bbox = await page.evaluate(async () => {
return await SvgVisualBBox.getSvgElementVisualBBoxTwoPassAggressive('svg');
});
`$3
The library exposes all functions through the
SvgVisualBBox namespace.####
waitForDocumentFonts(document, timeoutMs)Waits for fonts to be ready (or a timeout) before measuring text.
`js
await SvgVisualBBox.waitForDocumentFonts(document, 8000);
`####
getSvgElementVisualBBoxTwoPassAggressive(element, options)Compute a visual bounding box for an element (including stroke, filters,
etc.):
`js
const bbox = await SvgVisualBBox.getSvgElementVisualBBoxTwoPassAggressive(
element,
{
mode: 'unclipped', // ignore viewBox clipping when measuring
coarseFactor: 3, // coarse sampling
fineFactor: 24, // fine sampling
useLayoutScale: true // scale based on layout size
}
);// bbox: { x, y, width, height } in SVG user units
`####
getSvgElementVisibleAndFullBBoxes(svgElement, options)Compute both:
- visible – what’s inside the current viewBox.
- full – the entire drawing, ignoring viewBox clipping.
Used by the fixer and renderer to choose between "full drawing" and "visible
area inside the viewBox".
####
showTrueBBoxBorder(target, options) ⭐ NEWVisual debug helper - Displays a dotted border overlay around any SVG
element's true visual bounding box.
`js
// Show border with auto-detected theme
const result = await SvgVisualBBox.showTrueBBoxBorder('#myText');// Force dark theme for light backgrounds
const result = await SvgVisualBBox.showTrueBBoxBorder('#myPath', {
theme: 'dark'
});
// Custom styling
const result = await SvgVisualBBox.showTrueBBoxBorder('#myElement', {
borderColor: 'red',
borderWidth: '3px',
padding: 10
});
// Remove border
result.remove();
`Features of showTrueBBoxBorder():
- ✅ Auto-detects system dark/light theme
- ✅ Force theme with
theme: 'light' or 'dark' option
- ✅ Works with all SVG types (inline,