summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-24 10:04:47 +0300
committerPaul Buetow <paul@buetow.org>2026-06-24 10:04:47 +0300
commitba7ed37f671c92424a3058fb26465652fad3a131 (patch)
tree3d403eae8cb044cd57547837c2582401488287ff
parentf85b0cd77b3b72a487ca4f35a2eac053100dc8e7 (diff)
Make the generated album mobile friendly
Pure CSS/HTML, no JavaScript: - Add a <meta name="viewport"> tag to the two display heads (header.tmpl and splash.tmpl) so phones stop rendering at a zoomed-out desktop width. - Make the overview grid responsive: minmax(min(THUMBHEIGHT, 100%), 1fr) so a column never overflows a narrow screen, plus a max-width:700px media query that shows exactly two square columns on phones (2x2 feature tiles become full-width heroes). aspect-ratio keeps cells square at every width. - Add overflow-x:hidden to body so the slam/glitch entry animations (translateX +/-80vw) cannot make a phone scroll sideways. - Make the menus touch friendly on phones: the navigator/footer/splash links become large rounded buttons (~44px tap targets) and the "|" separators (now wrapped in <span class="nav-sep">) are hidden on mobile while still showing on desktop. - Fix a pre-existing W3C error: the stats filter view-page image was missing an alt attribute (and carried an obsolete border attribute). Verified with headless screenshots at phone width and the W3C Nu HTML checker + CSS validator (zero errors). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-rwxr-xr-xbin/shuriken7
-rw-r--r--share/templates/default/details.tmpl2
-rw-r--r--share/templates/default/header.tmpl53
-rw-r--r--share/templates/default/splash.tmpl1
-rw-r--r--share/templates/default/view.tmpl4
-rw-r--r--src/lib/stats-filter-album.source.sh7
-rwxr-xr-xtests/cli.sh5
7 files changed, 67 insertions, 12 deletions
diff --git a/bin/shuriken b/bin/shuriken
index aad054e..94e38bd 100755
--- a/bin/shuriken
+++ b/bin/shuriken
@@ -4736,7 +4736,8 @@ _stats_build_filterview_body() {
fi
view_page=$(album_view_page_for_photo "$photo")
if [ -n "$view_page" ]; then
- details_link=$(printf ' <a href="%s/%s-details.html">Details</a> |' \
+ details_link=$(printf \
+ ' <a href="%s/%s-details.html">Details</a> <span class="nav-sep">|</span>' \
"$backhref_html" "$view_page")
fi
_stats_print_filterview_body "$backhref_html" "$photo_html" \
@@ -4760,11 +4761,11 @@ _stats_print_filterview_body() {
cat <<END
<div class='view'>
<a href="$next.html">
- <img class='view $animation_class' border='0' src='$backhref_html/$STATS_PHOTOS_DIR/$photo_html'$tooltip_attr />
+ <img class='view $animation_class' alt='$photo_html' src='$backhref_html/$STATS_PHOTOS_DIR/$photo_html'$tooltip_attr />
</a>
<div class="navigator">
<a href="$prev.html" class="arrow">&lArr;</a>
- <a href="index.html">Gallery</a> |$details_link
+ <a href="index.html">Gallery</a> <span class="nav-sep">|</span>$details_link
<a href="$backhref_html/$STATS_PHOTOS_DIR/$photo_html">Direct link</a>
<a href="$next.html" class="arrow">&rArr;</a>
</div>
diff --git a/share/templates/default/details.tmpl b/share/templates/default/details.tmpl
index cd70328..c61aafd 100644
--- a/share/templates/default/details.tmpl
+++ b/share/templates/default/details.tmpl
@@ -13,7 +13,7 @@ cat <<END
</a>
<div class="navigator details-navigator">
<a href="${render_page_num_html}-${render_view_prev_html}-details.html" class="arrow">&lArr;</a>
- <a href="${render_page_num_html}-${render_preview_num_html}.html">Image view</a> |
+ <a href="${render_page_num_html}-${render_preview_num_html}.html">Image view</a> <span class="nav-sep">|</span>
<a href='${render_backhref_html}/${render_photos_dir_html}/${render_photo_html}'>Direct link</a>
<a href="${render_page_num_html}-${render_view_next_html}-details.html" class="arrow">&rArr;</a>
</div>
diff --git a/share/templates/default/header.tmpl b/share/templates/default/header.tmpl
index 2d01e21..d5d1648 100644
--- a/share/templates/default/header.tmpl
+++ b/share/templates/default/header.tmpl
@@ -3,6 +3,7 @@ cat <<END
<html lang="en">
<head>
<meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
<title>${render_title_html}</title>
<link rel="icon" href="${render_backhref_html}/favicon.ico" type="image/x-icon">
<style>
@@ -18,6 +19,9 @@ cat <<END
width, and makes the gap above the header / below the footer the
same 2px as the gaps between the header, grid and footer. */
margin: 0;
+ /* The slam/glitch entry animations translate elements by +/-80vw;
+ clip the horizontal overflow so a phone never scrolls sideways. */
+ overflow-x: hidden;
}
a {
@@ -204,8 +208,11 @@ cat <<END
leave. Spacing comes from the grid gap, so images carry no padding. */
div.thumbs-grid {
display: grid;
+ /* min(THUMBHEIGHT, 100%) keeps a column from ever exceeding the
+ viewport width, so narrow phones never scroll sideways; on wide
+ screens the columns are >= THUMBHEIGHT and grow (1fr) to fill. */
grid-template-columns:
- repeat(auto-fill, minmax(${render_thumbheight_html}px, 1fr));
+ repeat(auto-fill, minmax(min(${render_thumbheight_html}px, 100%), 1fr));
grid-auto-flow: dense;
gap: 10px;
margin: 0 4px;
@@ -377,6 +384,50 @@ cat <<END
width: 95%;
}
}
+
+ /* Phone layout: a 2-column square grid, and the navigator/footer/splash
+ links become large, well-spaced tap targets (~44px). Pure CSS. */
+ @media (max-width: 700px) {
+ div.thumbs-grid {
+ grid-template-columns: 1fr 1fr;
+ gap: 6px;
+ margin: 0 2px;
+ }
+
+ div.navigator {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+ align-items: center;
+ }
+
+ div.navigator a,
+ div.footer a {
+ display: inline-block;
+ padding: 12px 16px;
+ border: 2px solid #ffffff;
+ border-radius: 8px;
+ font-size: 1.1em;
+ text-decoration: none;
+ }
+
+ div.navigator a.arrow {
+ padding: 10px 18px;
+ font-size: 1.4em;
+ }
+
+ /* Hide the "|" separators (wrapped in spans) so the links read as
+ discrete buttons on a phone; they stay visible on desktop. */
+ div.navigator span.nav-sep {
+ display: none;
+ }
+
+ p.enter a {
+ padding: 14px 24px;
+ font-size: 1.3em;
+ }
+ }
</style>
</head>
diff --git a/share/templates/default/splash.tmpl b/share/templates/default/splash.tmpl
index de5837a..8937fc2 100644
--- a/share/templates/default/splash.tmpl
+++ b/share/templates/default/splash.tmpl
@@ -3,6 +3,7 @@ cat <<END
<html lang="en">
<head>
<meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
<title>${render_title_html}</title>
<link rel="icon" href="${render_backhref_html}/favicon.ico" type="image/x-icon">
<style>
diff --git a/share/templates/default/view.tmpl b/share/templates/default/view.tmpl
index b1e6c79..c28859b 100644
--- a/share/templates/default/view.tmpl
+++ b/share/templates/default/view.tmpl
@@ -13,8 +13,8 @@ cat <<END
</a>
<div class="navigator">
<a href="${render_page_num_html}-${render_view_prev_html}.html" class="arrow">&lArr;</a>
- <a href="page-${render_page_num_html}.html#${render_photo_html}">Thumbnails</a> |
- <a href="${render_page_num_html}-${render_preview_num_html}-details.html">Details</a> |
+ <a href="page-${render_page_num_html}.html#${render_photo_html}">Thumbnails</a> <span class="nav-sep">|</span>
+ <a href="${render_page_num_html}-${render_preview_num_html}-details.html">Details</a> <span class="nav-sep">|</span>
<a href='${render_backhref_html}/${render_photos_dir_html}/${render_photo_html}'>Direct link</a>
<a href="${render_page_num_html}-${render_view_next_html}.html" class="arrow">&rArr;</a>
</div>
diff --git a/src/lib/stats-filter-album.source.sh b/src/lib/stats-filter-album.source.sh
index eedb474..c1c1e1c 100644
--- a/src/lib/stats-filter-album.source.sh
+++ b/src/lib/stats-filter-album.source.sh
@@ -154,7 +154,8 @@ _stats_build_filterview_body() {
fi
view_page=$(album_view_page_for_photo "$photo")
if [ -n "$view_page" ]; then
- details_link=$(printf ' <a href="%s/%s-details.html">Details</a> |' \
+ details_link=$(printf \
+ ' <a href="%s/%s-details.html">Details</a> <span class="nav-sep">|</span>' \
"$backhref_html" "$view_page")
fi
_stats_print_filterview_body "$backhref_html" "$photo_html" \
@@ -178,11 +179,11 @@ _stats_print_filterview_body() {
cat <<END
<div class='view'>
<a href="$next.html">
- <img class='view $animation_class' border='0' src='$backhref_html/$STATS_PHOTOS_DIR/$photo_html'$tooltip_attr />
+ <img class='view $animation_class' alt='$photo_html' src='$backhref_html/$STATS_PHOTOS_DIR/$photo_html'$tooltip_attr />
</a>
<div class="navigator">
<a href="$prev.html" class="arrow">&lArr;</a>
- <a href="index.html">Gallery</a> |$details_link
+ <a href="index.html">Gallery</a> <span class="nav-sep">|</span>$details_link
<a href="$backhref_html/$STATS_PHOTOS_DIR/$photo_html">Direct link</a>
<a href="$next.html" class="arrow">&rArr;</a>
</div>
diff --git a/tests/cli.sh b/tests/cli.sh
index 6dfac0a..2c784bc 100755
--- a/tests/cli.sh
+++ b/tests/cli.sh
@@ -515,8 +515,9 @@ test_generate_cli_overrides_config_values() {
test::assert_path_absent "$TEST_TMPDIR/config-dist"
test::assert_find_count 0 "$TEST_TMPDIR/cli-dist" '*.tar'
test::assert_contains '<title>CLI title</title>' "$page_html"
- # THUMBHEIGHT is the grid's minimum cell width (columns grow to fill).
- test::assert_contains 'minmax(45px, 1fr)' "$page_html"
+ # THUMBHEIGHT is the grid's minimum cell width (columns grow to fill); it is
+ # wrapped in min(...,100%) so a column never overflows a narrow phone.
+ test::assert_contains 'minmax(min(45px, 100%), 1fr)' "$page_html"
test::assert_contains 'max-height: 456px;' "$view_html"
test::assert_contains 'Next 1 pictures' "$page_html"
test::assert_contains 'href="page-2.html" class="arrow">&rArr;</a>' \