Skip to content

Adopt the Sphinx theme's unused boxed inline literal, or keep the bare literal both builds render #180

Description

@mmcky

Raised by DrDrij in the v2.5.0 design review of QuantEcon/lecture-python-programming#363: "Spacing of inline <code> elements a little off, wide spacing between words but not enough padding before and after." Re-measured against the deployed Sphinx build, the theme reproduces code.literal within about 1% on every metric — including the padding, which Sphinx also sets to zero — and the wide inter-word gaps are the monospace space advance, which the Sphinx build has too. So there is no parity defect to fix. There is a design choice worth taking deliberately, because quantecon-book-theme ships the exact treatment DrDrij is describing as an opt-in mode that no lecture site has ever enabled.

What was measured

Sphinx column: the live page python-programming.quantecon.org/numpy.html as rendered, read from getComputedStyle in headless Chromium at 1440×1000 after document.fonts.ready. Theme column: the declarations at styles/quantecon.css:217-234 (.article :not(pre) > code), with the space advance measured for the resolved font stack in the same browser.

Property Sphinx code.literal Theme .article :not(pre) > code Δ
font-size 16.2px (.9rem of an 18px root) 16px (1rem of a 16px root) −1.2%
prose size around it 18px 18px (styles/quantecon.css:314)
font-family "Source Code Pro", monospace, and Source Code Pro is never loaded menlo, consolas, "DejaVu Sans Mono", monospace same rendered face
font-weight 400 400
letter-spacing 0.18px 0.16px (0.01rem) −0.02px
colour rgb(175, 95, 95) #af5f5f
padding 0px, all four sides none declared anywhere
background rgba(0, 0, 0, 0) none declared anywhere
border 0px none none declared anywhere
space advance inside the literal 9.91px 9.80px −1.1%

The wide inter-word gaps are the monospace space advance and nothing else. On the live Sphinx page a space inside code.literal measures 9.91px against 3.59px in the surrounding prose — a 2.76× ratio the theme reproduces at 9.80px. Letter-spacing contributes almost nothing: at 0.16px per gap it accounts for 2.89px of the 176.28px import numpy as np string, or 1.6%. Nothing narrows those gaps without narrowing the glyphs with them.

Source Code Pro is genuinely absent rather than merely unmeasurable: [...document.fonts] on the live page lists only Font Awesome, PT Serif, Source Sans Pro and the MathJax faces, and no @font-face for it exists in the 81KB quantecon-book-theme.css. The declared Source Code Pro, monospace therefore resolves to generic monospace, which measures the same 9.91px advance the theme's explicit stack lands on.

The theme's side of the padding row was checked two ways, not just by reading the rule: no declaration in styles/*.css puts padding, background or border on inline code, and @tailwindcss/typography's base styles add none either. Both builds render a bare literal.

Where the padding went, in Sphinx

Fetched from the deployed _static/styles/quantecon-book-theme.css. The boxed literal is defined:

cite,code,tt{background-color:#efefef;border:1px dotted #ccc;border-radius:2px;font-family:Source Code Pro,monospace;font-size:.9rem;font-style:normal;letter-spacing:.01rem;overflow-wrap:break-word;padding:0 2px}

and then switched off again for the case that actually occurs:

body:not(.inline-literal-box) code.literal{background-color:transparent;border:none;border-radius:0;padding:0}

inline-literal-box appears exactly once in that stylesheet — in the rule above, which disables the box — and nowhere in the served markup: every lecture page renders a bare <body> with className === "". So the disabling rule always matches, at (0,2,2) against the box rule's (0,0,1), and the box has never drawn on a QuantEcon lecture site. The padded, tinted, dotted-border literal DrDrij is asking for is not a new design. It is the Sphinx theme's own alternate mode, built and left unused, and under the recorded stance that makes it a live option rather than a closed question.

What adopting it actually costs

Not the CSS. The declarations already exist in both codebases, and the rendered difference is two pixels of horizontal padding, a grey ground and a dotted hairline. The cost is contrast and dark mode.

Light mode fails as written. #af5f5f is 4.54:1 on white — already only just over the AA 4.5:1 minimum, and flagged as such at styles/quantecon.css:83. On the #efefef ground it drops to 3.95:1. Adopting the box means darkening the literal colour or lightening the ground, in both stacks, so the two builds do not diverge on the colour while diverging on nothing else.

Dark mode is untested rather than absent. The Sphinx sheet does carry a dark treatment for the box:

body.dark-theme cite,body.dark-theme code,body.dark-theme tt{background-color:var(--qe-dark-surface);border-color:var(--qe-dark-border);color:var(--qe-dark-inline-code)}

with --qe-dark-surface:#252540 and --qe-dark-border:#3a3a5c. That rule is (0,1,2) and the disabling rule is (0,2,2), so the box is off in dark mode too and those values have never been displayed to a reader either. This theme has no counterpart for them: its dark block at styles/quantecon.css:99-103 defines only --qe-literal-color, --qe-link-color and --qe-link-hover-color. Adopting means shipping a dark treatment neither build has ever rendered, and introducing the two surface tokens here. The dark literal colour itself is fine — #d78787 on #252540 is 5.44:1.

Options 2 and 3 also move every visual baseline that contains inline code, across all four platform sets (24 PNGs under tests/visual/__snapshots__), and a two-pixel padding change is well inside the 1% maxDiffPixelRatio at tests/visual/theme.spec.ts:34, so the local refresh needs --update-snapshots=all and the CI set needs an /update-snapshots comment.

Options

  1. Accept as is. The theme reproduces what the lecture sites actually render, to within 1% on every metric of this rule. Reply to DrDrij with the measurements and record the decision. Costs nothing and moves no baseline. The right answer if the goal is that a reader cannot tell the two builds apart during the migration.
  2. Adopt the boxed literal in both builds. Answers DrDrij directly, with values that already exist in both codebases, and keeps the builds identical. Costs: a contrast pass on the literal colour against the new ground in both stacks, a dark-mode ground and border this theme has no tokens for, a matching change in quantecon-book-theme, and a baseline refresh here.
  3. Adopt it in this theme only. Cheapest to ship and it still needs the contrast and dark-mode work, but it makes the mystmd build visibly unlike the sites it replaces, on an element that appears in nearly every paragraph, for the whole migration window.

The measurements do not choose between these. What chooses is whether a designer wants the box now that it is clear nobody has ever seen it, and whether the contrast work is worth doing to get it.

Two things to confirm with DrDrij before deciding

Which viewport he reviewed at. Below 992px the Sphinx root steps down to 16px (@media(min-width:992px){html{font-size:18px}}, confirmed at 900px: root 16px, literal 14.4px), while this theme holds a flat 16px literal. That is an 11% difference at narrow widths, produced by a media query rather than by this rule, and the theme's flat sizing is deliberate — a px root is a WCAG 1.4.4 problem, which is why the Sphinx theme has to ship font-plus/font-minus controls to compensate (see the UNITS note at styles/quantecon.css:55-74). If he reviewed in a narrow window he saw a real difference, and it is not the one this issue is about. At desktop width he did not.

Which build his screenshot came from. The sentence in it — "After import numpy as np we have access to these attributes via the syntax np.attribute" — does not appear on the live Sphinx numpy.html. Fetching that page and searching for np.attribute, these attributes and import numpy as np returns zero matches for all three. So the comparison may not have been like with like, and it is worth knowing what the reference image was before reading anything into it.

A correction to make while anyone is in this rule

The comment at styles/quantecon.css:220-224 says the monospace family comes from "Tailwind's preflight and JupyterLab's stylesheet". Only the second half is doing any work. Tailwind's preflight sets code,kbd,samp,pre{font-family:theme('fontFamily.mono', …)} at (0,0,1), and thebe-core.css vendors a JupyterLab rule at the same (0,0,1):

tt,
code,
kbd,
samp,
pre {
  font-family: var(--jp-code-font-family);
  font-size: var(--jp-code-font-size);
  line-height: var(--jp-code-line-height);
}

app/root.tsx loads the Tailwind bundle at line 158 and thebe-core.css at line 159, so on equal specificity the later sheet wins and the resolved family is --jp-code-font-family-default = menlo, consolas, "DejaVu Sans Mono", monospace (node_modules/thebe-core/dist/lib/thebe-core.css:108-113, rule at :263-271). That is a happy accident rather than a mistake — Chrome's generic monospace on macOS resolves to Menlo too, which is why the measured advances match — but the comment records the wrong cause, and the same thebe rule is why --jp-code-font-size: 13px lands on inline <code> outside .article (article literals are safe: .article :not(pre) > code is (0,1,2) and wins).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

design-reviewdiscussOpen-ended team deliberation or a decision to be made

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions