sonith-website/js/main.js
Dominik Höfling dc51be2da1 feat: Statischer One-Pager für sonith.de
Kompletter Relaunch als statische Website:
- index.html: One-Pager mit Hero, Leistungen, USPs, Team, Kontakt
- impressum.html + datenschutz.html: Separate Unterseiten
- TailwindCSS via CDN, Custom Styles, Scroll-Animationen
- Mobile Menu, Scroll-Spy, Fade-in Animationen
- Farbschema: Dunkel-modern mit Sonith-Gelb (#DEDC1B)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 07:45:25 +01:00

97 lines
2.9 KiB
JavaScript

/* ============================================================
sonith.de — Main JavaScript
============================================================ */
document.addEventListener('DOMContentLoaded', () => {
initMobileMenu();
initScrollSpy();
initNavbarScroll();
initFadeIn();
});
/* ---- Mobile Menu ---- */
function initMobileMenu() {
const btn = document.getElementById('mobile-menu-btn');
const menu = document.getElementById('mobile-menu');
const iconOpen = document.getElementById('menu-icon-open');
const iconClose = document.getElementById('menu-icon-close');
if (!btn || !menu) return;
btn.addEventListener('click', () => {
const isOpen = !menu.classList.contains('hidden');
menu.classList.toggle('hidden');
iconOpen.classList.toggle('hidden');
iconClose.classList.toggle('hidden');
btn.setAttribute('aria-label', isOpen ? 'Menü öffnen' : 'Menü schließen');
});
// Menü schließen bei Klick auf Link
menu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
menu.classList.add('hidden');
iconOpen.classList.remove('hidden');
iconClose.classList.add('hidden');
btn.setAttribute('aria-label', 'Menü öffnen');
});
});
}
/* ---- Scroll Spy (aktiver Menüpunkt) ---- */
function initScrollSpy() {
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
if (!sections.length || !navLinks.length) return;
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.getAttribute('id');
navLinks.forEach(link => {
link.classList.toggle('active', link.getAttribute('href') === `#${id}`);
});
}
});
}, {
rootMargin: '-20% 0px -60% 0px',
threshold: 0
});
sections.forEach(section => observer.observe(section));
}
/* ---- Navbar Background on Scroll ---- */
function initNavbarScroll() {
const navbar = document.getElementById('navbar');
if (!navbar) return;
const update = () => {
navbar.classList.toggle('scrolled', window.scrollY > 50);
};
window.addEventListener('scroll', update, { passive: true });
update();
}
/* ---- Fade-in on Scroll ---- */
function initFadeIn() {
const elements = document.querySelectorAll('.fade-in, .service-card');
if (!elements.length) return;
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -40px 0px'
});
elements.forEach(el => observer.observe(el));
}