svg-line: Better Status Bars for Emacs | Charlie Holland's Blog
Skip to main content<br>svg-line: Better Status Bars for Emacs<br>svg-line: Better Status Bars for Emacs<br>June 8, 2026
© 2026 Charlie Holland
svg-line: Better Status Bars for Emacs
svg-line: Better Status Bars for Emacs
Table of Contents
1. TLDR
2. About
3. svg-line's Features
4. Why SVG Works
5. Configuration
5.1. Mode-line
5.1.1. Simple mode-line
5.1.2. Rich mode-line
5.2. Tab-line
6. Acknowledgement
1. TLDR
Emacs provides four useful status bars (mode-line, header-line, tab-bar, and tab-line), but each imposes different, inconsistent limits on multi-line layout, alignment, icons, and interactivity. svg-line (see code on GitHub) solves this by rendering them as SVG images, and normalizes a rich feature set across all status bars with a consistent configuration. svg-line works by defining a small rendering engine built on Emacs's native SVG support. Configuring status bars is easy: you simply write one :content function and call svg-line-activate. You can see my custom configuration of mode-line, header-line, tab-line, and tab-bar in my Emacs config.
Figure 1: Every *-line in this frame is one SVG image drawn by svg-line.
2. About
Emacs gives us four status bars, the mode-line, the header-line, the tab-bar, and the tab-line (*-lines for short). These are useful for providing a dynamic 'heads-up display', for important context, like what buffer you're in, the active major mode, and really any arbitrary thing you can define.
I'm a heavy user of the *-lines in Emacs, and I have them all enabled, but the issue that has plagued me is that, natively, each one behaves differently and each has unique limitations. For example, multi-line status (necessary on my small laptop) is possible, but only in the tab-bar. Right alignment is possible in the tab-bar, but only in the last line, and this alignment feature is only available in the tab-bar. I can display icons from all-the-icons in the mode-line and header-line, but not the tab-bar or tab-line. Etc….
What I really want is consistent behaviour and configuration across all these status bars, and I want the multi-line, alignment, and icons features available in all of them. It turns out that SVG (scaled vector graphics) is the key to solving this.
Inspired by Nicolas Rougier's dual-header gist, I built svg-line, which provides this experience by utilizing Emacs's built-in SVG rendering support. At first, this approach seemed like a hack, or abuse of the *-lines, or neglect of the built-in status bar behaviour. But I kept it and created a package because I was literally shocked how well this works and how native this feels (see the screenshot and video above).
Note that even if you only use the mode-line, svg-line is still useful — likely more so, since a single status bar has to render all your indicators on its own.
3. svg-line's Features
Multi-line everywhere , with per-row left/center/right alignment.
A tab-line that wraps overflowing tabs onto new rows instead of hiding them, including with file-type glyphs, a current-tab highlight, and an unsaved tint.
Clickable anything. Any segment can carry a left-click action, a right-click menu, and hover help with a highlight. This works uniformly across all four bars, including the otherwise-uncooperative tab-bar.
Icons as text. Using Nerd Fonts and an icon is just a character that flows with everything else. SVG rendering also enables a full-height "masthead" glyph option on status bars that can span multiple lines.
Dynamic and animated indicators : a buffer-position pie, progress bars, active vs. inactive styling per window.
It respects text scale. The bars track text-scale, re-rendering crisply instead of blurring.
A meta feature is that the configuration surface is uniform across all status bars, which is a pleasant improvement over the diverse configuration strategies for the native APIs.
4. Why SVG Works
When using svg-line, each line becomes one SVG image , and SVG images are more featureful than the native text engine:
It can be any height. Multi-row bars are now possible in every *-line.
Everything is placed at exact pixel coordinates. Left, right, and center alignment work identically on every row.
It draws whatever you want. Text, yes, but also wrapped tab flows, geometric progress bars and pies, and (with a Nerd Font) icon glyphs inline with the text, the same on all four lines. Anything you can render in an SVG (just about anything) is fair game.
The engine remembers where it drew. It can detect the mouse against those placements, so clicks, right-click menus, and hover all work on any element of any line.
5. Configuration
Configuring svg-line is deliberately simple. You write a :content function that returns rows, supply it to svg-line-define, and call svg-line-activate on the defined line. This configuration pattern is identical for all four bars. The engine has two layouts: lines (the default — rows of...