Commit 5348178 h
Pat Ambrosio · 26-08-27 14:26
Give a tooltip a width instead of letting it shrink-wrap
Changes: 3 files
+38
-0
Changes (Side-by-Side)
share/jenny/layout/page.sh +11 -0
cat << _EOF_ |
| 747 |
font-size: 0.85em; |
747 |
font-size: 0.85em; |
| 748 |
line-height: 1.4; |
748 |
line-height: 1.4; |
| 749 |
white-space: normal; |
749 |
white-space: normal; |
| |
750 |
/* An absolutely positioned box with no width shrink-wraps to its |
| |
751 |
containing block, and the containing block here is the <sup> -- |
| |
752 |
about 48px. The tooltip collapsed to a 89px column, 585px tall for |
| |
753 |
a long note. max-width is a ceiling and cannot lift a box off that |
| |
754 |
floor, so the width is stated and the viewport clamp keeps it |
| |
755 |
honest on a narrow screen. */ |
| |
756 |
width: max-content; |
| 750 |
max-width: min(280px, calc(100vw - 2em)); |
757 |
max-width: min(280px, calc(100vw - 2em)); |
| |
758 |
/* border-box so the cap counts the padding and border: measured at |
| |
759 |
299px against a 280px max, which is the difference between them |
| |
760 |
and is enough to push a tooltip off a narrow screen. */ |
| |
761 |
box-sizing: border-box; |
| 751 |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
762 |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| 752 |
z-index: 1000; |
763 |
z-index: 1000; |
| 753 |
opacity: 0; |
764 |
opacity: 0; |
share/jenny/layout/post.sh +11 -0
cat << _EOF_ |
| 568 |
font-size: 0.85em; |
568 |
font-size: 0.85em; |
| 569 |
line-height: 1.4; |
569 |
line-height: 1.4; |
| 570 |
white-space: normal; |
570 |
white-space: normal; |
| |
571 |
/* An absolutely positioned box with no width shrink-wraps to its |
| |
572 |
containing block, and the containing block here is the <sup> -- |
| |
573 |
about 48px. The tooltip collapsed to a 89px column, 585px tall for |
| |
574 |
a long note. max-width is a ceiling and cannot lift a box off that |
| |
575 |
floor, so the width is stated and the viewport clamp keeps it |
| |
576 |
honest on a narrow screen. */ |
| |
577 |
width: max-content; |
| 571 |
max-width: min(280px, calc(100vw - 2em)); |
578 |
max-width: min(280px, calc(100vw - 2em)); |
| |
579 |
/* border-box so the cap counts the padding and border: measured at |
| |
580 |
299px against a 280px max, which is the difference between them |
| |
581 |
and is enough to push a tooltip off a narrow screen. */ |
| |
582 |
box-sizing: border-box; |
| 572 |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
583 |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| 573 |
z-index: 1000; |
584 |
z-index: 1000; |
| 574 |
opacity: 0; |
585 |
opacity: 0; |
test/regressions.sh +16 -0
it "tooltips show on keyboard focus events" |
| 2435 |
# Script listens to focusin and focusout. |
2435 |
# Script listens to focusin and focusout. |
| 2436 |
assert_file_contains "$tt_post" "addEventListener('focusin'" |
2436 |
assert_file_contains "$tt_post" "addEventListener('focusin'" |
| 2437 |
|
2437 |
|
| |
2438 |
it "a tooltip is as wide as it needs to be, not as wide as its marker" |
| |
2439 |
# An absolutely positioned box with no width shrink-wraps to its containing |
| |
2440 |
# block, and the containing block is the <sup> -- about 48px. A long note |
| |
2441 |
# collapsed into an 89px column 585px tall. max-width is a ceiling and cannot |
| |
2442 |
# lift a box off that floor, so the width has to be stated. |
| |
2443 |
# |
| |
2444 |
# Scoped to the tooltip's own rule: "width: max-content" appears elsewhere in |
| |
2445 |
# the stylesheet, so a bare search passed with this line deleted. |
| |
2446 |
tip_w_rule=$("$SED" -n '/^ \.fn-tip,$/,/^ }/p' "$tt_post") |
| |
2447 |
assert_contains "$tip_w_rule" 'width: max-content;' |
| |
2448 |
|
| |
2449 |
it "the width cap counts the padding" |
| |
2450 |
# Without border-box the cap applies to the content only, so a 280px maximum |
| |
2451 |
# drew 299px -- enough to push a tooltip off a narrow screen. |
| |
2452 |
assert_contains "$tip_w_rule" 'box-sizing: border-box;' |
| |
2453 |
|
| 2438 |
it "a tooltip is kept inside the viewport by measurement, not a breakpoint" |
2454 |
it "a tooltip is kept inside the viewport by measurement, not a breakpoint" |
| 2439 |
# Centred on its marker, a tooltip near the right margin hangs off the edge -- |
2455 |
# Centred on its marker, a tooltip near the right margin hangs off the edge -- |
| 2440 |
# at 440px a 232px tooltip on a marker at x=329 ended 5px off-screen, while its |
2456 |
# at 440px a 232px tooltip on a marker at x=329 ended 5px off-screen, while its |
Raw
commit 53481788ff9eb9d0c2e18937a64d51e7236bb131
Author: Pat Ambrosio <cp.ambrosio@gmail.com>
Date: Thu Aug 27 14:26:55 2026 +0800
Give a tooltip a width instead of letting it shrink-wrap
A long footnote drew as an 89px column 585px tall -- taller than wide, at a
1440px viewport where the cap is 280px.
An absolutely positioned box with no width shrink-wraps to its containing
block, and the containing block here is the <sup>: about 48px. max-width is
a ceiling and cannot lift a box off that floor, so the width is stated as
max-content and the viewport clamp keeps it honest on a narrow screen. The
spec-rot note goes from 89x585 to 280x140.
box-sizing too: without it the cap applies to the content box only, so a
280px maximum drew 299px -- enough to push a tooltip off a narrow screen,
and exactly the kind of difference the earlier off-screen bug turned on.
Measured at 320, 380, 440, 600, 900 and 1440: 280px wide at every one,
never taller than wide, nothing off-screen, no page overflow with every
tooltip open at once. Then 65 tooltips across five widths on a review page
built for the purpose.
One of the two tests passed against broken code: "width: max-content"
appears elsewhere in the same stylesheet, so a bare search still matched
with the tooltip's own line deleted. It is scoped to the tooltip rule now,
and the mutation fails it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnSAstgnDYdKPwLGv1YZE5
diff --git a/share/jenny/layout/page.sh b/share/jenny/layout/page.sh
index b5d5489..fa807a4 100755
--- a/share/jenny/layout/page.sh
+++ b/share/jenny/layout/page.sh
@@ -747,7 +747,18 @@ cat << _EOF_
font-size: 0.85em;
line-height: 1.4;
white-space: normal;
+ /* An absolutely positioned box with no width shrink-wraps to its
+ containing block, and the containing block here is the <sup> --
+ about 48px. The tooltip collapsed to a 89px column, 585px tall for
+ a long note. max-width is a ceiling and cannot lift a box off that
+ floor, so the width is stated and the viewport clamp keeps it
+ honest on a narrow screen. */
+ width: max-content;
max-width: min(280px, calc(100vw - 2em));
+ /* border-box so the cap counts the padding and border: measured at
+ 299px against a 280px max, which is the difference between them
+ and is enough to push a tooltip off a narrow screen. */
+ box-sizing: border-box;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1000;
opacity: 0;
diff --git a/share/jenny/layout/post.sh b/share/jenny/layout/post.sh
index 5e5621c..4e0459e 100755
--- a/share/jenny/layout/post.sh
+++ b/share/jenny/layout/post.sh
@@ -568,7 +568,18 @@ cat << _EOF_
font-size: 0.85em;
line-height: 1.4;
white-space: normal;
+ /* An absolutely positioned box with no width shrink-wraps to its
+ containing block, and the containing block here is the <sup> --
+ about 48px. The tooltip collapsed to a 89px column, 585px tall for
+ a long note. max-width is a ceiling and cannot lift a box off that
+ floor, so the width is stated and the viewport clamp keeps it
+ honest on a narrow screen. */
+ width: max-content;
max-width: min(280px, calc(100vw - 2em));
+ /* border-box so the cap counts the padding and border: measured at
+ 299px against a 280px max, which is the difference between them
+ and is enough to push a tooltip off a narrow screen. */
+ box-sizing: border-box;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1000;
opacity: 0;
diff --git a/test/regressions.sh b/test/regressions.sh
index b9809fb..a098835 100755
--- a/test/regressions.sh
+++ b/test/regressions.sh
@@ -2435,6 +2435,22 @@ it "tooltips show on keyboard focus events"
# Script listens to focusin and focusout.
assert_file_contains "$tt_post" "addEventListener('focusin'"
+it "a tooltip is as wide as it needs to be, not as wide as its marker"
+# An absolutely positioned box with no width shrink-wraps to its containing
+# block, and the containing block is the <sup> -- about 48px. A long note
+# collapsed into an 89px column 585px tall. max-width is a ceiling and cannot
+# lift a box off that floor, so the width has to be stated.
+#
+# Scoped to the tooltip's own rule: "width: max-content" appears elsewhere in
+# the stylesheet, so a bare search passed with this line deleted.
+tip_w_rule=$("$SED" -n '/^ \.fn-tip,$/,/^ }/p' "$tt_post")
+assert_contains "$tip_w_rule" 'width: max-content;'
+
+it "the width cap counts the padding"
+# Without border-box the cap applies to the content only, so a 280px maximum
+# drew 299px -- enough to push a tooltip off a narrow screen.
+assert_contains "$tip_w_rule" 'box-sizing: border-box;'
+
it "a tooltip is kept inside the viewport by measurement, not a breakpoint"
# Centred on its marker, a tooltip near the right margin hangs off the edge --
# at 440px a 232px tooltip on a marker at x=329 ended 5px off-screen, while its