From e6c472ca7a60f2ee25ce6c7e2fea3a67cb663f65 Mon Sep 17 00:00:00 2001 From: spleenftw Date: Fri, 10 Jul 2026 14:40:50 +0200 Subject: [PATCH] v1.7.0: readability & UX pass --- README.md | 4 +++- css/style.css | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ metadata.json | 2 +- php/home.php | 18 ++++++++++++++++- php/icons.php | 22 ++++++++++++++++++++ php/page.php | 6 +++++- 6 files changed, 104 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9c07e8d..93ba9a0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ A clean, minimal theme for [Bludit](https://www.bludit.com) inspired by the - **Keyboard shortcuts** — `/` (search), `g h` (go home), `t` (back to top), `Esc` (close overlay). - **Randomized navigation** — the Navigation/Pages plugin list is shuffled on every load. - **Reading time & dates** shown on the post list and single posts. -- **Post-list excerpts** — the page description renders as a 2-line excerpt; tags are capped at 5 with a `+N` badge. +- **Post-list excerpts & thumbnails** — the page description renders as a 2-line excerpt with the cover image as a right-side thumbnail; tags are capped at 5 with a `+N` badge. - **Older / newer post navigation** — chronological links under every article, above the related posts. - **Social icons** in the navbar and hero (SVG files in `img/`). - **Tags & categories** rendered as pill badges. @@ -29,6 +29,8 @@ A clean, minimal theme for [Bludit](https://www.bludit.com) inspired by the - **SEO** — Open Graph, Twitter Card, JSON-LD (WebSite, Article, BreadcrumbList, sameAs), canonical URL, theme-color meta, cover-image preload. Duplicate OG/Twitter/canonical tags emitted by Bludit plugins are stripped automatically. - **Accessibility** — skip link, ARIA labels, `:focus-visible`, heading anchor links, print stylesheet. - **PWA** — web app manifest included. +- **CLS-free images** — `width`/`height` are injected server-side into local-upload images (plus lazy-loading and async decode). +- **View transitions** — smooth cross-document fade on supporting browsers; respects `prefers-reduced-motion`. - Fully responsive; no jQuery, no Bootstrap JS, no webfont requests. ## Installation diff --git a/css/style.css b/css/style.css index 5ff9307..c373a2d 100644 --- a/css/style.css +++ b/css/style.css @@ -244,6 +244,24 @@ --social-icon-filter: brightness(0) invert(1); } +/* ======================================== + VIEW TRANSITIONS (cross-document) + Smooth fade between page navigations on supporting browsers + (Chrome/Edge 126+); silently ignored elsewhere. Disabled for + users who prefer reduced motion. + ======================================== */ +@view-transition { + navigation: auto; +} + +@media (prefers-reduced-motion: reduce) { + ::view-transition-group(*), + ::view-transition-old(*), + ::view-transition-new(*) { + animation: none !important; + } +} + /* ======================================== BASE ======================================== */ @@ -896,6 +914,44 @@ img.nav-svg-icon { margin-top: var(--space-sm); } +/* Cover thumbnail: text left, image right (Blowfish-style) */ +.post-list-row { + display: flex; + gap: var(--space-md); + align-items: flex-start; +} + +.post-list-main { + flex: 1 1 auto; + min-width: 0; /* allow long titles/URLs to wrap instead of pushing the thumb */ +} + +.post-list-thumb { + flex: 0 0 auto; + display: block; +} + +.post-list-thumb img { + width: 168px; + height: 112px; + object-fit: cover; + border-radius: var(--radius-md); + border: 1px solid var(--border-subtle); + background: var(--bg-subtle); + transition: transform 0.2s ease; +} + +.post-list-thumb:hover img { + transform: scale(1.03); +} + +@media (max-width: 575.98px) { + .post-list-thumb img { + width: 96px; + height: 72px; + } +} + /* "+N" overflow badge — muted, links to the post (where all tags are shown) */ .taxonomy-badge-more { color: var(--text-muted); diff --git a/metadata.json b/metadata.json index 0f5a64f..4d834a6 100644 --- a/metadata.json +++ b/metadata.json @@ -6,5 +6,5 @@ "releaseDate": "2026-07-10", "license": "MIT", "compatible": "3.22.0", - "notes": "A Bludit theme inspired by the Blowfish Hugo theme. Five-theme swatch picker (Light/Dark/Nord/Dracula/Catppuccin), sticky ToC sidebar on articles, image lightbox with zoom, image carousel (```carousel fence), tabbed code blocks (```tabs fence), smart sidebar per page type, and clean responsive typography. v1.3.0: SEO (Open Graph, Twitter Card, JSON-LD, theme-color, cover preload), per-theme syntax highlighting (self-hosted highlight.js), copy-to-clipboard on code blocks, numbered pagination, inline-SVG icons (dropped the Bootstrap Icons webfont), removed jQuery/Bootstrap JS, deferred cached JS bundle, reading progress bar, back-to-top, randomised sidebar selection, lazy-loaded images, accessibility (skip link, ARIA, :focus-visible) and a print stylesheet. v1.4.0: canonical URL, WebSite + BreadcrumbList + author sameAs JSON-LD, og:image:alt / twitter:site+creator, cover-image aspect-ratio (CLS), heading anchor links, prev/next article nav, related posts, share buttons (X/LinkedIn/copy-link), mailto social icon, PWA web app manifest, 'updated on' date, and outbound-link hardening (noopener noreferrer). v1.5.0: callout/admonition boxes (> [!NOTE]/[!TIP]/[!WARNING]/...), code-block header bar with language label + copy button, visual breadcrumbs, custom 404 page, image figure/figcaption from the markdown title, a mobile table-of-contents drawer, and third-party resource hints. v1.6.0: self-hosted Inter (no Google Fonts), client-side search overlay (\"/\" key + navbar button), keyboard shortcuts (/ , g h, t, Esc), a tabbed-code copy button, series navigation (series-* tag), and content typography (keycaps, task-list checkboxes, , external-link icon, footnote/definition-list styling). the navbar search icon only appears once the on-page search box scrolls out of view, and code blocks use a header bar (language + copy) with tighter line-height. v1.7.0: readability pass - underlined in-content links, justified paragraphs with auto-hyphenation (left-aligned on mobile), post-list excerpts from the page description with a 5-tag cap (+N badge), older/newer post navigation under articles, and de-duplication of Open Graph / Twitter Card / canonical tags emitted by plugins." + "notes": "A Bludit theme inspired by the Blowfish Hugo theme. Five-theme swatch picker (Light/Dark/Nord/Dracula/Catppuccin), sticky ToC sidebar on articles, image lightbox with zoom, image carousel (```carousel fence), tabbed code blocks (```tabs fence), smart sidebar per page type, and clean responsive typography. v1.3.0: SEO (Open Graph, Twitter Card, JSON-LD, theme-color, cover preload), per-theme syntax highlighting (self-hosted highlight.js), copy-to-clipboard on code blocks, numbered pagination, inline-SVG icons (dropped the Bootstrap Icons webfont), removed jQuery/Bootstrap JS, deferred cached JS bundle, reading progress bar, back-to-top, randomised sidebar selection, lazy-loaded images, accessibility (skip link, ARIA, :focus-visible) and a print stylesheet. v1.4.0: canonical URL, WebSite + BreadcrumbList + author sameAs JSON-LD, og:image:alt / twitter:site+creator, cover-image aspect-ratio (CLS), heading anchor links, prev/next article nav, related posts, share buttons (X/LinkedIn/copy-link), mailto social icon, PWA web app manifest, 'updated on' date, and outbound-link hardening (noopener noreferrer). v1.5.0: callout/admonition boxes (> [!NOTE]/[!TIP]/[!WARNING]/...), code-block header bar with language label + copy button, visual breadcrumbs, custom 404 page, image figure/figcaption from the markdown title, a mobile table-of-contents drawer, and third-party resource hints. v1.6.0: self-hosted Inter (no Google Fonts), client-side search overlay (\"/\" key + navbar button), keyboard shortcuts (/ , g h, t, Esc), a tabbed-code copy button, series navigation (series-* tag), and content typography (keycaps, task-list checkboxes, , external-link icon, footnote/definition-list styling). the navbar search icon only appears once the on-page search box scrolls out of view, and code blocks use a header bar (language + copy) with tighter line-height. v1.7.0: readability pass - underlined in-content links, justified paragraphs with auto-hyphenation (left-aligned on mobile), post-list excerpts from the page description with a 5-tag cap (+N badge), older/newer post navigation under articles, de-duplication of Open Graph / Twitter Card / canonical tags emitted by plugins, cover thumbnails on the post list, server-side width/height injection on content images (CLS), and cross-document view transitions." } diff --git a/php/home.php b/php/home.php index b05b234..6f03e1d 100644 --- a/php/home.php +++ b/php/home.php @@ -52,11 +52,16 @@
-
+ coverImage(); ?> +
+
+ +
+

title()); ?>

@@ -101,6 +106,17 @@
+
+ + + + + + +
+ diff --git a/php/icons.php b/php/icons.php index 862064d..33e9a04 100644 --- a/php/icons.php +++ b/php/icons.php @@ -55,6 +55,28 @@ if (!function_exists('blowfish_icon')) { return DOMAIN_THEME . $rel . ($v ? '?v=' . $v : ''); } + // Inject width/height attributes into local-upload tags that lack + // them, so the browser reserves the box before the image loads (no CLS). + // Only touches images served from this site's uploads folder; remote + // images and tags that already declare a width are left alone. + function blowfish_img_dimensions($html) { + if (!defined('DOMAIN_UPLOADS') || !defined('PATH_UPLOADS')) { return $html; } + return preg_replace_callback('/]*>/i', function ($m) { + $tag = $m[0]; + if (preg_match('/\b(?:width|height)\s*=/i', $tag)) { return $tag; } + if (!preg_match('/\bsrc=["\']([^"\']+)["\']/i', $tag, $src)) { return $tag; } + $url = html_entity_decode($src[1], ENT_QUOTES, 'UTF-8'); + if (strpos($url, DOMAIN_UPLOADS) !== 0) { return $tag; } + $rel = rawurldecode(substr($url, strlen(DOMAIN_UPLOADS))); + if ($rel === '' || strpos($rel, '..') !== false) { return $tag; } + $file = PATH_UPLOADS . $rel; + if (!is_file($file)) { return $tag; } + $size = @getimagesize($file); + if (!$size || empty($size[0]) || empty($size[1])) { return $tag; } + return preg_replace('/) are untouched. - echo preg_replace( + $bdContent = preg_replace( '/]*\bloading=)/i', 'content() ); + // Add width/height to local-upload images so the layout doesn't + // shift as they load (CLS). CSS `img { height: auto }` keeps the + // aspect ratio responsive. + echo blowfish_img_dimensions($bdContent); ?>