Every page is 1280 pixels wide, including the tables, and the cap is one line in base.html #188

Closed
opened 2026-09-12 09:52:00 +00:00 by tiagoagueda · 1 comment
Owner

Observation

templates/base.html:

35:  <div class="relative mx-auto flex max-w-7xl ...">   {# header #}
128: <main id="main" class="mx-auto max-w-7xl px-4 py-8 outline-none">
135: <footer class="mx-auto flex max-w-7xl ...">

max-w-7xl is 80rem — 1280 pixels — so on a 1440p or 4K screen the whole application is
a 1280px column with grey on both sides. Nothing opts out: there is no max-w-none, no
w-screen, and no width preference anywhere in the templates or on Profile.

Where it actually costs something

Not the forms. The grids, and the cost is compounding:

  • A wide table scrolls horizontally inside the 1280px column, because the table sits in
    .scroll-x (overflow-x: auto). #136 then gave people chosen columns and saved column
    widths — so somebody can add a tenth column and drag it wider, and the page still refuses
    to use the monitor. The table just scrolls in a box.
  • #160 is making listings a table. #173 wants more filtering in the companies table. #179
    will want the same for captures. Every one of those makes the cap hurt more.
  • The board draws a column per status inside the same 1280px.
  • The dashboard is lg:grid-cols-4 inside it.

Accessibility: checked, and it does not argue against this

The one WCAG criterion about line length is SC 1.4.8 Visual Presentation — "Width is no
more than 80 characters or glyphs"
— and it is level AAA. CLAUDE.md and docs/PLAN.md
both promise WCAG 2.2 AA, and the changelog already keeps that distinction deliberately
("Reflow is level AA, and the README promises AA without qualification").

The reasoning behind 1.4.8 is real at any level, though: a long measure costs readers with
dyslexia, low vision and cognitive disabilities, who lose their place coming back to the
start of the next line. So it decides the shape of this change rather than blocking it —
and it is already being respected. max-w-2xl is 42rem = 672px, which at the 16px base
is about eighty characters. That is 1.4.8's own number; whoever chose it was aiming at it.

There is also an argument for widening the grids. Today a wide table scrolls inside a
capped column, so somebody using a screen magnifier scrolls in two nested contexts to read
one row. Lifting the outer cap removes one of them. Not SC 1.4.10 Reflow, which is about
320px — but the same hostility, at the other end.

The change

Take max-w-7xl off <main> and let each page say how wide it is. Every page that
already caps itself (26 × max-w-2xl, 11 × max-w-md, 7 × max-w-3xl, mostly forms and
entrance pages) is unaffected and keeps its measure.

The header and footer are a separate decision: they may stay at max-w-7xl for a tidy
masthead over a wide page, or follow. Worth choosing rather than inheriting.

Pages with no cap of their own, which is the whole risk surface

Grids — these are the point of the change:

applications/application_list.html      table
applications/application_board.html     a column per status
jobs/company_list.html                  table
jobs/listing_list.html                  table once #160 lands
jobs/capture_list.html                  wants to be one, #179
core/dashboard.html                     lg:grid-cols-4
documents/cv_list.html, letter_list.html, rendered_list.html, upload_list.html
applications/interview_list.html, reminder_list.html, suggestion_list.html

Prose and detail — these need a measure inside a wide page:

jobs/posting_detail.html         the job description; the sharpest case
applications/application_detail.html   notes and the timeline
documents/cv_detail.html, letter_detail.html   a letter body is prose
jobs/company_detail.html         notes
resume/overview.html             section blurbs
applications/report.html, report_print.html    prose and figures

A wide page is not a wide paragraph. A listing detail page going full width with its
description following is trading a table problem for a reading problem, and the description
is exactly the field that runs to forty thousand characters.

Settings already has its own sub-layout — settings/base.html:9 is
mx-auto max-w-5xl lg:flex with a 14rem sidebar — so those pages are unaffected either way.
#180 may widen it; that is that issue's call, not this one's.

Fixed, or a preference?

Recommendation: fixed. Grids go wide, prose keeps its measure, nobody configures
anything. A preference means a Profile field, a migration, a form control on Appearance,
and its strings in every catalogue — for a choice most people would set once and forget, and
which the per-page split already gets right for them.

Profile does already hold theme, table_settings and dashboard_widgets, so a width
preference would sit naturally beside them later if anybody asks. Doing it now would mean
building the machine before knowing whether the default is wrong.

Checks this must not break

  • test_accessibility.py runs axe-core over every page signed in and out; a layout change
    goes through it.
  • test_the_dashboard_lays_out_in_four_columns and test_a_narrow_screen_reads_downwards
    assert the dashboard's grid and stacking.
  • #73 is where the phone gets its proper attention. Nothing here should make a narrow
    screen worse, and the per-page caps are what keeps it from doing so.
  • The compiled stylesheet is committed and CI compares it, so this needs npm run build:css.
## Observation `templates/base.html`: 35: <div class="relative mx-auto flex max-w-7xl ..."> {# header #} 128: <main id="main" class="mx-auto max-w-7xl px-4 py-8 outline-none"> 135: <footer class="mx-auto flex max-w-7xl ..."> `max-w-7xl` is 80rem — **1280 pixels** — so on a 1440p or 4K screen the whole application is a 1280px column with grey on both sides. **Nothing opts out**: there is no `max-w-none`, no `w-screen`, and no width preference anywhere in the templates or on `Profile`. ## Where it actually costs something Not the forms. The **grids**, and the cost is compounding: - A wide table scrolls horizontally **inside** the 1280px column, because the table sits in `.scroll-x` (`overflow-x: auto`). #136 then gave people chosen columns and saved column widths — so somebody can add a tenth column and drag it wider, and the page still refuses to use the monitor. The table just scrolls in a box. - #160 is making listings a table. #173 wants more filtering in the companies table. #179 will want the same for captures. Every one of those makes the cap hurt more. - The board draws a column per status inside the same 1280px. - The dashboard is `lg:grid-cols-4` inside it. ## Accessibility: checked, and it does not argue against this The one WCAG criterion about line length is **SC 1.4.8 Visual Presentation** — *"Width is no more than 80 characters or glyphs"* — and it is **level AAA**. `CLAUDE.md` and `docs/PLAN.md` both promise **WCAG 2.2 AA**, and the changelog already keeps that distinction deliberately ("Reflow is level AA, and the README promises AA without qualification"). The reasoning behind 1.4.8 is real at any level, though: a long measure costs readers with dyslexia, low vision and cognitive disabilities, who lose their place coming back to the start of the next line. So it decides the shape of this change rather than blocking it — **and it is already being respected.** `max-w-2xl` is 42rem = 672px, which at the 16px base is about eighty characters. That is 1.4.8's own number; whoever chose it was aiming at it. There is also an argument **for** widening the grids. Today a wide table scrolls inside a capped column, so somebody using a screen magnifier scrolls in two nested contexts to read one row. Lifting the outer cap removes one of them. Not SC 1.4.10 Reflow, which is about 320px — but the same hostility, at the other end. ## The change **Take `max-w-7xl` off `<main>`** and let each page say how wide it is. Every page that already caps itself (26 × `max-w-2xl`, 11 × `max-w-md`, 7 × `max-w-3xl`, mostly forms and entrance pages) is unaffected and keeps its measure. The header and footer are a separate decision: they may stay at `max-w-7xl` for a tidy masthead over a wide page, or follow. Worth choosing rather than inheriting. ### Pages with no cap of their own, which is the whole risk surface **Grids — these are the point of the change:** applications/application_list.html table applications/application_board.html a column per status jobs/company_list.html table jobs/listing_list.html table once #160 lands jobs/capture_list.html wants to be one, #179 core/dashboard.html lg:grid-cols-4 documents/cv_list.html, letter_list.html, rendered_list.html, upload_list.html applications/interview_list.html, reminder_list.html, suggestion_list.html **Prose and detail — these need a measure *inside* a wide page:** jobs/posting_detail.html the job description; the sharpest case applications/application_detail.html notes and the timeline documents/cv_detail.html, letter_detail.html a letter body is prose jobs/company_detail.html notes resume/overview.html section blurbs applications/report.html, report_print.html prose and figures **A wide page is not a wide paragraph.** A listing detail page going full width with its description following is trading a table problem for a reading problem, and the description is exactly the field that runs to forty thousand characters. **Settings already has its own sub-layout** — `settings/base.html:9` is `mx-auto max-w-5xl lg:flex` with a 14rem sidebar — so those pages are unaffected either way. `#180` may widen it; that is that issue's call, not this one's. ## Fixed, or a preference? **Recommendation: fixed.** Grids go wide, prose keeps its measure, nobody configures anything. A preference means a `Profile` field, a migration, a form control on Appearance, and its strings in every catalogue — for a choice most people would set once and forget, and which the per-page split already gets right for them. `Profile` does already hold `theme`, `table_settings` and `dashboard_widgets`, so a width preference would sit naturally beside them **later** if anybody asks. Doing it now would mean building the machine before knowing whether the default is wrong. ## Checks this must not break - `test_accessibility.py` runs axe-core over every page signed in and out; a layout change goes through it. - `test_the_dashboard_lays_out_in_four_columns` and `test_a_narrow_screen_reads_downwards` assert the dashboard's grid and stacking. - `#73` is where the phone gets its proper attention. Nothing here should make a narrow screen worse, and the per-page caps are what keeps it from doing so. - The compiled stylesheet is committed and CI compares it, so this needs `npm run build:css`.
Author
Owner

Landed on main as 43d51b043, with one change of shape from what this issue proposed.

Rather than take the cap off <main> and chase every page that had no cap of its own --
the allauth and MFA pages among them -- <main> takes its width from a main_width block
whose default is the cap it always had. The thirteen grid pages listed here empty it
and take the screen; everything else keeps its measure without being touched. That inverts
the risk surface: the only pages that change are the ones meant to.

The header and footer span the width, so a masthead never sits narrower than a table under
it. Below 1280 pixels nothing changes, and the compiled stylesheet did not either.

Checked from the markup by tests/test_width.py (twelve grid pages uncapped, seven measured
pages at 7xl, header and footer uncapped) and from a browser at 2560 pixels by
tests/e2e/test_width.py (the applications table's main and its scroll box take the
screen; a form stays at 1280).

Two things noticed on the way: /jobs/captures/ now redirects to /listings/ and
/settings/ to /settings/appearance/, so the tests name the final pages. The print report
is a standalone document outside base.html and is unaffected either way.

Landed on `main` as `43d51b043`, with one change of shape from what this issue proposed. Rather than take the cap off `<main>` and chase every page that had no cap of its own -- the allauth and MFA pages among them -- `<main>` takes its width from a `main_width` block whose **default is the cap it always had**. The thirteen grid pages listed here empty it and take the screen; everything else keeps its measure without being touched. That inverts the risk surface: the only pages that change are the ones meant to. The header and footer span the width, so a masthead never sits narrower than a table under it. Below 1280 pixels nothing changes, and the compiled stylesheet did not either. Checked from the markup by `tests/test_width.py` (twelve grid pages uncapped, seven measured pages at 7xl, header and footer uncapped) and from a browser at 2560 pixels by `tests/e2e/test_width.py` (the applications table's `main` and its scroll box take the screen; a form stays at 1280). Two things noticed on the way: `/jobs/captures/` now redirects to `/listings/` and `/settings/` to `/settings/appearance/`, so the tests name the final pages. The print report is a standalone document outside `base.html` and is unaffected either way.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#188
No description provided.