234 lines
8.4 KiB
CSS
234 lines
8.4 KiB
CSS
|
|
body {
|
||
|
|
font-family: var(--serif);
|
||
|
|
font-size: 100%;
|
||
|
|
line-height: 1.3;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* The monospace font is scaled so its letters are the height of the serif
|
||
|
|
font's, rather than by eye: md_to_pdf.py computes --mono-scale from the
|
||
|
|
two fonts' x-height and cap-height (the same rule the SKS applies), so
|
||
|
|
this stays right if either font is changed. */
|
||
|
|
code, pre {
|
||
|
|
font-family: var(--mono);
|
||
|
|
font-size: calc(1em * var(--mono-scale, 1));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Once, not twice. A fenced block is <pre><code>, so both elements match
|
||
|
|
the rule above and the scale is applied to the scaled size: measured
|
||
|
|
before this rule, inline code came out at 14.00px and the same code in a
|
||
|
|
box at 12.26px -- a metric-matched scale silently defeating itself. The
|
||
|
|
code in a box inherits the pre's size instead. */
|
||
|
|
pre code {
|
||
|
|
font-size: 1em;
|
||
|
|
}
|
||
|
|
|
||
|
|
h1, h2, h3, h4, h5, h6 {
|
||
|
|
font-family: var(--sans);
|
||
|
|
font-weight: normal;
|
||
|
|
padding-top: .5rem;
|
||
|
|
padding-bottom: 0rem;
|
||
|
|
margin-top: .0rem;
|
||
|
|
margin-bottom: 0rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h1 {
|
||
|
|
font-size: 1.2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h2 {
|
||
|
|
font-size: 1.1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h3, h4, h5, h6 {
|
||
|
|
font-size: 1.0rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* The gap between a section number and its title, in a heading and in a
|
||
|
|
table-of-contents entry alike. The number is plain text in the Markdown
|
||
|
|
("## 2.9 Keystone correction", "- [2.9 Keystone correction](#29-...)");
|
||
|
|
md_to_pdf.py wraps it in this span and eats the space that followed it, so
|
||
|
|
the whole distance is set here. Change --secnum-gap to widen or narrow
|
||
|
|
it, or give the contents its own gap with a "li .secnum" rule. To rule a
|
||
|
|
contents into columns rather than merely space it, add
|
||
|
|
"display: inline-block" and a "min-width" there: the titles then align
|
||
|
|
instead of each starting one gap after a number of its own width. */
|
||
|
|
:root {
|
||
|
|
--secnum-gap: 0.5em;
|
||
|
|
}
|
||
|
|
|
||
|
|
.secnum {
|
||
|
|
margin-right: var(--secnum-gap);
|
||
|
|
}
|
||
|
|
|
||
|
|
p, ol, ul {
|
||
|
|
margin-top: 0.5rem;
|
||
|
|
margin-bottom: 0.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
pre {
|
||
|
|
/* A code line wider than the page does not overflow or clip when
|
||
|
|
printing: Chromium shrinks the WHOLE document until it fits, silently,
|
||
|
|
by a factor that changes with the longest line. Wrapping guarantees
|
||
|
|
that never happens. md_to_pdf.py --wrap-code breaks shell lines at a
|
||
|
|
word boundary with a "\" first, which is copy-pasteable; this catches
|
||
|
|
what it cannot wrap (PowerShell, .ini, ASCII diagrams). */
|
||
|
|
white-space: pre-wrap;
|
||
|
|
overflow-wrap: anywhere;
|
||
|
|
padding-left: 0rem;
|
||
|
|
border: 1px solid #888;
|
||
|
|
background-color: #EFE;
|
||
|
|
}
|
||
|
|
|
||
|
|
th {
|
||
|
|
border-bottom: 1px solid #000;
|
||
|
|
}
|
||
|
|
|
||
|
|
table, th, td {
|
||
|
|
border: 1px solid gray;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
@media print {
|
||
|
|
/* A section title never sits alone at the foot of a page: the break is
|
||
|
|
forbidden between a heading and whatever follows it, so the heading
|
||
|
|
moves to the next page with its text. break-inside keeps a heading
|
||
|
|
that wraps from being split across the fold.
|
||
|
|
|
||
|
|
Chromium honours these when it paginates for printing (measured on a
|
||
|
|
16-page test document: three headings stranded at a page bottom
|
||
|
|
before, none after, and the page count unchanged). A heading it
|
||
|
|
cannot honour them for -- one taller than the page -- is laid out
|
||
|
|
as if they were absent rather than looped over, which is the
|
||
|
|
specified behaviour for an unsatisfiable avoid.
|
||
|
|
|
||
|
|
This does NOT govern how much of the following paragraph comes with
|
||
|
|
the heading: that is `orphans`, below. */
|
||
|
|
h1, h2, h3, h4, h5, h6 {
|
||
|
|
break-after: avoid;
|
||
|
|
break-inside: avoid;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* A paragraph split by a page break leaves at least two lines on each
|
||
|
|
side of it: never one line stranded at the foot of a page (orphans),
|
||
|
|
never one line arriving alone at the top of the next (widows) -- and
|
||
|
|
with break-after above, that top-of-page line would be the one
|
||
|
|
directly under a heading the break has just moved. Both properties
|
||
|
|
are inherited, so declaring them on body covers list items and table
|
||
|
|
cells too.
|
||
|
|
|
||
|
|
Measured on a 16-page test document: Chromium honours both -- with
|
||
|
|
orphans: 1 it packs the text into 15 pages, and with widows: 1 it
|
||
|
|
moves a line back across a page boundary (same page count, different
|
||
|
|
pagination) -- and 2 is ALREADY its default for both, so rendering
|
||
|
|
with these declarations is byte-identical to rendering without them.
|
||
|
|
They are here to pin the values, not to change today's output: the CSS
|
||
|
|
initial value is 2 but a UA is free to differ, and a stylesheet added
|
||
|
|
after this one could relax it. */
|
||
|
|
body {
|
||
|
|
orphans: 2;
|
||
|
|
widows: 2;
|
||
|
|
}
|
||
|
|
pre {
|
||
|
|
padding: .75rem 1.25rem .75rem 1.25rem;
|
||
|
|
break-inside: avoid;
|
||
|
|
}
|
||
|
|
a[href]:after {
|
||
|
|
content: none;
|
||
|
|
}
|
||
|
|
th, td {
|
||
|
|
padding: .25rem .75rem;
|
||
|
|
}
|
||
|
|
table {
|
||
|
|
margin-left: 1rem;
|
||
|
|
margin-bottom: .5rem;
|
||
|
|
border-collapse: collapse;
|
||
|
|
}
|
||
|
|
th {
|
||
|
|
border-bottom: 1px solid #000;
|
||
|
|
text-align: left;
|
||
|
|
padding-right: 2rem;
|
||
|
|
padding-bottom: 0.2em;
|
||
|
|
}
|
||
|
|
tbody tr:first-child td {
|
||
|
|
padding-top: 0.0em;
|
||
|
|
}
|
||
|
|
blockquote {
|
||
|
|
margin-left: 1rem;
|
||
|
|
}
|
||
|
|
table, th, td {
|
||
|
|
border: 1px solid #BBB;
|
||
|
|
}
|
||
|
|
:root {
|
||
|
|
--link-blue: #042B8C; /* #03216C; */
|
||
|
|
}
|
||
|
|
|
||
|
|
a {
|
||
|
|
color: var(--link-blue);
|
||
|
|
}
|
||
|
|
|
||
|
|
a, a:link, a:visited {
|
||
|
|
outline: 0;
|
||
|
|
text-decoration: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
a:hover {
|
||
|
|
text-decoration: underline;
|
||
|
|
text-underline-offset: 0.2em;
|
||
|
|
text-decoration-thickness: 1px;
|
||
|
|
outline: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* The page number, in the document's own face.
|
||
|
|
|
||
|
|
This is a CSS Paged Media margin box, and it is the reason to prefer
|
||
|
|
it over md_to_pdf.py's --page-numbers: Chromium's footer template is
|
||
|
|
rendered in a context of its own that cannot see this stylesheet, so
|
||
|
|
the number comes out in a generic sans, while var(--serif) here is the
|
||
|
|
EB Garamond the text is set in. Measured 2026-08-09 on Brave 151:
|
||
|
|
margin boxes work and count pages. They are recent, though -- an
|
||
|
|
older Chromium silently prints no number at all.
|
||
|
|
|
||
|
|
DO NOT ALSO PASS --page-numbers. The two mechanisms are independent
|
||
|
|
and both would draw, one over the other, and the flag additionally
|
||
|
|
widens the bottom margin.
|
||
|
|
|
||
|
|
HEIGHT. A margin box is drawn in the margin and cannot be moved out
|
||
|
|
of it, so where the number sits and how much text a page holds are
|
||
|
|
one question, not two. Chromium centres the box in the margin band
|
||
|
|
by default; these declarations pin it to the top of a slightly larger
|
||
|
|
band instead, which puts the number 27pt above the paper edge rather
|
||
|
|
than 12 -- a body line higher -- while the padding, all 1.5pt of it,
|
||
|
|
leaves the text block ending just above it. The text therefore keeps
|
||
|
|
the line it would otherwise have lost to the raised number: measured,
|
||
|
|
a document that grew from 3 pages to 4 when the number was raised
|
||
|
|
alone is back to 3.
|
||
|
|
|
||
|
|
THE TIGHT SPOT, and the number to change if it shows. Text and
|
||
|
|
number now share a narrow band, so on a page whose last line reaches
|
||
|
|
the bottom of the block they nearly touch: measured worst pages over
|
||
|
|
three documents, 7.6 / 3.1 / 2.4pt between the last line's box and
|
||
|
|
the number's. Nothing overlapped, but 2.4pt is close. Giving the
|
||
|
|
text back only HALF a line -- margin-bottom 0.60in, padding-top
|
||
|
|
4.4pt, the number within a point of where it is now -- measured
|
||
|
|
8.4 / 9.1 / 11.4pt instead, and cost no document a page.
|
||
|
|
|
||
|
|
var(--serif) is safe here because the body is set in it, so the
|
||
|
|
webfont is loaded. A face the document does not otherwise use is NOT
|
||
|
|
loaded for a margin box: var(--mono) in a prose-only document fell
|
||
|
|
back to the platform monospace, and in one variant the box rendered
|
||
|
|
nothing whatever -- silently, as ever with print CSS. */
|
||
|
|
@page {
|
||
|
|
margin-bottom: 0.56in; /* the number, and little else */
|
||
|
|
@bottom-center {
|
||
|
|
content: counter(page) " of " counter(pages);
|
||
|
|
font-family: var(--serif);
|
||
|
|
font-size: 9pt;
|
||
|
|
color: black;
|
||
|
|
vertical-align: top; /* not centred in the margin band */
|
||
|
|
padding-top: 1.5pt; /* its distance from the text */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|