ui: App-Rahmen-Layout auf allen Seiten (Header/Footer fix, main scrollt intern)

Statt Seiten-Scroll jetzt überall der Journal-„Rahmen": body height:100dvh +
overflow:hidden, Header oben / Footer unten fix, main scrollt INTERN mit
verstecktem Scrollbalken. Dadurch:
- keine Seiten-Scrollbar → Header/Footer reichen schwarz bis an den rechten Rand
  (kein weißer scrollbar-gutter-Streifen mehr)
- Footer immer unten, Inhalt im Rahmen dazwischen
- nichts hat sichtbare Scrollbalken

Inhalt 72ch-zentriert in der vollbreiten Scroll-Fläche; Hero-Bild füllt die
volle Breite (kein 100vw-Hack mehr); Breadcrumb wandert in main (scrollt mit).
Mobil: normaler Seiten-Scroll (kein 100dvh-Rahmen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 05:36:45 +02:00
parent 309d12f8a2
commit af587af851
2 changed files with 41 additions and 31 deletions
+33 -25
View File
@@ -82,7 +82,9 @@
/* Scrollbalken-Platz auf der Wurzel reservieren UND horizontalen Überlauf hier
kappen → Inhaltsbreite identisch auf ALLEN Seiten (auch Home ohne Scrollbar),
damit das zentrierte Logo/Menü nirgends springt. */
html { margin: 0; overflow-x: hidden; scrollbar-gutter: stable; }
/* Kein Seiten-Scroll, kein Scrollbalken-Gutter → Header/Footer reichen bis ganz
an den rechten Rand (schwarz bis zur Kante). Gescrollt wird nur main intern. */
html { margin: 0; overflow: hidden; }
body {
font-family: var(--font-family-serif);
@@ -90,25 +92,35 @@ body {
line-height: 1.55;
padding: 0;
margin: 0;
/* Flex-Spalte → STICKY FOOTER auf allen Seiten: main wächst (flex:1), Footer
behält Inhaltshöhe und klebt unten. (overflow-x + scrollbar-gutter: html.) */
min-height: 100dvh;
/* App-Rahmen auf ALLEN Seiten: feste Höhe, Seite scrollt nicht — Header oben,
Footer unten, der Inhalt (main) scrollt INTERN mit verstecktem Scrollbalken. */
height: 100dvh;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Inhaltsspalte zentrieren = 72ch + 1.75rem Gutter (Home ist Vollbreite).
Header/Footer bleiben volle Breite (eigenes inneres Raster zentriert sie). */
body:not(.is-home) > main,
body:not(.is-home) > .page-foot-nav {
width: 100%;
body > header.site-header,
body > footer { flex: none; }
body > main {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
scrollbar-width: none; /* Scrollbalken aus (kein weißer Streifen) */
-ms-overflow-style: none;
}
body > main::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* Inhalt 72ch-zentriert in der vollbreiten Scroll-Fläche (Home = Vollbreite). */
body:not(.is-home) > main > * {
max-width: calc(var(--container-width) + 3.5rem);
margin-inline: auto;
padding-inline: 1.75rem;
}
body:not(.is-home) > main { flex: 1 0 auto; } /* füllt → Footer unten */
body:not(.is-home) > header.site-header,
body:not(.is-home) > .page-foot-nav,
body:not(.is-home) > footer { flex: none; }
/* Full-Bleed-Hero füllt die ganze Breite (main ist schon viewportbreit). */
body:not(.is-home) > main > .single-hero-image {
max-width: none;
margin-inline: 0;
padding-inline: 0;
}
p { margin: var(--spacing-sm) 0; }
@@ -380,7 +392,10 @@ body.is-home > footer { margin-top: 0; padding: 0.55rem 0; }
body.is-home > footer .footer-grid { row-gap: 0.2rem; }
@media (max-width: 720px) {
/* Mobil: kein Full-Height-Zwang — normal scrollen, eine Spalte. */
/* Mobil: kein Full-Height-Rahmen — normale Seite scrollt, kein interner Scroll. */
html { overflow: visible; }
body { height: auto; min-height: 100dvh; overflow: visible; }
body > main { overflow: visible; }
body.is-home { height: auto; overflow: visible; }
body.is-home > main { display: block; overflow: visible; }
body.is-home .journal { display: block; }
@@ -1122,22 +1137,15 @@ a.byline-author:hover, a.journal-author:hover { color: var(--accent); }
------------------------------------------------------------------------ */
.single { margin-top: var(--spacing-md); }
.single-header { margin-bottom: var(--spacing-md); }
/* Single article — full-bleed cover image directly under the masthead.
width:100vw breaks the boxed column horizontally; negative top margin
cancels the body grid gap + header margin so the image sits flush. */
/* Cover-Bild füllt die volle Breite des Scroll-Rahmens, bündig unter dem Header. */
.single-hero-image {
display: block;
width: 100vw;
max-width: 100vw;
width: 100%;
max-width: 100%;
height: auto;
max-height: 60vh;
object-fit: cover;
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
/* bündig direkt unter die Masthead (kein Überlappen) — gleicht nur den
Body-Grid-Gap aus, nicht mehr (sonst rutscht das Bild über den Header). */
margin-top: calc(-1 * var(--spacing-sm));
margin-bottom: var(--spacing-sm);
margin: 0 0 var(--spacing-sm);
filter: none;
}
.single-hero-image:hover { filter: none; }
+8 -6
View File
@@ -14,12 +14,14 @@
{{ partial "menu.html" (dict "menuID" "main" "page" .) }}
</nav>
</header>
<main id="main-content" role="main">{{ block "main" . }}{{ end }}</main>
{{ if not .IsHome }}
<nav class="page-foot-nav" aria-label="Breadcrumb">
{{ partial "header.html" . }}
</nav>
{{ end }}
<main id="main-content" role="main">
{{ block "main" . }}{{ end }}
{{ if not .IsHome }}
<nav class="page-foot-nav" aria-label="Breadcrumb">
{{ partial "header.html" . }}
</nav>
{{ end }}
</main>
<footer role="contentinfo">{{ partial "footer.html" . }}</footer>
</body>
</html>