From 30a3bb7854e5ece9db515eb3e1ef8e53bf4f4100 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Thu, 25 Dec 2025 15:36:55 -0500 Subject: [PATCH] Improve mobile experience --- script.js | 24 +++++++++++++- style.css | 98 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/script.js b/script.js index a06b075..b472a25 100644 --- a/script.js +++ b/script.js @@ -316,10 +316,32 @@ document.body.appendChild(tocToggle); const toc = document.querySelector(".toc"); const layout = document.querySelector(".layout"); +const isMobile = () => window.matchMedia("(max-width: 700px)").matches; + tocToggle.addEventListener("click", () => { toc?.classList.toggle("collapsed"); layout?.classList.toggle("toc-hidden"); - document.body.classList.toggle("toc-collapsed"); + if (isMobile()) { + document.body.classList.toggle("toc-open"); + } else { + document.body.classList.toggle("toc-collapsed"); + } +}); + +// auto-collapse on mobile (CSS defaults to collapsed, just ensure classes match) +if (isMobile()) { + toc?.classList.add("collapsed"); + layout?.classList.add("toc-hidden"); + document.body.classList.remove("toc-open"); +} + +// close drawer when clicking a toc link on mobile +tocList?.addEventListener("click", (e) => { + if (e.target.tagName === "A" && isMobile()) { + toc?.classList.add("collapsed"); + layout?.classList.add("toc-hidden"); + document.body.classList.remove("toc-open"); + } }); // scroll TOC item into view when navigating via hash diff --git a/style.css b/style.css index f72a69b..3d1e16c 100644 --- a/style.css +++ b/style.css @@ -14,8 +14,13 @@ box-sizing: border-box; } +html { + max-width: 100%; +} + body { margin: 0; + max-width: 100%; color: var(--ink); background: radial-gradient( @@ -40,7 +45,7 @@ body { } .hero { - padding: 48px 6vw 32px; + padding: clamp(24px, 6vw, 48px) clamp(16px, 6vw, 6vw) clamp(16px, 4vw, 32px); background: linear-gradient(120deg, rgba(182, 82, 47, 0.12), transparent 55%), linear-gradient(220deg, rgba(122, 46, 26, 0.18), transparent 45%); @@ -51,7 +56,7 @@ body { .hero h1 { font-family: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Garamond, serif; - font-size: clamp(2.4rem, 4vw, 3.6rem); + font-size: clamp(1.5rem, 6vw, 3.6rem); letter-spacing: 0.02em; margin: 0 0 8px; } @@ -65,15 +70,15 @@ body { .layout { display: grid; - grid-template-columns: minmax(240px, 320px) minmax(0, 1fr); - gap: 28px; - padding: 32px 6vw 64px; + grid-template-columns: minmax(200px, 280px) minmax(0, 1fr); + gap: clamp(16px, 4vw, 28px); + padding: clamp(16px, 4vw, 32px) clamp(12px, 6vw, 6vw) clamp(32px, 8vw, 64px); } .toc { background: var(--nav-bg); border-radius: 18px; - padding: 24px; + padding: clamp(16px, 4vw, 24px); box-shadow: 0 18px 40px var(--shadow); position: sticky; top: 24px; @@ -102,7 +107,7 @@ body { .toc-letters { display: grid; - grid-template-columns: repeat(9, 1fr); + grid-template-columns: repeat(auto-fill, minmax(28px, 1fr)); gap: 6px; margin-bottom: 16px; } @@ -148,10 +153,13 @@ body { .content { background: rgba(255, 255, 255, 0.6); - border-radius: 24px; - padding: 32px 36px; + border-radius: clamp(12px, 3vw, 24px); + padding: clamp(16px, 4vw, 32px) clamp(16px, 5vw, 36px); box-shadow: 0 20px 55px var(--shadow); animation: fade-up 0.8s ease 0.2s both; + overflow-wrap: break-word; + word-wrap: break-word; + min-width: 0; } .content h2, @@ -258,41 +266,69 @@ body.toc-collapsed .toc-toggle::before { grid-template-columns: 0 minmax(0, 1fr); } -@media (max-width: 980px) { - .layout { - grid-template-columns: 1fr; +@media (max-width: 700px) { + .page, + .hero, + .content { + max-width: 100%; } .toc { - position: relative; - max-height: none; + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: min(85vw, 320px); + max-height: 100vh; + border-radius: 0 18px 18px 0; + z-index: 200; + margin-left: 0; + transform: translateX(-100%); + transition: transform 0.3s ease, opacity 0.3s ease; + } + + .toc:not(.collapsed) { + transform: translateX(0); + opacity: 1; + pointer-events: auto; } .toc.collapsed { - margin-left: 0; - margin-top: -100%; - height: 0; - padding: 0; - overflow: hidden; - } - - .layout.toc-hidden { - grid-template-columns: 1fr; + opacity: 0; + pointer-events: none; } .toc-toggle { - top: auto; - bottom: 20px; - left: 20px; - transform: none; - border-radius: 8px; + top: 50%; + bottom: auto; + transform: translateY(-50%); + z-index: 201; + transition: left 0.3s ease; + padding: 10px 6px; + font-size: 1rem; + left: 0; + } + + body.toc-open .toc-toggle { + left: min(85vw, 320px); } .toc-toggle::before { - content: "▲"; + content: "▶"; } - body.toc-collapsed .toc-toggle::before { - content: "▼"; + body.toc-open .toc-toggle::before { + content: "◀"; + } + + .layout, + .layout.toc-hidden { + display: block; + grid-template-columns: none; + max-width: 100%; + } + + .content { + border-radius: clamp(8px, 2vw, 16px); } }