svg-margin: Better Gutters for Emacs | Charlie Holland's Blog
Skip to main content<br>svg-margin: Better Gutters for Emacs<br>svg-margin: Better Gutters for Emacs<br>June 24, 2026
© 2026 Charlie Holland
svg-margin: Better Gutters for Emacs
svg-margin: Better Gutters for Emacs
Table of Contents
1. TLDR
2. About
3. svg-margin's Features
4. Configuration
4.1. A simple provider
4.2. Decoupled providers
4.3. Reclaiming the fringe
5. Why an image, not text
6. Caveat: line-wrap indicators stay in the fringe
7. Note on Inspiration
1. TLDR
Emacs can draw line-level indicators in the built-in fringe and margin, the thin gutters beside the buffer text. The fringe gives you a single monochrome mark per side, and the margin can technically hold more, but getting several independent sources to share one line cleanly is surprisingly hard to pull off in the plain text rendering that the margin uses out-of-the-box.
svg-margin (code on GitHub) fixes this by rendering indicators as SVG in the window margins, so any number of independent "providers" present text, icon glyphs, and clickable markers side by side on one line. Like my svg-line package, it overlays SVGs onto built-in UI components (the margin in this case) by leveraging Emacs's built-in SVG support. My personal config channels many sources to it, including VC, flycheck, evil marks, Org elements, whitespace indicators, and live symbol occurrences.
Figure 1: See svg-margin in action (to the left of the grey fringe). Note the lines where there are multiple indicators. On line 38, we have an evil mark (m), a symbol-overlay indicator ({}), and git-gutter. I'm also using the right margin to display a white-space indicator. The margin grows and shrinks to accommodate an arbitrary number of indicators.
2. About
I lean on the fringe and margin heavily because I'm a HUD maximalist, and scanning a buffer's gutter at a glance is almost always faster than parsing the same data out of the buffer's text.
To satisfy my greed for HUD, I yearned for a flexible gutter where any number of independent (that's a key word, remember it) indicator sources can coexist without competition on a given line, and without me having to allocate them to predetermined slots. I want an API that's like "here's a gutter, any package can push pretty indicators to it".
Emacs's fringe can't give me that because it's one monochrome bitmap per side. It's charming in its ugliness, and very useful (arguably necessary) for things like line wrap indicators. It's the Quasimodo of Emacs's UI components: rough around the edges, naive, and loyal.
Emacs's margin is the Esmeralda to the fringe's Quasimodo, and provides a much better stage for the decoupled-indicator-provider vibe I'm going for, mainly because it supports multiple indicators on a given line. But it falls ever so short of my requirements because it lacks a way to compose multiple indicators together.
The main contribution of svg-margin is exactly that missing compositor. It lets you push however many indicators you want into a given margin line, with graceful resizing (over the built-in truncation), and with position priority (for example, so that git-gutter information always renders closest to the buffer's text).
To address an anticipated question: Why use SVG when you can use a compositor like the one defined in svg-margin with the built-in margin? Basically, it works, but it's very difficult to get the built-in margin's text rendering to play nice with pretty glyphs in the multiple-indicator-per-line scenario. As optional reading, you can read more about why in the Why an image, not text section below.
3. svg-margin's Features
Multi-column packing : several indicators stack side by side on one line, in both margins; the margin grows and shrinks to fit, with no upper bound on the number of indicators per side.
Decoupled providers : a provider of indicators is a simple function of the buffer returning a list of indicators, so independent packages coexist without conflict.
Rich indicator style : built-in shapes (dot, ring, bar, box, triangle), centred text, Nerd Font icon glyphs, or a custom :draw function can all be used to render indicators in the margin.
Clickable anything : any indicator can carry a left-click action, a right-click menu, and hover help with a highlight.
No jitter on buffer switch, text-scale aware : margin widths are buffer-local and indicators resize with text-scale. This avoids jitter when switching buffers and ugly or truncated repaints, respectively.
4. Configuration
A provider is a function of the buffer that returns a list of indicator plists. As shown below, you simply define the provider, register it with svg-margin-register-provider and then enable svg-margin-mode (or global-svg-margin-mode).
4.1. A simple provider
This example puts a red dot beside every line containing the string TODO:
(svg-margin-register-provider 'todo<br>(lambda (_buffer)<br>(let (out) ;; out is shorthand for...