diff --git a/frontend/src/lib/markdown.ts b/frontend/src/lib/markdown.ts index 2258e3e..75111bd 100644 --- a/frontend/src/lib/markdown.ts +++ b/frontend/src/lib/markdown.ts @@ -119,7 +119,16 @@ function groupFigures(html: string): string { const m = fig.match(/]*\swidth="(\d+)"[^>]*\sheight="(\d+)"/); const ratio = m ? Number(m[1]) / Number(m[2]) : 1; const safe = Number.isFinite(ratio) && ratio > 0 ? ratio : 1; - return fig.replace('
', `
`); + const r = safe.toFixed(3); + // flex-basis tracks target row height (var --row-h) × aspect ratio, + // so the browser fits as many figures per row as it can while keeping + // each at roughly the target height; the rest wrap. max-width caps + // any leftover row so a lone last image doesn't balloon. + const style = [ + `flex:${r} ${r} calc(${r} * var(--row-h, 16rem))`, + `max-width:calc(${r} * var(--row-max, 30rem))`, + ].join(';'); + return fig.replace('
', `
`); }); return `
${items.join('')}
`; }, diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index e9c1d9a..651e424 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -548,6 +548,11 @@ code, pre, kbd, samp { * row; each figure gets `flex: ` inline so widths divide * proportionally and heights line up. Wraps to a column on narrow screens. */ .prose .figure-row { + /* Target row height. Each figure's flex-basis is ratio × this value, so + * rows pack as many figures as fit at roughly --row-h tall, then wrap. + * --row-max caps how tall a sparsely-filled final row can grow. */ + --row-h: 16rem; + --row-max: 30rem; display: flex; flex-wrap: wrap; gap: 0.9rem; @@ -557,6 +562,12 @@ code, pre, kbd, samp { width: calc(100% + min(8vw, 4rem)); margin-left: calc(min(8vw, 4rem) / -2); } +@media (min-width: 1024px) { + .prose .figure-row { + --row-h: 18rem; + --row-max: 34rem; + } +} .prose .figure-row figure { margin: 0; min-width: 0; /* allow flex children to shrink below content width */