Mobiles Menü als Drawer: oben verankert, Accordion statt Sprung
Das Overlay war vertikal zentriert. Beim Aufklappen eines Dropdowns wuchs die Liste und rezentrierte sich — der gerade angetippte Punkt sprang unter dem Finger weg, bei langen Menüs lief der Inhalt aus dem Screen (nicht scrollbar). Jetzt ist die Liste oben verankert (justify-content: flex-start, padding unter Header + Logo-Überhang) und scrollbar mit overscroll-behavior: contain. Punkte sind volle Tap-Breite mit Hairline-Trennern, Chevron rechtsbündig, aktive Seite mit rotem Balken links. Untermenüs animieren über die 0fr/1fr-Zeile des li-Grids statt display: none — weiches Auf-/Zuklappen ohne Layout-Sprung. Unterpunkte in Abel statt Coolvetica (unter 28px unleserlich, siehe CLAUDE.md), linksbündig, Desktop-Panel-Optik im Overlay komplett zurückgesetzt (inkl. backdrop-filter/radius/translateX, die sonst durchschlugen). nav.js setzt .site-nav--js auf die Nav: nur ohne JS öffnet :focus-within die Untermenüs. Mit JS wäre das ein Bug — der Button behält nach dem Tipp den Fokus, das Menü ließe sich nie wieder zuklappen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MSsVdooFLgPA8gPFp7HwZU
This commit is contained in:
@@ -264,6 +264,12 @@
|
|||||||
z-index: 30;
|
z-index: 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Logo/Brand ebenfalls über dem Overlay halten — Orientierung bei offenem Menü. */
|
||||||
|
.site-header__brand {
|
||||||
|
position: relative;
|
||||||
|
z-index: 30;
|
||||||
|
}
|
||||||
|
|
||||||
.site-nav {
|
.site-nav {
|
||||||
order: 3;
|
order: 3;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
@@ -317,59 +323,146 @@
|
|||||||
transform: translateY(-9px) rotate(-45deg);
|
transform: translateY(-9px) rotate(-45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overlay: oben verankert + scrollbar — beim Aufklappen eines Dropdowns bleibt
|
||||||
|
der angetippte Punkt stehen (kein Re-Zentrier-Sprung), lange Menüs laufen
|
||||||
|
nicht mehr aus dem Screen. */
|
||||||
.site-nav__list {
|
.site-nav__list {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
gap: 1.75rem;
|
align-items: stretch;
|
||||||
background: rgb(0 0 0 / 0.91);
|
gap: 0;
|
||||||
font-size: var(--fs-700);
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
background: rgb(8 8 8 / 0.96);
|
||||||
|
font-size: var(--fs-650);
|
||||||
|
text-align: left;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity var(--transition), visibility var(--transition);
|
transition: opacity var(--transition), visibility var(--transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Padding separat mit (0,2,0): der reset-Selektor ul[class] (0,1,1) würde
|
||||||
|
es auf der Ein-Klassen-Regel überschreiben. Links auf --container-pad,
|
||||||
|
damit die Menüpunkte mit dem Logo fluchten. */
|
||||||
|
.site-nav .site-nav__list {
|
||||||
|
/* Oben: Header + Logo-Überhang (Logo ragt unter den Header) + Luft. */
|
||||||
|
padding: calc(var(--header-h) + 4rem) var(--container-pad) 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (backdrop-filter: blur(1px)) {
|
||||||
|
.site-nav__list {
|
||||||
|
background: rgb(8 8 8 / 0.85);
|
||||||
|
backdrop-filter: blur(18px) saturate(1.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.site-nav__list a:not(.btn) {
|
.site-nav__list a:not(.btn) {
|
||||||
font-family: var(--ff-heading);
|
font-family: var(--ff-heading);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dropdown im Overlay: Trigger wie die anderen Punkte, Untermenü inline darunter. */
|
/* Drawer-Zeilen: volle Tap-Breite mit Hairline-Trennern statt frei schwebender
|
||||||
.site-nav__sublink {
|
Punkte — Chevron sitzt rechtsbündig, aktive Seite bekommt den roten Balken
|
||||||
font-family: var(--ff-heading);
|
links (die Desktop-Unterstreichung wird hier neutralisiert). Untermenü-Höhe
|
||||||
font-size: var(--fs-700);
|
animiert über die 0fr/1fr-Zeile des li-Grids (weicher Accordion-Effekt). */
|
||||||
text-transform: uppercase;
|
.site-nav__list > .site-nav__item {
|
||||||
justify-content: center;
|
border-bottom: 1px solid var(--clr-glass-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Im Overlay inline einklappen — display statt visibility, sonst bliebe Platz reserviert.
|
.site-nav__list > .site-nav__item > a:not(.btn),
|
||||||
Spezifität (0,2,0) gleich der Desktop-Regel; gewinnt hier per Quell-Reihenfolge. */
|
.site-nav__sublink {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem 0.25rem;
|
||||||
|
border-bottom: 0;
|
||||||
|
font-family: var(--ff-heading);
|
||||||
|
font-size: var(--fs-650);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-nav__list > .site-nav__item > a[aria-current="page"],
|
||||||
|
.site-nav__sublink[data-current] {
|
||||||
|
border-bottom: 0;
|
||||||
|
box-shadow: inset 3px 0 0 var(--clr-accent);
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Volle Breite + zentrierter Text: Items und Untermenüs zentrieren sich am
|
||||||
|
Screen (nicht am shrink-gewrappten li), Unterstreichungen bleiben textbreit. */
|
||||||
|
.site-nav__item--has-submenu {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 0fr;
|
||||||
|
transition: grid-template-rows var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-nav__item--has-submenu:has(> .site-nav__sublink[aria-expanded="true"]) {
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ohne JS gibt es kein aria-expanded-Toggling — dann (und nur dann) öffnet
|
||||||
|
:focus-within. Mit JS wäre :focus-within ein Bug: der Button behält nach
|
||||||
|
dem Tipp den Fokus, das Menü ließe sich nie wieder zuklappen. */
|
||||||
|
.site-nav:not(.site-nav--js) .site-nav__item--has-submenu:focus-within {
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Desktop-Panel-Optik komplett zurücksetzen (inkl. backdrop-filter/radius —
|
||||||
|
sonst schimmert das Glas-Panel im Overlay durch). Spezifität (0,2,0) gleich
|
||||||
|
der Desktop-Regel; gewinnt hier per Quell-Reihenfolge. */
|
||||||
.site-nav__list .site-nav__submenu {
|
.site-nav__list .site-nav__submenu {
|
||||||
position: static;
|
position: static;
|
||||||
transform: none;
|
transform: none;
|
||||||
display: none;
|
display: grid;
|
||||||
opacity: 1;
|
min-height: 0;
|
||||||
visibility: visible;
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
margin: 0.75rem 0 0;
|
justify-self: stretch;
|
||||||
|
margin: 0;
|
||||||
|
/* Kein Padding am ul: bei border-box könnte die 0fr-Zeile sonst nicht auf 0
|
||||||
|
kollabieren (ungleiche Abstände). Luft macht das letzte Kind-li. Keine
|
||||||
|
Einrückung — Hierarchie kommt aus Schriftart/-größe und Farbe. */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: none;
|
background: none;
|
||||||
|
backdrop-filter: none;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
transition: opacity var(--transition), visibility var(--transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-nav__item--has-submenu:focus-within > .site-nav__submenu,
|
.site-nav__sublink[aria-expanded="true"] + .site-nav__submenu,
|
||||||
.site-nav__sublink[aria-expanded="true"] + .site-nav__submenu {
|
.site-nav:not(.site-nav--js) .site-nav__item--has-submenu:focus-within > .site-nav__submenu {
|
||||||
display: grid;
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
/* Desktop-Open-Regel (0,3,0) setzt translateX(-50%) — hier neutralisieren,
|
||||||
|
sonst hängt das Untermenü halb aus dem Screen. */
|
||||||
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.site-nav__list .site-nav__submenu > li:last-child {
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unterpunkte in Abel, Groß-/Kleinschreibung — wie im Desktop-Dropdown
|
||||||
|
(Coolvetica-Condensed-Uppercase wird unter 28px unleserlich). Bündig mit
|
||||||
|
den Hauptpunkten; die aktive Unterseite rückt per Desktop-Regel mit
|
||||||
|
Akzentbalken + Tint leicht ein. */
|
||||||
.site-nav__list .site-nav__submenu a:not(.btn) {
|
.site-nav__list .site-nav__submenu a:not(.btn) {
|
||||||
font-size: var(--fs-600);
|
padding: 0.6rem 0.25rem;
|
||||||
|
font-family: var(--ff-body);
|
||||||
|
font-size: var(--fs-500);
|
||||||
|
text-transform: none;
|
||||||
color: var(--clr-text-muted);
|
color: var(--clr-text-muted);
|
||||||
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.nav-open .site-nav__list {
|
body.nav-open .site-nav__list {
|
||||||
|
|||||||
@@ -11,6 +11,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marker fürs CSS: mit JS steuert allein aria-expanded die Dropdowns,
|
||||||
|
// der :focus-within-Fallback (No-JS) wird abgeschaltet (sonst ließe sich
|
||||||
|
// ein Untermenü auf Touch nie wieder zuklappen).
|
||||||
|
toggle.closest('.site-nav').classList.add('site-nav--js');
|
||||||
|
|
||||||
var subToggles = Array.prototype.slice.call(list.querySelectorAll('.site-nav__sublink'));
|
var subToggles = Array.prototype.slice.call(list.querySelectorAll('.site-nav__sublink'));
|
||||||
|
|
||||||
function closeSubmenus(except) {
|
function closeSubmenus(except) {
|
||||||
|
|||||||
Reference in New Issue
Block a user