Simplify image/figure styling: markdown always renders standalone images as figures
Standalone markdown images (captioned or not) now become block <figure> elements; only inline-with-text images and raw author <img> HTML stay plain. This collapses the img/figure selector duplication in pagerite.css into a default + override structure: figure fills the column, floats go 30% (1em text gap), an explicit width attribute shrink-wraps the figure (images with width are left untouched by CSS so the attribute hint survives), and .wide re-anchors are grouped with the main rule.
This commit is contained in:
@@ -609,40 +609,57 @@ td {
|
||||
padding: 0.35rem 0.8rem;
|
||||
}
|
||||
|
||||
/* Images and figures */
|
||||
/* Images and figures
|
||||
|
||||
Markdown images standing alone in a paragraph render as a block
|
||||
<figure> (with <figcaption> when the image has a title); the
|
||||
brace-attribute positioning class ({.left}, {.right}, {.wide}) lives
|
||||
on the img inside, but only the figure is ever positioned, so the
|
||||
caption stays below the image. Raw <img> HTML written by the author
|
||||
stays inline and unstyled beyond these defaults. */
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Figures are block containers filling the column; the image fills the
|
||||
figure. The auto inline margins only take effect once a rule below
|
||||
shrinks the width (centering the figure); at 100% they compute to 0. */
|
||||
figure {
|
||||
margin: 0 0 1.5rem;
|
||||
margin: 0 auto 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
/* The image fills the figure, except when it carries an explicit width
|
||||
attribute — that width is a browser presentational hint which CSS
|
||||
cannot restore once overridden, so such images are simply left alone. */
|
||||
figure img:not([width]) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Captions of full-bleed images: centered and kept to a readable width. */
|
||||
figure:has(.wide) figcaption {
|
||||
max-width: 65ch;
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Positioning via brace-attribute classes: {.right}, {.left}, {.wide} */
|
||||
figure:has(.right),
|
||||
img.right {
|
||||
/* Floated figures: {.right} / {.left}, defaulting to 30% of the column
|
||||
and capped at half of it. */
|
||||
figure:has(.right) {
|
||||
float: right;
|
||||
margin: 0.3rem 0 1rem 1.5rem;
|
||||
width: 30%;
|
||||
max-width: 50%;
|
||||
margin: 0.3rem 0 1rem 1em;
|
||||
}
|
||||
|
||||
figure:has(.left),
|
||||
img.left {
|
||||
figure:has(.left) {
|
||||
float: left;
|
||||
margin: 0.3rem 1.5rem 1rem 0;
|
||||
width: 30%;
|
||||
max-width: 50%;
|
||||
margin: 0.3rem 1em 1rem 0;
|
||||
}
|
||||
|
||||
/* An image with an explicit width attribute shrink-wraps instead: the
|
||||
figure fits the image and, per the auto inline margins above, centers
|
||||
in the column. Placed after the percentage widths above so it
|
||||
overrides them at equal specificity. */
|
||||
figure:has(img[width]) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
/* .wide is full bleed: edge to edge of the viewport (or of the space right
|
||||
@@ -651,52 +668,81 @@ img.left {
|
||||
symmetric margins of (50% of the column − 50% of the target width) break
|
||||
out of the column and center the element on the same center — making the
|
||||
left edge land exactly at the viewport's edge (or the editor's right
|
||||
border). The sidebar stacks above it (z-index + translucent blur). */
|
||||
figure:has(.wide),
|
||||
img.wide {
|
||||
display: block;
|
||||
/* no inline strut/descender gaps around the image */
|
||||
border). The sidebar stacks above it (z-index + translucent blur).
|
||||
|
||||
The rules below re-anchor the bleed for the layouts where the article
|
||||
is not viewport-centered; each just overrides width/margin-inline, and
|
||||
later rules win at equal specificity. */
|
||||
figure:has(.wide) {
|
||||
width: 100vw;
|
||||
max-width: none;
|
||||
margin-inline: calc(50% - 50vw);
|
||||
/* negative margins also kill the UA figure margin */
|
||||
/* Follow the docked editor's margin-left transition smoothly. */
|
||||
transition: margin-left 0.25s ease;
|
||||
}
|
||||
|
||||
/* A paragraph wrapping only a wide image must not add its line height. */
|
||||
p:has(> img.wide:only-child) {
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
/* A captioned image is a <figure>, and the positioning class lives on the
|
||||
img inside it: only the figure may float/shift, never the img itself,
|
||||
or the caption would wrap beside the image instead of sitting below.
|
||||
The image fills the figure's width. */
|
||||
figure:has(.right) img,
|
||||
figure:has(.left) img {
|
||||
float: none;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Full bleed means edge to edge — no rounded corners. */
|
||||
figure:has(.wide) img {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* Floats take a fixed share of the text column rather than sizing by the
|
||||
image's intrinsic width, which varies wildly (SVGs have none, and
|
||||
min-content collapses them). A percentage also scales correctly inside
|
||||
multi-column segments, where the column is the containing block. The
|
||||
caption wraps within that width. A width attribute ({.right width=300})
|
||||
overrides the default on uncaptioned images. */
|
||||
figure:has(.right),
|
||||
figure:has(.left),
|
||||
img.right:not([width]),
|
||||
img.left:not([width]) {
|
||||
width: 30%;
|
||||
/* .wide on multicol pages: the article is not viewport-centered (no right
|
||||
gutter), so the bleed anchors at the left gutter — the 1fr share of the
|
||||
1fr + 4fr grid, i.e. 20vw — plus main's padding, and spans on to the
|
||||
right viewport edge. */
|
||||
body:has(.multicol) figure:has(.wide) {
|
||||
margin-inline: calc(-20vw - 1.25rem) 0;
|
||||
}
|
||||
|
||||
/* Editing: shrink the bleed to the space right of the docked editor. */
|
||||
body.editing figure:has(.wide) {
|
||||
width: calc(100vw - var(--editor-w));
|
||||
margin-inline: calc(50% - (100vw - var(--editor-w)) / 2);
|
||||
}
|
||||
|
||||
/* Editing + multicol: the left gutter is 1/5 of the space right of the
|
||||
editor, and the bleed also crosses #content's 1rem editing gap plus
|
||||
main's 1.25rem left padding (the gutter shrink from the padding roughly
|
||||
cancels the rounding): −2rem in total. */
|
||||
body.editing:has(.multicol) figure:has(.wide) {
|
||||
margin-inline: calc((100vw - var(--editor-w)) / -5 - 2rem) 0;
|
||||
}
|
||||
|
||||
/* Narrow windows with a sidebar: below 102rem the symmetric gutters can no
|
||||
longer both hold the 12rem sidebar, so #content reserves it with a fixed
|
||||
left track (see the matching media query below) and the article always
|
||||
starts at 12rem (+ main's 1.25rem padding) — the bleed margin is a plain
|
||||
constant. Scoped by :has(#sidebar) since the sidebar element is omitted
|
||||
entirely on pages without sub-navigation, and excluded while editing,
|
||||
where the editing rules above apply instead. */
|
||||
@media (max-width: 102rem) {
|
||||
body:has(#sidebar):not(.editing) figure:has(.wide) {
|
||||
margin-inline: -13.25rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: var(--muted);
|
||||
line-height: 1;
|
||||
font-size: 0.85rem;
|
||||
hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
text-wrap: pretty;
|
||||
text-align: left;
|
||||
/* Never let a long caption stretch a shrink-to-fit figure wider than the
|
||||
image; the caption wraps at the figure's width instead. */
|
||||
width: 0;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
/* Full-bleed figures: center the caption, shrink-wrapped to its text and
|
||||
capped at a readable width. The min-width shrink-wrap trick above would
|
||||
win over max-width (min beats max per spec), so it is reset here. */
|
||||
figure:has(.wide) figcaption {
|
||||
width: fit-content;
|
||||
min-width: 0;
|
||||
max-width: 65ch;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* Section headings start below any floated figures of the previous
|
||||
@@ -709,9 +755,10 @@ article h2 {
|
||||
/* Narrow windows with a sidebar: below 102rem the symmetric gutters can no
|
||||
longer both hold the 12rem sidebar, so reserve its space with a fixed
|
||||
left track instead of letting it overlap the article. The article then
|
||||
always starts at 12rem (+ main's 1.25rem padding), so the .wide breakout
|
||||
margin is a plain constant. Scoped by :has(#sidebar) since the sidebar
|
||||
element is omitted entirely on pages without sub-navigation. */
|
||||
always starts at 12rem (+ main's 1.25rem padding), which the matching
|
||||
.wide breakout rule in the images section relies on. Scoped by
|
||||
:has(#sidebar) since the sidebar element is omitted entirely on pages
|
||||
without sub-navigation. */
|
||||
@media (max-width: 102rem) {
|
||||
body:has(#sidebar):not(.editing) #content {
|
||||
grid-template-columns: 12rem minmax(0, 78rem) minmax(0, 1fr);
|
||||
@@ -720,40 +767,10 @@ article h2 {
|
||||
/* Long articles stay fluid here too: same 12rem reservation for the
|
||||
sidebar, then the article takes everything to the right viewport
|
||||
edge. The article's left edge stays at 12rem either way, so the
|
||||
constant .wide breakout margin below remains correct. */
|
||||
constant .wide breakout margin remains correct. */
|
||||
body:has(#sidebar):has(.multicol):not(.editing) #content {
|
||||
grid-template-columns: 12rem minmax(0, 1fr);
|
||||
}
|
||||
|
||||
body:has(#sidebar) figure:has(.wide),
|
||||
body:has(#sidebar) img.wide:not(figure img) {
|
||||
margin-inline: -13.25rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* .wide on multicol pages: the article is not viewport-centered (no right
|
||||
gutter), so the bleed anchors at the left gutter — the 1fr share of the
|
||||
1fr + 4fr grid, i.e. 20vw — plus main's padding, and spans on to the
|
||||
right viewport edge. Loses to the sidebar rule above (id in :has) and to
|
||||
the editing rules below (same specificity, later in the file). */
|
||||
body:has(.multicol) figure:has(.wide),
|
||||
body:has(.multicol) img.wide:not(figure img) {
|
||||
margin-inline: calc(-20vw - 1.25rem) 0;
|
||||
}
|
||||
|
||||
/* Editing: shrink the bleed to the space right of the docked editor. */
|
||||
body.editing figure:has(.wide),
|
||||
body.editing img.wide:not(figure img) {
|
||||
width: calc(100vw - var(--editor-w));
|
||||
margin-inline: calc(50% - (100vw - var(--editor-w)) / 2);
|
||||
}
|
||||
|
||||
/* Editing + multicol: the left gutter is 1/5 of the space right of the
|
||||
editor. */
|
||||
body.editing:has(.multicol) figure:has(.wide),
|
||||
body.editing:has(.multicol) img.wide:not(figure img) {
|
||||
width: calc(100vw - var(--editor-w));
|
||||
margin-inline: calc((100vw - var(--editor-w)) / -5 - 1.25rem) 0;
|
||||
}
|
||||
|
||||
/* Scroll reveal (pagerite.js adds .reveal/.in; JS off = fully visible) */
|
||||
|
||||
Reference in New Issue
Block a user