5

I'd like man to use a sans-serif font, which is easier to read on a screen not paper. man uses a monospace terminal, which is slowest to read for prose. man -Tpdf uses the "Times-Roman" font, which is serif. I'd like the PDF to use Noto Sans, but if only PostScript Level 1 is supported, I'll accept Helvetica and its Linux metric-compatible replacements. The text should be reflowed if applicable, instead of blindly replacing the font name in the PDF leaving large gaps. Monospace should be retained. My current serif-outputting command is man --nh -Tpdf "$1" > "$1".pdf && okular "$1".pdf && unlink "$1".pdf .

-Thtml outputs a webpage omitting font-family, which goes well with my Firefox configuration for Noto Sans. But it's \raggedright and tables are blurry in HiDPI and illegible with Dark Reader. khelpcenter has no dark mode or support for multiple windows, and printing breaks HiDPI and selectability. yelp man:man is monospace. The solution can use intermediate formats before PDF, but shouldn't ahead-of-time compile as gcloud/Perl put 7000+ files in man3 that I sometimes read, but I want the solution ≤1 MB and ≤3 startup seconds.

I tried to set MANROFFOPT='-f H', but it did not change the font. Perhaps I mistyped it but it didn't raise any error. Seemingly when -Tpdf is the first argument, it's ignored, even though it responds with a nroff error without it. Then I tried zcat /usr/share/man/man1/man.1.gz | tbl | groff -fH -man > manpage.pdf , but only the per-page header and footer are sans-serif and the text is both serif and unselectable.

2
  • Does this strictly need to use your local manpages as the input? Commented yesterday
  • @grawity Most likely, given: 1. I want it to autodetect whether my queried command is in /usr/bin or ~/.nvm/versions/node/v25.6.0/bin. 2. I have MANPATH=~/opt/my_redirector_to_current_node/share/man 3. I'm usually on the latest non-devel Ubuntu (25.10), and I run ncu -g frequently, so you can try to find a web-based solution, but I think it'd be harder Commented yesterday

2 Answers 2

8

Arch Linux publishes HTML versions of manual pages from all its packages using mandoc as the renderer, which is an alternative implementation of the man command which doesn't use groff (and AFAIK is the default on OpenBSD and probably some other BSDs).

Among other differences, it renders tables as actual HTML <table> rather than as images.

The usage is man -Thtml ..., the same as with man-db (although depending on your distribution it might either fully replace man-db or install side-by-side).

man -Thtml bash > bash.html

mandoc -Thtml /usr/share/man/man1/man.1.gz > man.html

Example output of the project's own manual:

Example with Arch's stylesheet applied:

Some manpages use the BSD 'mdoc' macros, and therefore htmlize somewhat differently than the more common 'man' markup. AFAIK the latter is more expressive but not sufficiently "semantic" in a way that would allow for clean translation to HTML or other non-paper-like formats.

In some cases the manpage is already generated from XML (Docbook), POD, or some other markup source. With such manuals you'd likely get a better result from converting the original directly to HTML – for example, Perl manual pages are generated from Pod markup which can be (and indeed the original might even contain inline HTML for that purpose):

pod2html "$(perldoc -l Pod::Checker)"
10
  • Can you provide the mandoc command used to generate those webpages? The mandoc -l mandoc.1 man.1 apropos.1 makewhatis.8 example fails with mandoc: mandoc.1: BADARG: bad command line argument: No such file or directory [...] Commented yesterday
  • That sounds like a local issue. The same command works on my system (as long as I'm in a directory where the mandoc.1 or mandoc.1.gz file actually exists, of course, e.g. after I've cd'd to /usr/share/man/man1). The mandoc command expects to be given actual file paths, and won't look in your MANPATH – if that's what you're expecting, use the man command that mandoc also includes (which as I said has the exact same usage as man-db/groff's man). Commented yesterday
  • 1
    Found a way: <s>mandoc -Thtml "$(man -w "$1" | head -n1)" > manpage.html && firefox ./manpage.html # Then optionally print</s> Wow, mandoc unlike man-Tpdf can even handle the tables in set -- systemd.unit properly. Edit: The first part simplifies to mman -Thtml "$1", and mandoc's version's named mman not man on at least my distro. The systemd one is just an example with tables. I know about systemd's online docs, but I have yet to find the package for their HTML offline docs Commented yesterday
  • Yeah, the command naming depends on whether the package is designed to replace man-db or install side-by-side. On Arch it completely replaces man-db so it has the same man command instead. Commented yesterday
  • For completeness, I needed to use a Stylus regex-URL userscript *{text-align: justify}.Bd-indent{margin-left:4em} to avoid \raggedright and get certain indents to show up. The bullets inside ConditionFirmware= lack spaces after and indents on the next line on mman -Thtml unlike a simple mman. But mman -Thtml Pod::Checker displays proper lists, so it's probably a systemd quirk Commented yesterday
1

I tried to set MANROFFOPT='-f H', but it did not change the font.

If you're using man-db man(1), you need to tell it to use troff(1) instead of nroff(1) to format the document. nroff is for terminal devices, and terminal devices can't change the font family. (In groff, nroff is a shell script that wraps troff, selecting a terminal device for output, configuring "nroff mode".)

Perhaps I mistyped it but it didn't raise any error.

To avoid producing a lot of spurious diagnostics, when GNU troff is in "nroff mode", it silently ignores operations that are meaningful only on typesetters, like requests to change the font family or the type size. That's so that authors of *roff documents don't have to write a bunch of .if t and .if n conditionals and similar.

Seemingly when -Tpdf is the first argument, it's ignored, even though it responds with a nroff error without it.

The man(1) page on my system says that its -T option, as in -Tpdf, implies -t.

zcat /usr/share/man/man1/man.1.gz | tbl | groff -fH -man > manpage.pdf ,

Without a -T argument, groff uses its default output device, which is "ps" (PostScript), not "pdf". Some PDF viewers can fall back in a limited way to PostScript rendering.

This works for me (EDIT: with groff 1.22.4, 1.24.0, and 1.24.1, but not 1.23.0), producing Helvetica throughout the page:

zcat /usr/share/man/man1/man.1.gz | groff -t -f H -m an -T pdf > manpage.pdf

(EDIT 2: See below for a workaround for the groff 1.23.0 bug.)

(I used groff's -t option instead of manually crafting a pipeline with tbl; groff has supported this for about 35 years.)

I get the same result with this:

MANROFFOPT='-f H' man -Tpdf man >| manpage2.pdf

$ cksum manpage*
3476235134 33349 manpage.pdf
2185569191 33349 manpage2.pdf

The files appear to differ only in an embedded date stamp recording the time of their production.

but only the per-page header and footer are sans-serif and the text is both serif and unselectable.

That's a byproduct of your PDF reader's fall-back-to-PostScript rendering, I would guess.

For groff 1.23.0 users, here's a patch you can apply to your /etc/groff/man.local file to work around Savannah #64130.

--- /groff-1.23.0/share/groff/site-tmac/man.local~      2026-03-31 04:10:05.977077627 -0500
+++ /groff-1.23.0/share/groff/site-tmac/man.local       2026-03-31 04:10:43.388942750 -0500
@@ -7,6 +7,10 @@
 .if !'\*[.T]'html' \
 .  if !r U \
 .    nr U 0
+.
+.am TH
+.ds an*body-family \n[.fam]
+..
 .\"
 .\" "CW" is not a portable font name, but some man pages use it anyway.
 .\" Uncomment this to suppress warnings produced by such pages.  This
4
  • zcat /usr/share/man/man1/man.1.gz | groff -t -f H -m an -T pdf > manpage.pdf does not work for me. I get the same header/footer-OK, body-not-OK problem. The text "an interface to the system reference manuals" appears in Times (serif) font. If it's hard to see visual, then run pdffonts ./manpage.pdf and observe that "Times-{Bold,Italic,Roman}" are still present Commented yesterday
  • 1
    It sounds like you've encountered savannah.gnu.org/bugs/?64130 . I've updated my answer. Try groff 1.22.4, 1.24.0, or 1.24.1. Commented 19 hours ago
  • Nice find. Tested working in a Kubuntu 22.04.3 LiveCD + groff=1.22.4-8build1. Too bad Ubuntu 24.04, 25.10, 26.10 and Debian 13, 14, and sid are all stuck on 1.23 Commented 19 hours ago
  • The fix is a one-liner. cgit.git.savannah.gnu.org/cgit/groff.git/commit/… You could update your /usr/share/groff/1.23.0/tmac/an.tmac file in place (possibly using dpkg-divert first if you're scrupulous), or finagle it into your /etc/groff/man.local. If you do the latter, you'll want to append the string definition to the definition of the TH macro. Since I'll need a code block to illustrate, I'll update my answer again. Commented 19 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.