Using dvisvgm, you can produce beautiful SVGs, for example the diagrams in my git merge vs rebase tutorial.
Installing LaTeX is the first step. Windows users want MikTeX, and can follow the Ghostscript installation instructions on the dvisvgm FAQ.
On macOS, it’s a bit more involved. First, use MacTeX, which can be installed with homebrew. You’ll also need Ghostscript if you want things like fonts to work properly with dvisvgm.
$ brew cask install mactex
$ brew install ghostscript
dvisvgm is installed with MacTeX. In the current version (2.1.3), you also need to tell dvisvgm where to find Ghostscript. I’ve submitted a patch for it to work automatically, but that isn’t in MacTeX yet. To do this, add the following to your .bash_profile
:
export LIBGS="$(brew --prefix ghostscript)/lib/libgs.9.dylib"
Or, for Fish shell fans, put this in your ~/.config/fish/config.fish
file:
set -x LIBGS (brew --prefix ghostscript)/lib/libgs.9.dylib
Then, make sure dvisvgm finds Ghostscript. You’ll have to make sure your shell reloads the changes to .bash_profile
.
$ source ~/.bash_profile
$ dvisvgm -l | grep ps
ps dvips PostScript specials
If you don’t see any output, dvisvgm can’t find Ghostscript. But if you do, you’re ready.
Using the standalone
class, each TikZ picture is rendered on a separate page, and each page is the size of the TikZ picture. Here’s a basic example:
\documentclass[tikz,margin=5pt]{standalone}
\begin{document}
\begin{tikzpicture}
\node {Hello World};
\end{tikzpicture}
\end{document}
First, margin=5pt
sets a margin, otherwise standalone really does only set the picture size to what is required. And here’s the result, converted to PNG with a border added to emphasise the margin:
However, if you compiled this, you’ll still get a PDF out. To get an SVG, add the dvisvgm
option to the document class options. Here’s another example with that:
\documentclass[dvisvgm,tikz]{standalone}
\renewcommand{\familydefault}{\sfdefault}
\begin{document}
\begin{tikzpicture}[very thick]
\useasboundingbox (2,2) -- (-2,-2);
\node (a) at (-1,-1) {A};
\node (b) at (1,1) {B};
\path (a) edge[->] (b);
\end{tikzpicture}
\end{document}
A pitfall is that if you add the dvisvgm
option, you lose the ability to make PDF files properly. This isn’t a huge issue, LaTeX packages usually provide a DVI viewer. But if you want PDF files while you’re making the graphics, you can omit the dvisvgm
option, and then add it in when you’re ready to make the SVG file. (Of course, if you forget dvisvgm
in the options, the output won’t work well with dvisvgm.)
I’ve also used this to demonstrate how to set the font to sans-serif (\renewcommand{\familydefault}{\sfdefault}
), and how to use \useasboundingbox
to set the output page size instead of margin
. To create the SVG file, first have LaTeX make a DVI file, and then convert it to SVG with dvisvgm:
$ latex example.tex
$ dvisvgm \
--clipjoin \
--bbox=papersize \
--page=1- \
example.dvi
The dvisvgm options are important. --clipjoin
prevents clipping issues. --bbox=papersize
instructs dvisvgm to use the papersize information in the DVI file. Some other options for --box
, dvi
and preview
do not work reliably when I tried them, especially if your TikZ coordinates can be negative (easy to do). Finally, and this is awesome, since you can have multiple TikZ pictures in one TeX file, --page=1-
tells dvisvgm to process all pages, and output them to separate SVG files. Nice.
And this is the resulting SVG:
I have performed one extra operation on the file. SVGO optimised SVG files by stripping out unnecessary rubbish and greatly reduces the filesize of SVG files. The only downside is you’ll need npm
installed. (I hate NPM and Javascript, but SVGO is really the best thing out there to optimise SVG files.)
$ brew install npm
$ npm install -g svgo
SVGO has loads of options, too many to specify on the CLI. You can download the config.yml
file I use, or use this SVGO GUI to try them out yourself.
$ svgo --config=config.yml example.svg
And that’s it!