diff --git a/src/http/app/app.css b/src/http/app/app.css index bf4f75f..ed23f85 100644 --- a/src/http/app/app.css +++ b/src/http/app/app.css @@ -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; }