enhance mobile navigation with responsive design improvements and accessibility features

This commit is contained in:
Fabian Schieder 2026-02-27 22:38:45 +01:00
parent 5e421709f0
commit f9988e1139
9 changed files with 614 additions and 33 deletions

View File

@ -14,7 +14,7 @@ error_log("[404] $ip $method $requestUri");
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<link rel="icon" href="assets/images/favicon.ico" sizes="any">
<title>404 Seite nicht gefunden | Geizkragen</title>

View File

@ -106,7 +106,7 @@
@media (max-width: 768px) {
.home-nav__inner {
justify-content: flex-start;
padding: 0.5rem 0.75rem;
padding: 0.4rem 0.5rem;
}
.home-nav__list {
@ -115,9 +115,12 @@
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
gap: 0.25rem;
gap: 0.2rem;
flex-wrap: nowrap;
justify-content: flex-start;
/* Fade edges */
mask-image: linear-gradient(90deg, transparent, black 0.5rem, black calc(100% - 0.5rem), transparent);
-webkit-mask-image: linear-gradient(90deg, transparent, black 0.5rem, black calc(100% - 0.5rem), transparent);
}
.home-nav__list::-webkit-scrollbar { display: none; }
@ -128,7 +131,24 @@
}
.home-nav__list li a {
padding: 0.45rem 1rem;
padding: 0.5rem 1rem;
font-size: 0.82rem;
min-height: 40px;
}
}
@media (max-width: 480px) {
.home-nav__inner {
padding: 0.35rem 0.25rem;
}
.home-nav__list li a {
padding: 0.45rem 0.8rem;
font-size: 0.78rem;
min-height: 36px;
}
.home-nav__list li a::after {
display: none; /* Simpler on tiny screens */
}
}

View File

@ -239,17 +239,84 @@
/* ─── Responsive ─── */
@media (max-width: 768px) {
.product-grid {
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 0.8rem;
padding: 1rem;
}
.product-section {
padding: 1.25rem 0 0.25rem;
}
.product-section h2 {
margin-left: 1rem;
font-size: 1.15rem;
font-size: 1.1rem;
}
.product-scroll {
padding: 0.5rem 1rem 2rem;
gap: 1rem;
padding: 0.5rem 1rem 1.5rem;
gap: 0.8rem;
mask-image: linear-gradient(90deg, transparent, black 1rem, black calc(100% - 1rem), transparent);
-webkit-mask-image: linear-gradient(90deg, transparent, black 1rem, black calc(100% - 1rem), transparent);
}
.product-scroll .product-card {
flex: 0 0 240px;
flex: 0 0 200px;
min-height: 230px;
}
.product-card img {
height: 130px;
padding: 10px;
}
.product-card__content {
padding: 0.75rem 0.9rem 0.85rem;
gap: 0.25rem;
}
.product-card__content h3 {
font-size: 0.82rem;
}
.product-card__content p {
font-size: 0.72rem;
-webkit-line-clamp: 2;
}
.product-card__content .price {
font-size: 0.92rem;
}
}
@media (max-width: 480px) {
.product-grid {
grid-template-columns: repeat(2, 1fr);
gap: 0.6rem;
padding: 0.75rem;
}
.product-scroll .product-card {
flex: 0 0 170px;
min-height: 210px;
}
.product-card img {
height: 110px;
padding: 8px;
}
.product-card__content {
padding: 0.6rem 0.7rem 0.7rem;
}
.product-card__content h3 {
font-size: 0.78rem;
-webkit-line-clamp: 1;
}
.product-card__content p {
display: none;
}
}

View File

@ -443,6 +443,11 @@
RESPONSIVE
========================================================== */
@media (max-width: 900px) {
.auth {
padding: 1.5rem 1rem 3rem;
min-height: auto;
}
.auth__grid {
width: min(480px, 100%);
}
@ -453,6 +458,23 @@
width: min(480px, 100%);
}
.auth__grid.auth__card__side .auth__card {
width: 100%;
}
.auth__grid.auth__card__side .auth__card.auth__card__side__picture {
width: 100%;
justify-self: stretch;
}
.auth__grid.auth__card__side .auth__card.auth__card__side__picture img {
max-width: 100%;
width: auto;
max-height: 200px;
margin: 0 auto;
display: block;
}
.auth__logo {
width: 120px;
}
@ -464,23 +486,75 @@
@media (max-width: 520px) {
.auth {
padding-top: 1.5rem;
padding: 1rem 0.75rem 2rem;
}
.auth::before {
width: 250px;
height: 250px;
}
.auth__card {
padding: 1.25rem;
border-radius: var(--radius-md);
}
.auth__header {
grid-template-columns: 1fr;
gap: 0.5rem;
}
.auth__logo {
width: 140px;
width: 120px;
grid-row: auto;
margin-bottom: 0.5rem;
}
.auth__title {
font-size: 1.25rem;
font-size: 1.2rem;
}
.auth__subtitle {
font-size: 0.88rem;
}
.auth__field input[type="text"],
.auth__field input[type="password"],
.auth__field input[type="email"],
.auth__field input[type="file"] {
padding: 0.7rem 0.8rem;
font-size: 16px; /* Prevents iOS zoom on focus */
}
.auth__submit {
padding: 0.85rem 1rem;
font-size: 0.95rem;
min-height: 48px;
}
.auth__muted {
font-size: 0.82rem;
}
}
@media (max-width: 380px) {
.auth {
padding: 0.75rem 0.5rem 1.5rem;
}
.auth__card {
padding: 1rem;
}
.auth__logo {
width: 100px;
}
.auth__title {
font-size: 1.1rem;
}
.auth__grid.auth__card__side .auth__card.auth__card__side__picture img {
max-height: 160px;
}
}

View File

@ -156,10 +156,43 @@ textarea.auth__input {
/* ─── Responsive ─── */
@media (max-width: 720px) {
.auth {
padding: 1.5rem 0.75rem;
padding: 1.25rem 0.75rem;
}
.auth__card {
padding: 1.25rem;
}
.auth__select {
font-size: 16px; /* Prevents iOS zoom */
padding: 0.8rem 2.5rem 0.8rem 0.8rem;
}
.auth__input {
font-size: 16px; /* Prevents iOS zoom */
padding: 0.75rem 0.8rem;
}
}
@media (max-width: 480px) {
.auth {
padding: 1rem 0.5rem;
}
.auth__card {
padding: 1rem;
border-radius: var(--radius-md);
}
.auth__grid {
gap: 1rem;
}
.auth__title {
font-size: 1.05rem;
}
.auth__select__wrap {
margin-top: 0.5rem;
}
}

View File

@ -154,11 +154,54 @@
.product-wrapper {
flex-direction: column;
gap: 2rem;
margin: 2rem auto;
margin: 1.5rem auto;
padding: 0 1rem;
}
.product-image-box {
padding: 1.5rem;
}
.product-title {
font-size: 1.5rem;
font-size: 1.4rem;
margin-bottom: 1rem;
padding-bottom: 0.75rem;
}
.product-desc {
font-size: 0.92rem;
}
}
@media (max-width: 600px) {
.product-wrapper {
gap: 1.25rem;
margin: 1rem auto;
padding: 0 0.75rem;
}
.product-image-box {
padding: 1rem;
border-radius: var(--radius-lg);
}
.product-title {
font-size: 1.2rem;
}
.product-desc {
font-size: 0.88rem;
line-height: 1.6;
margin-bottom: 1rem;
}
.product-specs p {
padding: 0.6rem 0.8rem;
font-size: 0.85rem;
}
.product-specs p:hover {
transform: none;
}
}
@ -352,10 +395,59 @@
.shop-price {
font-size: 1.2rem;
}
.shop-offers {
padding: 0 1rem;
margin-bottom: 3rem;
}
}
@media (max-width: 600px) {
.shop-line {
gap: 0.5rem;
padding: 0.85rem;
border-radius: var(--radius-md);
}
.shop-line:hover {
padding-left: 0.85rem;
transform: none;
}
.shop-left {
gap: 0.75rem;
}
.shop-logo img {
max-height: 28px;
max-width: 70px;
}
.shop-name {
font-size: 0.88rem;
}
.shop-middle {
gap: 0.5rem;
font-size: 0.8rem;
}
.shop-stock {
font-size: 0.72rem;
padding: 0.2rem 0.6rem;
}
.shop-price {
font-size: 1.1rem;
}
.shop-offers {
padding: 0 1rem;
padding: 0 0.75rem;
gap: 0.5rem;
}
.no-shop {
padding: 1.5rem;
font-size: 0.88rem;
}
}

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/assets/css/login.css">
@ -14,16 +14,36 @@
<link rel="icon" href="/assets/images/favicon.ico" sizes="any">
<!-- Prevent tap-highlight on mobile -->
<style>
* { -webkit-tap-highlight-color: transparent; }
/* Mobile menu overlay */
.nav__overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
z-index: 1000;
opacity: 0;
transition: opacity 300ms ease;
}
.nav__overlay.show { display: block; opacity: 1; }
</style>
<title>Geizkragen</title>
</head>
<body>
<!-- Mobile overlay for hamburger menu -->
<div class="nav__overlay" id="nav-overlay"></div>
<header class="header" id="header">
<nav class="nav" aria-label="Hauptnavigation">
<a class="nav__logoLink" href="index.php">
<img class="nav__logo" src="/assets/images/logoText.png" alt="Geizkragen" width="150">
</a>
<!-- Desktop search (hidden on mobile via CSS) -->
<form class="nav__searchForm" action="index.php" method="GET" autocomplete="off">
<div class="nav__searchField">
<input class="nav__searchInput" type="text" id="search" name="search" placeholder="Produkte suchen…" inputmode="text">
@ -32,14 +52,29 @@
<div class="nav__inner container">
<div class="nav__menu" id="nav-menu">
<!-- Mobile search (inside hamburger) -->
<form class="nav__searchForm nav__searchForm--mobile" action="index.php" method="GET" autocomplete="off">
<div class="nav__searchField">
<input class="nav__searchInput" type="text" name="search" placeholder="Produkte suchen…" inputmode="text">
</div>
</form>
<ul class="nav__list">
<li class="nav__item">
<a href="index.php" class="nav__link">Home</a>
</li>
<li class="nav__item nav__item--mobile">
<a href="wunschliste.php" class="nav__link">Wunschliste</a>
</li>
<li class="nav__item nav__item--mobile">
<a href="account.php" class="nav__link">Account</a>
</li>
</ul>
<div class="nav__close" id="nav-close">
<i class="ri-close-line"></i>
<div class="nav__close" id="nav-close" role="button" aria-label="Menü schließen" tabindex="0">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</div>
</div>
@ -54,10 +89,47 @@
<path d="M4 22C4 17.5817 7.58172 14 12 14C16.4183 14 20 17.5817 20 22H18C18 18.6863 15.3137 16 12 16C8.68629 16 6 18.6863 6 22H4ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11Z"/>
</svg>
</a>
<div class="nav__toggle" id="nav-toggle">
<i class="ri-menu-line"></i>
<div class="nav__toggle" id="nav-toggle" role="button" aria-label="Menü öffnen" tabindex="0">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/>
</svg>
</div>
</div>
</div>
</nav>
</header>
<!-- Hamburger Menu JS -->
<script>
(function() {
const toggle = document.getElementById('nav-toggle');
const close = document.getElementById('nav-close');
const menu = document.getElementById('nav-menu');
const overlay = document.getElementById('nav-overlay');
function openMenu() {
menu.classList.add('show-menu');
overlay.classList.add('show');
document.body.style.overflow = 'hidden';
}
function closeMenu() {
menu.classList.remove('show-menu');
overlay.classList.remove('show');
document.body.style.overflow = '';
}
if (toggle) toggle.addEventListener('click', openMenu);
if (close) close.addEventListener('click', closeMenu);
if (overlay) overlay.addEventListener('click', closeMenu);
// Close on Escape
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') closeMenu();
});
// Close menu on link click (mobile)
menu.querySelectorAll('.nav__link').forEach(function(link) {
link.addEventListener('click', closeMenu);
});
})();
</script>

View File

@ -1,11 +1,11 @@
<?php include 'header.php'; ?>
<main style="padding: 3rem 1.5rem; max-width: 800px; margin: 0 auto; animation: fadeInUp 0.5s ease both;">
<main style="padding: 2rem 1rem; max-width: 800px; margin: 0 auto; animation: fadeInUp 0.5s ease both;">
<div class="auth__card" style="width: 100%; max-width: 100%;">
<header class="auth__header">
<header class="auth__header" style="grid-template-columns: 1fr;">
<h1 class="auth__title">Impressum</h1>
</header>
<p style="color: var(--text-secondary); line-height: 1.8;">Impressum 123</p>
<p style="color: var(--text-secondary); line-height: 1.8; font-size: 0.95rem;">Impressum 123</p>
</div>
</main>

243
style.css
View File

@ -345,6 +345,10 @@ a:hover {
.nav__toggle { display: none; }
.nav__close { display: none; }
/* Mobile-only search + items: hidden on desktop */
.nav__searchForm--mobile { display: none; }
.nav__item--mobile { display: none; }
/* ==========================================================
MOBILE NAV
========================================================== */
@ -353,39 +357,69 @@ a:hover {
display: flex;
}
.nav__item--mobile {
display: list-item;
}
.nav__menu {
position: fixed;
top: 0;
right: -100%;
width: 300px;
width: min(300px, 85vw);
height: 100%;
background: rgba(13, 17, 23, 0.95);
background: rgba(13, 17, 23, 0.97);
backdrop-filter: blur(30px);
-webkit-backdrop-filter: blur(30px);
border-left: 1px solid var(--border-subtle);
padding: 5rem 2rem 2rem;
padding: 4.5rem 1.5rem 2rem;
transition: right 350ms cubic-bezier(0.4, 0, 0.2, 1);
flex-direction: column;
align-items: flex-start;
gap: 2rem;
gap: 1.25rem;
z-index: 1001;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.nav__menu.show-menu {
right: 0;
}
/* Show mobile search inside menu */
.nav__searchForm--mobile {
display: block;
width: 100%;
position: static;
transform: none;
}
.nav__searchForm--mobile .nav__searchField {
width: 100%;
}
.nav__searchForm--mobile .nav__searchInput {
width: 100%;
height: 44px;
padding: 0 16px;
font-size: 0.92rem;
border-radius: var(--radius-md);
}
.nav__list {
flex-direction: column;
gap: 0.5rem;
gap: 0.25rem;
width: 100%;
}
.nav__link {
font-size: 1.05rem;
font-size: 1rem;
color: var(--text-secondary);
display: block;
padding: 0.75rem 1rem;
display: flex;
align-items: center;
min-height: 44px;
padding: 0.6rem 1rem;
border-radius: var(--radius-md);
width: 100%;
}
.nav__link:hover {
@ -396,9 +430,14 @@ a:hover {
.nav__close {
display: flex;
position: absolute;
top: 1.2rem;
right: 1.2rem;
top: 1rem;
right: 1rem;
color: var(--text-secondary);
padding: 0.5rem;
min-height: 44px;
min-width: 44px;
align-items: center;
justify-content: center;
}
.nav__close:hover {
@ -824,3 +863,187 @@ a:hover {
.animate-children > *:nth-child(4) { animation-delay: 0.2s; }
.animate-children > *:nth-child(5) { animation-delay: 0.25s; }
.animate-children > *:nth-child(6) { animation-delay: 0.3s; }
/* ==========================================================
MOBILE OPTIMIZATIONS
========================================================== */
/* ─── Touch Optimizations ─── */
@media (pointer: coarse) {
.nav__link,
.home-nav__list li a,
.nav__login,
.nav__wishlist,
.btn,
.auth__submit,
.shop-line {
min-height: 44px;
display: inline-flex;
align-items: center;
}
/* Disable hover-only effects on touch */
.product-card:hover {
transform: none;
box-shadow: var(--shadow-sm);
}
.product-card:active {
transform: scale(0.98);
box-shadow: var(--shadow-md), var(--shadow-glow-blue);
}
.shop-line:hover {
transform: none;
padding-left: 1.5rem;
}
.shop-line:active {
background: rgba(15, 21, 32, 0.9);
}
}
/* ─── Reduce motion for accessibility ─── */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ─── Tablet (max-width: 900px) ─── */
@media (max-width: 900px) {
:root {
--nav-gutter: 1rem;
}
.nav {
min-height: 56px;
padding: 0 0.5rem;
}
.nav__logo {
max-width: 120px;
}
/* Mobile search inside hamburger */
.nav__searchForm--mobile {
display: block;
width: 100%;
position: static;
transform: none;
margin-bottom: 1rem;
}
.nav__searchForm--mobile .nav__searchField {
width: 100%;
}
.nav__searchForm--mobile .nav__searchInput {
width: 100%;
height: 44px;
padding: 0 16px 0 42px;
font-size: 0.95rem;
}
.container {
padding-inline: 1rem;
}
.layout {
padding: 0 1rem;
margin: 1.5rem auto;
gap: 1.5rem;
}
}
/* ─── Phone (max-width: 600px) ─── */
@media (max-width: 600px) {
:root {
--nav-gutter: 0.75rem;
}
body {
font-size: 0.95rem;
}
/* Simplify background effects on mobile */
body::before {
background-size: 60px 60px;
}
body::after {
width: 300px;
height: 300px;
}
.nav {
min-height: 52px;
padding: 0 0.25rem;
}
.nav__logo {
max-width: 110px;
}
.nav__actions {
gap: 0;
}
.nav__login,
.nav__search {
padding: 0.4rem;
}
.icon-user {
width: 20px;
height: 20px;
}
/* Mobile menu full-width */
.nav__menu {
width: 100% !important;
right: -100%;
}
.product-grid {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 0.8rem;
}
.product-content {
padding: 0.7rem 0.8rem 0.9rem;
}
.product-title {
font-size: 0.82rem;
}
.product-price {
font-size: 1.1rem;
}
/* Buttons larger touch targets */
.btn {
padding: 0.7rem 1.1rem;
font-size: 0.88rem;
}
.container {
padding-inline: 0.75rem;
}
}
/* ─── Tiny phones (max-width: 380px) ─── */
@media (max-width: 380px) {
.nav__logo {
max-width: 90px;
}
.nav__login,
.nav__search {
padding: 0.3rem;
}
.icon-user {
width: 18px;
height: 18px;
}
}