modernize / optimize the main navigation

This commit is contained in:
madrilene 2024-09-18 13:14:04 +02:00
parent bc421a860d
commit 00aa9643d1
6 changed files with 154 additions and 199 deletions

View file

@ -29,15 +29,14 @@
{% if drawerNav %}
<!-- template element holding a button that needs to be injected when JavaScript is finally available. -->
<!-- based on an article by Manuel Matuzovic, https://web.dev/website-navigation/ -->
<!-- based on solution by Manuel Matuzovic, https://web.dev/website-navigation/ and the Web Accessibility Cookbook -->
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
<template id="burger-template">
<button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
<button type="button" aria-expanded="false" aria-controls="mainnav">
<span>{{ meta.navigation.navLabel }}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
@ -54,14 +53,6 @@
</template>
{% endif %}
{% css "inline" %}
{% include "css/nav-pills.css" %}
{% if drawerNav %}
{% include "css/nav-drawer.css" %}
{% endif %}
{% include "css/nav-desktop.css" %}
{% endcss %}
{% if drawerNav %}
{% js "defer" %}
{% include "scripts/nav-drawer.js" %}

View file

@ -1,47 +0,0 @@
@media screen(navigation) {
.mainnav {
--nav-button-display: none;
--nav-position: static;
}
.mainnav ul {
--list-background: transparent;
--list-layout: row;
--list-position: static;
--list-height: auto;
--list-width: 100%;
--list-shadow: none;
--list-transform: none;
--list-visibility: visible;
--list-width: auto;
--list-block-padding: 0;
--list-inline-padding: 0;
}
.mainnav a {
--item-padding: var(--space-xs) 0.2em;
--item-border-color: transparent;
--item-background-color: transparent;
--item-text-decoration: transparent;
--item-text-color: var(--color-text);
text-decoration-line: underline;
text-decoration-color: var(--item-text-decoration, transparent);
text-decoration-thickness: 3px;
text-underline-offset: 0.2em;
}
.mainnav a:where(:hover, :focus) {
--item-background-color: transparent;
--item-text-color: var(--color-text);
--item-text-decoration: var(--color-text);
}
/* Change border-color and color for the active page */
.mainnav [aria-current='page'],
.mainnav [data-state='active'] {
--item-border-color: transparent;
--item-background-color: transparent;
--item-text-color: var(--color-primary);
--item-text-decoration: var(--color-primary);
}
}

View file

@ -1,94 +0,0 @@
@media (scripting: enabled) {
.mainnav {
--nav-position: absolute;
inset-inline-end: 0;
}
.mainnav:has([aria-expanded='true']) {
--nav-position: fixed;
inset-inline-end: var(--gap);
}
.mainnav ul {
--gutter: var(--space-xs);
--cluster-vertical-alignment: normal;
--list-block-padding: var(--space-2xl);
--list-inline-padding: var(--space-s);
z-index: 1;
background: var(--list-background, var(--color-bg));
box-shadow: var(--list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
flex-direction: var(--list-layout, column);
block-size: var(--list-height, 100vh);
position: var(--list-position, fixed);
inset-block-start: 0;
inset-inline-end: 0;
inline-size: var(--list-width, min(18rem, 100vw));
visibility: var(--list-visibility, visible);
}
.mainnav :where([aria-expanded='false']) + ul {
transform: var(--list-transform, translateX(100%));
--list-visibility: hidden;
}
/* animates ul only when opening to avoid flash on page load, svg always */
@media (prefers-reduced-motion: no-preference) {
.mainnav [aria-expanded='true'] + ul,
.mainnav svg {
transition:
transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55),
visibility 0.05s linear;
}
}
.mainnav [aria-expanded='true'] + ul {
padding-top: var(--space-2xl);
overflow: auto;
overscroll-behavior: contain;
}
.mainnav button {
display: var(--nav-button-display, flex);
align-items: center;
position: relative;
z-index: 2;
padding: var(--space-2xs) 0;
}
.mainnav span {
font-weight: var(--font-extra-bold);
text-transform: uppercase;
padding-inline-end: 0.1em;
font-size: var(--size-step-min-1);
font-family: var(--font-display);
}
.mainnav svg {
inline-size: auto;
color: var(--color-text);
stroke-width: 3;
}
.mainnav [aria-expanded='true'] svg {
transform: var(--list-rotate, rotate(45deg));
}
.mainnav a {
--item-border-color: transparent;
--item-padding: var(--space-m) var(--space-xs);
--item-background-color: transparent;
}
.mainnav a:where(:hover, :focus) {
--item-background-color: var(--color-bg-accent);
--item-text-color: var(--color-text);
--item-border-color: transparent;
}
.mainnav [aria-current='page'],
.mainnav [data-state='active'] {
--item-border-color: transparent;
--item-background-color: var(--color-primary);
--item-text-color: var(--color-light);
}
}

View file

@ -1,43 +0,0 @@
.mainnav {
--gutter: var(--space-s);
position: var(--nav-position, relative);
}
.mainnav ul {
--gutter: var(--space-xs);
--list-block-padding: var(--space-s);
--list-inline-padding: 0;
margin: 0;
line-height: 0.5em;
padding-block: var(--list-block-padding);
padding-inline: var(--list-inline-padding);
}
.mainnav a {
--item-text-color: var(--color-text);
--item-background-color: var(--color-bg);
--item-border-color: var(--color-bg-accent-2);
--item-padding: var(--space-s);
background-color: var(--item-background-color);
color: var(--item-text-color);
padding: var(--item-padding);
text-decoration: none;
display: block;
border-radius: var(--border-radius);
border: 1px solid var(--item-border-color);
}
/* Change the border-color on :hover and :focus */
.mainnav a:where(:hover, :focus) {
--item-background-color: var(--color-text);
--item-text-color: var(--color-bg);
--item-border-color: var(--color-bg);
}
/* Change border-color and color for the active page. data-state='active' if a child is active. */
.mainnav [aria-current='page'],
.mainnav [data-state='active'] {
--item-background-color: var(--color-text);
--item-border-color: var(--color-bg);
--item-text-color: var(--color-bg);
}

View file

@ -0,0 +1,149 @@
.mainnav {
position: var(--nav-position, absolute);
inset-inline-end: 0;
}
.mainnav:has([aria-expanded='true']) {
--nav-position: fixed;
inset-inline-end: var(--gap);
}
.mainnav ul {
--gutter: var(--space-xs);
--cluster-vertical-alignment: normal;
background: var(--nav-list-background, var(--color-bg));
box-shadow: var(--nav-list-shadow, -5px 0 11px 0 hsl(0 0% 0% / 0.2));
display: flex;
flex-direction: var(--nav-list-layout, column);
flex-wrap: wrap;
block-size: var(--nav-list-height, 100dvh);
list-style: none;
margin: 0;
padding: var(--nav-list-padding, var(--space-s));
position: var(--nav-list-position, fixed);
inset-block-start: 0;
inset-inline-end: 0;
inline-size: var(--nav-list-width, min(18rem, 100vw));
visibility: var(--nav-list-visibility, hidden);
}
.mainnav [aria-expanded='false'] + ul {
transform: var(--list-transform, translateX(100%));
}
.mainnav [aria-expanded='true'] + ul {
--nav-list-visibility: visible;
padding-top: var(--space-2xl);
overflow: auto;
overscroll-behavior: contain;
}
@media (prefers-reduced-motion: no-preference) {
.mainnav [aria-expanded='true'] + ul,
.mainnav svg {
transition:
transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55),
visibility 0.05s linear;
}
}
.mainnav button {
display: var(--nav-button-display, flex);
align-items: center;
position: relative;
z-index: 2;
padding: var(--space-2xs) 0;
}
.mainnav span {
font-weight: var(--font-extra-bold);
text-transform: uppercase;
padding-inline-end: 0.1em;
font-size: var(--size-step-min-1);
font-family: var(--font-display);
}
.mainnav svg {
inline-size: auto;
color: var(--color-text);
stroke-width: 3;
}
.mainnav [aria-expanded='true'] svg {
transform: rotate(45deg);
}
.mainnav a {
background: var(--nav-item-background, transparent);
color: var(--nav-item-text-color, var(--color-text));
padding: var(--nav-item-padding, var(--space-xs) var(--space-2xs));
display: block;
border-radius: var(--border-radius);
text-decoration-line: underline;
text-decoration-color: var(--nav-item-decoration-color, transparent);
text-decoration-thickness: 3px;
text-underline-offset: 0.2em;
}
.mainnav a:where(:hover, :focus) {
--nav-item-background: transparent;
--nav-item-text-color: var(--color-text);
--nav-item-decoration-color: var(--color-text);
}
.mainnav [aria-current='page'],
.mainnav [data-state='active'] {
--nav-item-background: var(--color-bg-accent);
--nav-item-text-color: var(--color-primary);
--nav-item-decoration-color: transparent;
}
@media screen(navigation) {
.mainnav {
--nav-position: static;
--nav-button-display: none;
}
.mainnav ul {
--nav-list-layout: row;
--nav-list-position: static;
--nav-list-padding: 0;
--nav-list-height: auto;
--nav-list-width: 100%;
--nav-list-shadow: none;
--nav-list-visibility: visible;
}
.mainnav [aria-current='page'],
.mainnav [data-state='active'] {
--nav-item-background: transparent;
--nav-item-decoration-color: var(--color-primary);
}
.mainnav [aria-expanded='false'] + ul {
--list-transform: none;
}
}
/* Repeat the settings to provide a different styling when JavaScript is disabled or drawerNav is set to false. The selector
assumes that the button doesnt exist without JS, making the list the first child within the navigation. */
.mainnav ul:first-child {
--nav-list-layout: row;
--nav-list-position: static;
--nav-list-padding: 0;
--nav-list-height: auto;
--nav-list-width: 100%;
--nav-list-shadow: none;
--nav-list-visibility: visible;
}
.mainnav ul:first-child [aria-current='page'],
.mainnav ul:first-child [data-state='active'] {
--nav-item-background: transparent;
--nav-item-decoration-color: var(--color-primary);
}
.mainnav:has(ul:first-child) {
--nav-position: relative;
}

View file

@ -1,19 +1,18 @@
// © Manuel Matuzović: https://web.dev/website-navigation/
// © Manuel Matuzović: https://web.dev/website-navigation/ / Web Accessibility Cookbook
const nav = document.querySelector('nav');
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const svg = nav.querySelector('svg');
const button = burgerClone.querySelector('button');
button.addEventListener('click', e => {
const isOpen = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !isOpen);
});
// avoid DRY: disabling menu
const disableMenu = () => {
button.setAttribute('aria-expanded', false);
button.focus();
};
// close on escape