|
2 | 2 | forms.css — Alignment, spacing & responsive polish for django-forms-workflows |
3 | 3 | ═══════════════════════════════════════════════════════════════════════════ */ |
4 | 4 |
|
5 | | -/* ── Side-by-side field alignment ──────────────────────────────────────── |
6 | | - When two or more fields sit in a .row.fields-aligned-row, every column |
7 | | - becomes a flex column so .mb-3 can stretch to fill it. The input/select |
8 | | - uses margin-top:auto to push itself to the bottom of the label area, |
9 | | - keeping inputs horizontally aligned regardless of label wrapping. */ |
10 | | - |
11 | | -/* 1. Make each column a flex column so .mb-3 can stretch */ |
12 | | -.row.fields-aligned-row > [class*="col-"], |
13 | | -.row.fields-aligned-row > .field-wrapper { |
14 | | - display: flex; |
15 | | - flex-direction: column; |
16 | | -} |
17 | | - |
18 | | -/* 2. .mb-3 fills the column and is itself a flex column */ |
19 | | -.row.fields-aligned-row > [class*="col-"] > .mb-3, |
20 | | -.row.fields-aligned-row > .field-wrapper > .mb-3 { |
21 | | - display: flex; |
22 | | - flex-direction: column; |
23 | | - flex: 1 1 auto; |
24 | | -} |
| 5 | +/* ── Side-by-side field alignment (CSS Grid + subgrid) ───────────────── |
| 6 | + When two or more fields sit in a .row.fields-aligned-row we switch from |
| 7 | + Bootstrap's flexbox row to a CSS Grid so that labels, inputs and help |
| 8 | + text each share a common row track across columns. This guarantees |
| 9 | + perfect horizontal alignment regardless of label wrapping or the |
| 10 | + presence / absence of help text in any column. |
| 11 | +
|
| 12 | + Grid row tracks: 1 = label | 2 = input | 3 = help text / errors |
| 13 | + ──────────────────────────────────────────────────────────────────────── */ |
| 14 | + |
| 15 | +/* 1. The row becomes a CSS Grid; columns flow automatically */ |
| 16 | +@media (min-width: 768px) { |
| 17 | + .row.fields-aligned-row { |
| 18 | + display: grid !important; |
| 19 | + grid-auto-flow: column; |
| 20 | + grid-auto-columns: 1fr; |
| 21 | + grid-template-rows: auto auto auto; |
| 22 | + column-gap: var(--bs-gutter-x, 1.5rem); |
| 23 | + margin-left: 0; |
| 24 | + margin-right: 0; |
| 25 | + } |
25 | 26 |
|
26 | | -/* 3. Labels stay at their natural size */ |
27 | | -.row.fields-aligned-row > [class*="col-"] > .mb-3 > label, |
28 | | -.row.fields-aligned-row > .field-wrapper > .mb-3 > label { |
29 | | - flex-shrink: 0; |
30 | | -} |
| 27 | + /* 2. Each field-wrapper spans all 3 row tracks and inherits them */ |
| 28 | + .row.fields-aligned-row > .field-wrapper { |
| 29 | + display: grid; |
| 30 | + grid-template-rows: subgrid; |
| 31 | + grid-row: span 3; |
| 32 | + /* Reset Bootstrap column flex/width — grid handles sizing */ |
| 33 | + width: auto !important; |
| 34 | + max-width: none !important; |
| 35 | + flex: none !important; |
| 36 | + padding-left: 0; |
| 37 | + padding-right: 0; |
| 38 | + } |
31 | 39 |
|
32 | | -/* 4. Push the input/select to the bottom of the label area */ |
33 | | -.row.fields-aligned-row > [class*="col-"] > .mb-3 > .form-control, |
34 | | -.row.fields-aligned-row > [class*="col-"] > .mb-3 > .form-select, |
35 | | -.row.fields-aligned-row > .field-wrapper > .mb-3 > .form-control, |
36 | | -.row.fields-aligned-row > .field-wrapper > .mb-3 > .form-select { |
37 | | - margin-top: auto; |
38 | | -} |
| 40 | + /* 3. .mb-3 also inherits the 3 row tracks via subgrid */ |
| 41 | + .row.fields-aligned-row > .field-wrapper > .mb-3 { |
| 42 | + display: grid; |
| 43 | + grid-template-rows: subgrid; |
| 44 | + grid-row: span 3; |
| 45 | + margin-bottom: 0 !important; /* grid gap handles spacing */ |
| 46 | + } |
39 | 47 |
|
40 | | -/* 5. Help text sits after the input at its natural size */ |
41 | | -.row.fields-aligned-row > [class*="col-"] > .mb-3 > .form-text, |
42 | | -.row.fields-aligned-row > .field-wrapper > .mb-3 > .form-text { |
43 | | - flex-shrink: 0; |
| 48 | + /* 4. Labels sit at the bottom of their row-track so short labels |
| 49 | + align with the bottom of taller (wrapping) labels. */ |
| 50 | + .row.fields-aligned-row > .field-wrapper > .mb-3 > label { |
| 51 | + align-self: end; |
| 52 | + } |
44 | 53 | } |
45 | 54 |
|
46 | 55 | /* ── Consistent field spacing ────────────────────────────────────────── */ |
|
0 commit comments