2 Commits

Author SHA1 Message Date
MechaCat02
27add08659 Merge: the panes scroll, the page does not
A hundred notes in the list made the page scroll and the editor grow to
the height of every note put together. `body` had a minimum height
where it needed a definite one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 21:25:39 +02:00
MechaCat02
bafad9b72d Scroll the note list, not the page
With a hundred notes in it the list grew to its full height, the page
scrolled instead of the list, and the editor — a flex sibling stretching
to the row — became as tall as every note put together: 12419px next to
a 700px window.

The cause was one word. `body` had `min-height: 100dvh`, which leaves
the page free to grow with its content, and a column of flex boxes with
no definite height at the top cannot cap anything below it. `min-height:
0` on the items lets them shrink but nothing was telling them what to
shrink *to*. The page now has a definite height and no scrolling of its
own, so the two panes do the scrolling, which is what they were built
for. The settings screen and the login screen scroll themselves, having
no pane.

While there: the editor's floor drops from 12rem to 6rem so a landscape
phone with its keyboard up keeps the toolbar and the save button on
screen rather than overflowing, and the login card centres with `margin:
auto` rather than `justify-content`, because a centred flex item in a
scrolling container cannot be scrolled back to once it overflows the
top.

Reproduced with 123 seeded day notes and measured in Firefox at 1100px
and 390px, before and after: page 12684px → 700px, list scrolls itself,
editor 12419px → 435px, toolbar and save button still on screen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 21:25:34 +02:00

View File

@@ -36,18 +36,34 @@
* { box-sizing: border-box; }
/*
* A *definite* height, not a minimum.
*
* `min-height` leaves the page free to grow with its content, and a column of
* flex boxes with no definite height at the top cannot cap anything below it:
* with a hundred notes in the list, the list grew to its full height, the page
* scrolled instead of the list, and the editor — a flex sibling stretching to
* the row — became as tall as every note put together. Scrolling belongs to the
* two panes, so the page itself must not have any.
*/
body {
margin: 0;
background: var(--bg);
color: var(--fg);
/* Fills the viewport on a phone, where 100vh lies about the toolbar. */
min-height: 100dvh;
height: 100vh;
/* dvh where it exists: 100vh lies about the height while a phone's toolbar
is on screen. */
height: 100dvh;
overflow: hidden;
display: flex;
flex-direction: column;
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.screen { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.screen { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; }
/* The page does not scroll, so anything that is not itself a pane must. */
#login, #view-settings { overflow-y: auto; }
[hidden] { display: none !important; }
/* --- chrome ------------------------------------------------------------ */
@@ -85,6 +101,7 @@ header { border-bottom: 1px solid var(--line); }
.rail {
flex: 0 0 18rem;
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
border-right: 1px solid var(--line);
@@ -147,7 +164,18 @@ header { border-bottom: 1px solid var(--line); }
.row mark { background: color-mix(in srgb, var(--accent) 28%, transparent); color: inherit; border-radius: 0.15rem; }
.detail { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; padding: 0.75rem; min-height: 0; }
.detail {
flex: 1;
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 0.75rem;
/* The editor inside it scrolls; the pane itself never does, so the toolbar
and the save button cannot be pushed off a short screen. */
overflow: hidden;
}
/* Only a phone needs a way back to the list; on a wide screen it is never gone. */
.back { display: none; align-self: flex-start; padding: 0.4rem 0.7rem; font-size: 0.9rem; }
@@ -232,7 +260,9 @@ header { border-bottom: 1px solid var(--line); }
*/
.editor {
flex: 1;
min-height: 12rem;
/* Small enough that a landscape phone with its keyboard up still shows the
toolbar and the actions rather than overflowing the pane. */
min-height: 6rem;
overflow-y: auto;
padding: 0.75rem;
border: 1px solid var(--line);
@@ -309,7 +339,7 @@ header { border-bottom: 1px solid var(--line); }
textarea {
flex: 1;
min-height: 12rem;
min-height: 6rem;
width: 100%;
padding: 0.75rem;
border: 1px solid var(--line);
@@ -386,8 +416,11 @@ input[type="password"], input[type="text"] {
font: inherit;
}
#login { justify-content: center; }
#login .card { width: min(24rem, 100%); align-self: center; }
/* `margin: auto` rather than `justify-content: center`: a centred flex item in
a scrolling container cannot be scrolled back to once it overflows the top,
which on a short screen with the keyboard up would put the password field out
of reach. */
#login .card { width: min(24rem, calc(100% - 1.5rem)); margin: auto; }
#login button { width: 100%; margin-top: 1rem; }
.steps { margin: 0.5rem 0; padding-left: 1.1rem; color: var(--muted); font-size: 0.85rem; line-height: 1.5; }