Skip to content
IRC-Coding IRC-Coding
Webentwicklung Grundlagen HTML CSS JavaScript DOM Manipulation Responsive Design Frontend

Webentwicklung Grundlagen: HTML, CSS, JavaScript, DOM-Manipulation & Responsive Design

Webentwicklung Grundlagen mit HTML5, CSS3, JavaScript ES6+, DOM-Manipulation und Responsive Design. Moderne Web-Technologien mit praktischen Beispielen und Best Practices.

S

schutzgeist

2 min read

Webentwicklung Grundlagen: HTML, CSS, JavaScript, DOM-Manipulation & Responsive Design

Dieser Beitrag ist eine umfassende Einführung in die Webentwicklung Grundlagen – inklusive HTML5, CSS3, JavaScript ES6+, DOM-Manipulation und Responsive Design mit praktischen Beispielen.

In a Nutshell

Webentwicklung basiert auf drei Kerntechnologien: HTML für Struktur, CSS für Styling und JavaScript für Interaktivität. Responsive Design sorgt für optimale Darstellung auf allen Geräten.

Kompakte Fachbeschreibung

Webentwicklung ist die Erstellung von Webanwendungen durch Kombination von Markup-, Style- und Programmiersprachen.

Kerntechnologien:

HTML5 (HyperText Markup Language)

  • Struktur: Semantische Auszeichnung von Inhalten
  • Elemente: Header, nav, main, section, article, footer
  • Formulare: Input-Typen, Validierung, Accessibility
  • Multimedia: Audio, Video, Canvas, SVG

CSS3 (Cascading Style Sheets)

  • Styling: Farben, Schriftarten, Layout, Animationen
  • Layout: Flexbox, Grid, Positioning, Responsive Design
  • Pseudo-Klassen: :hover, :active, :focus, :nth-child
  • Media Queries: Responsive Design, Breakpoints

JavaScript ES6+

  • Interaktivität: DOM-Manipulation, Event-Handling
  • Features: Arrow Functions, Template Literals, Destructuring
  • DOM API: Elemente auswählen, manipulieren, Events
  • Asynchron: Promises, async/await, Fetch API

Prüfungsrelevante Stichpunkte

  • HTML5: Semantische Markup-Sprache für Web-Inhalte
  • CSS3: Stylesheet-Sprache für Design und Layout
  • JavaScript: Programmiersprache für Web-Interaktivität
  • DOM: Document Object Model für dynamische Manipulation
  • Responsive Design: Anpassung an verschiedene Bildschirmgrößen
  • Media Queries: CSS-Bedingungen für Geräte-Eigenschaften
  • Flexbox/Grid: Moderne Layout-Techniken
  • IHK-relevant: Grundlage für alle Web-Entwicklungsberufe

Kernkomponenten

  1. HTML5: Semantische Struktur und Inhalt
  2. CSS3: Visuelle Gestaltung und Layout
  3. JavaScript: Dynamische Funktionalität
  4. DOM: Programmierbare Schnittstelle
  5. Responsive Design: Geräteübergreifende Kompatibilität
  6. Accessibility: Barrierefreie Webentwicklung
  7. Performance: Ladezeiten und Optimierung
  8. Best Practices: Moderne Entwicklungsstandards

Praxisbeispiele

1. HTML5 Grundstruktur

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Moderne Webanwendung mit HTML5, CSS3 und JavaScript">
    <title>Webentwicklung Demo</title>
    
    <!-- CSS einbinden -->
    <link rel="stylesheet" href="styles.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
    
    <!-- Favicon -->
    <link rel="icon" type="image/svg+xml" href="favicon.svg">
    
    <!-- Open Graph Meta Tags -->
    <meta property="og:title" content="Webentwicklung Demo">
    <meta property="og:description" content="Moderne Webanwendung">
    <meta property="og:type" content="website">
</head>
<body>
    <!-- Skip Navigation für Accessibility -->
    <a href="#main-content" class="skip-link">Zum Hauptinhalt springen</a>
    
    <!-- Header mit Navigation -->
    <header class="header">
        <nav class="nav" aria-label="Hauptnavigation">
            <div class="nav-container">
                <div class="nav-brand">
                    <a href="#" class="brand-link">
                        <img src="logo.svg" alt="Logo" class="brand-logo">
                        <span class="brand-text">WebDev</span>
                    </a>
                </div>
                
                <button class="nav-toggle" aria-expanded="false" aria-controls="nav-menu">
                    <span class="hamburger"></span>
                    <span class="visually-hidden">Menü</span>
                </button>
                
                <ul id="nav-menu" class="nav-menu">
                    <li><a href="#home" class="nav-link">Home</a></li>
                    <li><a href="#features" class="nav-link">Features</a></li>
                    <li><a href="#contact" class="nav-link">Kontakt</a></li>
                </ul>
            </div>
        </nav>
    </header>
    
    <!-- Hauptinhalt -->
    <main id="main-content" class="main">
        <!-- Hero Section -->
        <section class="hero" id="home">
            <div class="container">
                <h1 class="hero-title">Moderne Webentwicklung</h1>
                <p class="hero-subtitle">HTML5, CSS3 und JavaScript in Aktion</p>
                
                <div class="hero-actions">
                    <button class="btn btn-primary" data-action="start">Starten</button>
                    <a href="#features" class="btn btn-secondary">Mehr erfahren</a>
                </div>
                
                <!-- Interactive Demo -->
                <div class="demo-section">
                    <div class="demo-container">
                        <canvas id="demo-canvas" width="400" height="200"></canvas>
                        <div class="demo-controls">
                            <button class="demo-btn" data-action="clear">Löschen</button>
                            <button class="demo-btn" data-action="animate">Animieren</button>
                            <input type="color" id="color-picker" value="#3b82f6">
                        </div>
                    </div>
                </div>
            </div>
        </section>
        
        <!-- Features Section -->
        <section class="features" id="features">
            <div class="container">
                <h2 class="section-title">Features</h2>
                
                <div class="features-grid">
                    <article class="feature-card">
                        <div class="feature-icon">
                            <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <path d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"/>
                            </svg>
                        </div>
                        <h3 class="feature-title">Sicherheit</h3>
                        <p class="feature-description">Moderne Sicherheitsstandards und Best Practices</p>
                    </article>
                    
                    <article class="feature-card">
                        <div class="feature-icon">
                            <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
                                <line x1="8" y1="21" x2="16" y2="21"/>
                                <line x1="12" y1="17" x2="12" y2="21"/>
                            </svg>
                        </div>
                        <h3 class="feature-title">Responsive</h3>
                        <p class="feature-description">Optimale Darstellung auf allen Geräten</p>
                    </article>
                    
                    <article class="feature-card">
                        <div class="feature-icon">
                            <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
                            </svg>
                        </div>
                        <h3 class="feature-title">Performance</h3>
                        <p class="feature-description">Schnelle Ladezeiten und reibungslose Interaktion</p>
                    </article>
                </div>
            </div>
        </section>
        
        <!-- Kontakt Formular -->
        <section class="contact" id="contact">
            <div class="container">
                <h2 class="section-title">Kontakt</h2>
                
                <form class="contact-form" novalidate>
                    <div class="form-group">
                        <label for="name" class="form-label">Name *</label>
                        <input type="text" id="name" name="name" class="form-input" required>
                        <span class="form-error" id="name-error">Bitte geben Sie Ihren Namen ein</span>
                    </div>
                    
                    <div class="form-group">
                        <label for="email" class="form-label">E-Mail *</label>
                        <input type="email" id="email" name="email" class="form-input" required>
                        <span class="form-error" id="email-error">Bitte geben Sie eine gültige E-Mail ein</span>
                    </div>
                    
                    <div class="form-group">
                        <label for="message" class="form-label">Nachricht</label>
                        <textarea id="message" name="message" class="form-textarea" rows="4"></textarea>
                    </div>
                    
                    <div class="form-actions">
                        <button type="submit" class="btn btn-primary">Senden</button>
                        <button type="reset" class="btn btn-secondary">Zurücksetzen</button>
                    </div>
                </form>
            </div>
        </section>
    </main>
    
    <!-- Footer -->
    <footer class="footer">
        <div class="container">
            <p>&copy; 2024 Webentwicklung Demo. Alle Rechte vorbehalten.</p>
            <div class="footer-links">
                <a href="#impressum">Impressum</a>
                <a href="#datenschutz">Datenschutz</a>
            </div>
        </div>
    </footer>
    
    <!-- JavaScript einbinden -->
    <script src="script.js"></script>
</body>
</html>

2. CSS3 mit Responsive Design

/* CSS Reset und Basis-Styles */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* CSS Custom Properties (Variables) */
:root {
    /* Farben */
    --color-primary: #3b82f6;
    --color-primary-dark: #2563eb;
    --color-primary-light: #60a5fa;
    --color-secondary: #64748b;
    --color-success: #10b981;
    --color-error: #ef4444;
    --color-warning: #f59e0b;
    
    /* Neutral */
    --color-white: #ffffff;
    --color-gray-50: #f8fafc;
    --color-gray-100: #f1f5f9;
    --color-gray-900: #0f172a;
    
    /* Typography */
    --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: 1.5rem;
    --font-size-3xl: 1.875rem;
    --font-size-4xl: 2.25rem;
    
    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-2xl: 3rem;
    
    /* Border Radius */
    --radius-sm: 0.25rem;
    --radius-md: 0.5rem;
    --radius-lg: 1rem;
    --radius-full: 9999px;
    
    /* Shadows */
    --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
    --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
    --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
    --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
    
    /* Transitions */
    --transition-fast: 150ms ease-in-out;
    --transition-normal: 300ms ease-in-out;
    --transition-slow: 500ms ease-in-out;
}

/* Basis-Styles */
html {
    font-size: 16px;
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-family);
    font-size: var(--font-size-base);
    line-height: 1.6;
    color: var(--color-gray-900);
    background-color: var(--color-white);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Utility Classes */
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 var(--spacing-md);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    background: var(--color-primary);
    color: var(--color-white);
    padding: var(--spacing-sm) var(--spacing-md);
    text-decoration: none;
    border-radius: var(--radius-md);
    z-index: 100;
    transition: top var(--transition-fast);
}

.skip-link:focus {
    top: var(--spacing-sm);
}

/* Header & Navigation */
.header {
    background-color: var(--color-white);
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: 0;
    z-index: 50;
}

.nav-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--spacing-md) 0;
}

.brand-link {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    text-decoration: none;
    color: var(--color-gray-900);
    font-weight: 600;
    transition: color var(--transition-fast);
}

.brand-link:hover {
    color: var(--color-primary);
}

.brand-logo {
    width: 32px;
    height: 32px;
}

.nav-toggle {
    display: none;
    background: none;
    border: none;
    padding: var(--spacing-sm);
    cursor: pointer;
}

.hamburger {
    display: block;
    width: 24px;
    height: 2px;
    background-color: var(--color-gray-900);
    position: relative;
    transition: background-color var(--transition-fast);
}

.hamburger::before,
.hamburger::after {
    content: '';
    position: absolute;
    width: 24px;
    height: 2px;
    background-color: var(--color-gray-900);
    transition: transform var(--transition-fast);
}

.hamburger::before {
    top: -8px;
}

.hamburger::after {
    top: 8px;
}

.nav-toggle[aria-expanded="true"] .hamburger {
    background-color: transparent;
}

.nav-toggle[aria-expanded="true"] .hamburger::before {
    transform: rotate(45deg);
    top: 0;
}

.nav-toggle[aria-expanded="true"] .hamburger::after {
    transform: rotate(-45deg);
    top: 0;
}

.nav-menu {
    display: flex;
    list-style: none;
    gap: var(--spacing-lg);
}

.nav-link {
    text-decoration: none;
    color: var(--color-gray-700);
    font-weight: 500;
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-md);
    transition: all var(--transition-fast);
}

.nav-link:hover {
    color: var(--color-primary);
    background-color: var(--color-gray-50);
}

/* Hero Section */
.hero {
    background: linear-gradient(135deg, var(--color-gray-50) 0%, var(--color-white) 100%);
    padding: var(--spacing-2xl) 0;
    text-align: center;
}

.hero-title {
    font-size: var(--font-size-4xl);
    font-weight: 700;
    color: var(--color-gray-900);
    margin-bottom: var(--spacing-md);
    line-height: 1.2;
}

.hero-subtitle {
    font-size: var(--font-size-xl);
    color: var(--color-secondary);
    margin-bottom: var(--spacing-xl);
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
}

.hero-actions {
    display: flex;
    gap: var(--spacing-md);
    justify-content: center;
    margin-bottom: var(--spacing-2xl);
}

/* Buttons */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-md) var(--spacing-lg);
    font-size: var(--font-size-base);
    font-weight: 600;
    text-decoration: none;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
    min-width: 120px;
}

.btn-primary {
    background-color: var(--color-primary);
    color: var(--color-white);
}

.btn-primary:hover {
    background-color: var(--color-primary-dark);
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.btn-secondary {
    background-color: var(--color-gray-100);
    color: var(--color-gray-900);
}

.btn-secondary:hover {
    background-color: var(--color-gray-200);
    transform: translateY(-2px);
}

/* Demo Section */
.demo-section {
    margin-top: var(--spacing-2xl);
}

.demo-container {
    background-color: var(--color-white);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    box-shadow: var(--shadow-md);
    max-width: 500px;
    margin: 0 auto;
}

#demo-canvas {
    border: 2px solid var(--color-gray-200);
    border-radius: var(--radius-md);
    width: 100%;
    height: auto;
    display: block;
    margin-bottom: var(--spacing-md);
}

.demo-controls {
    display: flex;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
    align-items: center;
}

.demo-btn {
    padding: var(--spacing-sm) var(--spacing-md);
    background-color: var(--color-gray-100);
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: var(--font-size-sm);
    transition: all var(--transition-fast);
}

.demo-btn:hover {
    background-color: var(--color-gray-200);
}

#color-picker {
    width: 50px;
    height: 36px;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

/* Features Section */
.features {
    padding: var(--spacing-2xl) 0;
    background-color: var(--color-gray-50);
}

.section-title {
    font-size: var(--font-size-3xl);
    font-weight: 700;
    text-align: center;
    margin-bottom: var(--spacing-2xl);
    color: var(--color-gray-900);
}

.features-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--spacing-xl);
}

.feature-card {
    background-color: var(--color-white);
    padding: var(--spacing-xl);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    text-align: center;
    transition: transform var(--transition-normal), box-shadow var(--transition-normal);
}

.feature-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-xl);
}

.feature-icon {
    display: flex;
    justify-content: center;
    margin-bottom: var(--spacing-lg);
    color: var(--color-primary);
}

.feature-title {
    font-size: var(--font-size-xl);
    font-weight: 600;
    margin-bottom: var(--spacing-md);
    color: var(--color-gray-900);
}

.feature-description {
    color: var(--color-secondary);
    line-height: 1.6;
}

/* Contact Form */
.contact {
    padding: var(--spacing-2xl) 0;
}

.contact-form {
    max-width: 600px;
    margin: 0 auto;
}

.form-group {
    margin-bottom: var(--spacing-lg);
}

.form-label {
    display: block;
    font-weight: 600;
    margin-bottom: var(--spacing-sm);
    color: var(--color-gray-900);
}

.form-input,
.form-textarea {
    width: 100%;
    padding: var(--spacing-md);
    border: 2px solid var(--color-gray-200);
    border-radius: var(--radius-md);
    font-size: var(--font-size-base);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-input:focus,
.form-textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgb(59 130 246 / 0.1);
}

.form-input:invalid,
.form-textarea:invalid {
    border-color: var(--color-error);
}

.form-error {
    display: none;
    color: var(--color-error);
    font-size: var(--font-size-sm);
    margin-top: var(--spacing-xs);
}

.form-input:invalid ~ .form-error {
    display: block;
}

.form-actions {
    display: flex;
    gap: var(--spacing-md);
    justify-content: flex-end;
}

/* Footer */
.footer {
    background-color: var(--color-gray-900);
    color: var(--color-gray-100);
    padding: var(--spacing-xl) 0;
    text-align: center;
}

.footer-links {
    margin-top: var(--spacing-md);
    display: flex;
    gap: var(--spacing-lg);
    justify-content: center;
}

.footer-links a {
    color: var(--color-gray-400);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.footer-links a:hover {
    color: var(--color-white);
}

/* Responsive Design */

/* Mobile First Approach */
/* Small Tablets und Large Phones */
@media (min-width: 640px) {
    .container {
        padding: 0 var(--spacing-lg);
    }
    
    .hero-title {
        font-size: var(--font-size-5xl);
    }
    
    .features-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Tablets */
@media (min-width: 768px) {
    .nav-toggle {
        display: none;
    }
    
    .nav-menu {
        display: flex;
    }
    
    .hero-actions {
        flex-direction: row;
    }
    
    .demo-controls {
        justify-content: center;
    }
}

/* Desktop */
@media (min-width: 1024px) {
    .hero {
        padding: var(--spacing-3xl) 0;
    }
    
    .features-grid {
        grid-template-columns: repeat(3, 1fr);
    }
    
    .form-actions {
        justify-content: flex-start;
    }
}

/* Large Desktop */
@media (min-width: 1280px) {
    .container {
        padding: 0 var(--spacing-xl);
    }
    
    .hero-title {
        font-size: var(--font-size-6xl);
    }
}

/* Dark Mode Support */
@media (prefers-color-scheme: dark) {
    :root {
        --color-white: #0f172a;
        --color-gray-50: #1e293b;
        --color-gray-100: #334155;
        --color-gray-900: #f8fafc;
        --color-gray-700: #cbd5e1;
        --color-gray-200: #475569;
    }
    
    .header {
        background-color: var(--color-gray-50);
    }
    
    .hero {
        background: linear-gradient(135deg, var(--color-gray-50) 0%, var(--color-white) 100%);
    }
    
    .features {
        background-color: var(--color-white);
    }
    
    .btn-secondary {
        background-color: var(--color-gray-200);
        color: var(--color-gray-900);
    }
    
    .btn-secondary:hover {
        background-color: var(--color-gray-100);
    }
}

/* Print Styles */
@media print {
    .nav-toggle,
    .hero-actions,
    .demo-section,
    .contact-form {
        display: none;
    }
    
    .hero {
        padding: var(--spacing-lg) 0;
    }
    
    body {
        font-size: 12pt;
        line-height: 1.4;
    }
    
    h1, h2, h3 {
        page-break-after: avoid;
    }
    
    .feature-card {
        break-inside: avoid;
    }
}

/* Animation Classes */
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.fade-in {
    animation: fadeIn 0.6s ease-out;
}

@keyframes pulse {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.05);
    }
}

.pulse {
    animation: pulse 2s infinite;
}

/* Focus Styles für Accessibility */
.btn:focus,
.nav-link:focus,
.form-input:focus,
.form-textarea:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* High Contrast Mode */
@media (prefers-contrast: high) {
    :root {
        --color-primary: #0000ff;
        --color-secondary: #000000;
        --color-gray-900: #000000;
        --color-gray-100: #ffffff;
    }
    
    .btn {
        border: 2px solid currentColor;
    }
    
    .form-input,
    .form-textarea {
        border-width: 3px;
    }
}

/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

3. JavaScript ES6+ mit DOM-Manipulation

// Modern JavaScript mit ES6+ Features

// DOM Elements auswählen
const elements = {
    // Navigation
    navToggle: document.querySelector('.nav-toggle'),
    navMenu: document.querySelector('#nav-menu'),
    navLinks: document.querySelectorAll('.nav-link'),
    
    // Hero Section
    heroTitle: document.querySelector('.hero-title'),
    heroActions: document.querySelector('.hero-actions'),
    
    // Demo
    canvas: document.querySelector('#demo-canvas'),
    demoButtons: document.querySelectorAll('.demo-btn'),
    colorPicker: document.querySelector('#color-picker'),
    
    // Form
    contactForm: document.querySelector('.contact-form'),
    formInputs: document.querySelectorAll('.form-input'),
    
    // Features
    featureCards: document.querySelectorAll('.feature-card')
};

// State Management
const state = {
    isNavOpen: false,
    currentColor: '#3b82f6',
    isDrawing: false,
    lastX: 0,
    lastY: 0
};

// Utility Functions
const utils = {
    // Debounce für Performance
    debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    },
    
    // Throttle für Events
    throttle(func, limit) {
        let inThrottle;
        return function() {
            const args = arguments;
            const context = this;
            if (!inThrottle) {
                func.apply(context, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    },
    
    // Element mit Animation einblenden
    animateIn(element, animation = 'fade-in') {
        element.style.opacity = '0';
        element.classList.add(animation);
        
        // Force reflow
        element.offsetHeight;
        
        element.style.opacity = '1';
        
        setTimeout(() => {
            element.classList.remove(animation);
            element.style.opacity = '';
        }, 600);
    },
    
    // Smooth Scroll
    smoothScroll(target) {
        const element = document.querySelector(target);
        if (element) {
            element.scrollIntoView({
                behavior: 'smooth',
                block: 'start'
            });
        }
    },
    
    // Local Storage
    saveToLocalStorage(key, data) {
        try {
            localStorage.setItem(key, JSON.stringify(data));
        } catch (error) {
            console.warn('LocalStorage nicht verfügbar:', error);
        }
    },
    
    getFromLocalStorage(key) {
        try {
            const data = localStorage.getItem(key);
            return data ? JSON.parse(data) : null;
        } catch (error) {
            console.warn('LocalStorage Lesefehler:', error);
            return null;
        }
    }
};

// Navigation
class Navigation {
    constructor() {
        this.init();
    }
    
    init() {
        // Mobile Navigation Toggle
        if (elements.navToggle) {
            elements.navToggle.addEventListener('click', this.toggleNav.bind(this));
        }
        
        // Navigation Links
        elements.navLinks.forEach(link => {
            link.addEventListener('click', this.handleNavClick.bind(this));
        });
        
        // Close on Escape
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && state.isNavOpen) {
                this.closeNav();
            }
        });
        
        // Close on outside click
        document.addEventListener('click', (e) => {
            if (state.isNavOpen && !elements.navMenu.contains(e.target) && !elements.navToggle.contains(e.target)) {
                this.closeNav();
            }
        });
    }
    
    toggleNav() {
        state.isNavOpen = !state.isNavOpen;
        this.updateNavUI();
    }
    
    openNav() {
        state.isNavOpen = true;
        this.updateNavUI();
    }
    
    closeNav() {
        state.isNavOpen = false;
        this.updateNavUI();
    }
    
    updateNavUI() {
        elements.navToggle.setAttribute('aria-expanded', state.isNavOpen);
        elements.navMenu.classList.toggle('nav-open', state.isNavOpen);
        
        // Body scroll lock
        document.body.style.overflow = state.isNavOpen ? 'hidden' : '';
    }
    
    handleNavClick(e) {
        e.preventDefault();
        const href = e.target.getAttribute('href');
        
        if (href && href.startsWith('#')) {
            utils.smoothScroll(href);
            this.closeNav();
        }
    }
}

// Canvas Demo
class CanvasDemo {
    constructor(canvas) {
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        this.init();
    }
    
    init() {
        this.setupCanvas();
        this.bindEvents();
        this.drawInitialContent();
    }
    
    setupCanvas() {
        // High DPI Support
        const dpr = window.devicePixelRatio || 1;
        const rect = this.canvas.getBoundingClientRect();
        
        this.canvas.width = rect.width * dpr;
        this.canvas.height = rect.height * dpr;
        
        this.ctx.scale(dpr, dpr);
        
        this.canvas.style.width = rect.width + 'px';
        this.canvas.style.height = rect.height + 'px';
    }
    
    bindEvents() {
        // Mouse Events
        this.canvas.addEventListener('mousedown', this.startDrawing.bind(this));
        this.canvas.addEventListener('mousemove', this.draw.bind(this));
        this.canvas.addEventListener('mouseup', this.stopDrawing.bind(this));
        this.canvas.addEventListener('mouseout', this.stopDrawing.bind(this));
        
        // Touch Events
        this.canvas.addEventListener('touchstart', this.handleTouch.bind(this));
        this.canvas.addEventListener('touchmove', this.handleTouch.bind(this));
        this.canvas.addEventListener('touchend', this.stopDrawing.bind(this));
        
        // Demo Buttons
        elements.demoButtons.forEach(btn => {
            btn.addEventListener('click', this.handleDemoAction.bind(this));
        });
        
        // Color Picker
        elements.colorPicker.addEventListener('change', (e) => {
            state.currentColor = e.target.value;
        });
        
        // Window Resize
        window.addEventListener('resize', utils.debounce(() => {
            this.setupCanvas();
            this.drawInitialContent();
        }, 250));
    }
    
    startDrawing(e) {
        state.isDrawing = true;
        const rect = this.canvas.getBoundingClientRect();
        state.lastX = e.clientX - rect.left;
        state.lastY = e.clientY - rect.top;
    }
    
    draw(e) {
        if (!state.isDrawing) return;
        
        const rect = this.canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        this.ctx.beginPath();
        this.ctx.moveTo(state.lastX, state.lastY);
        this.ctx.lineTo(x, y);
        this.ctx.strokeStyle = state.currentColor;
        this.ctx.lineWidth = 3;
        this.ctx.lineCap = 'round';
        this.ctx.stroke();
        
        state.lastX = x;
        state.lastY = y;
    }
    
    stopDrawing() {
        state.isDrawing = false;
    }
    
    handleTouch(e) {
        e.preventDefault();
        const touch = e.touches[0];
        const mouseEvent = new MouseEvent(e.type === 'touchstart' ? 'mousedown' : 
                                         e.type === 'touchmove' ? 'mousemove' : 'mouseup', {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        this.canvas.dispatchEvent(mouseEvent);
    }
    
    handleDemoAction(e) {
        const action = e.target.dataset.action;
        
        switch (action) {
            case 'clear':
                this.clearCanvas();
                break;
            case 'animate':
                this.animateShapes();
                break;
        }
    }
    
    clearCanvas() {
        const rect = this.canvas.getBoundingClientRect();
        this.ctx.clearRect(0, 0, rect.width, rect.height);
        this.drawInitialContent();
    }
    
    drawInitialContent() {
        const rect = this.canvas.getBoundingClientRect();
        const centerX = rect.width / 2;
        const centerY = rect.height / 2;
        
        // Willkommens-Text
        this.ctx.font = '20px Inter';
        this.ctx.fillStyle = state.currentColor;
        this.ctx.textAlign = 'center';
        this.ctx.fillText('Zeichnen Sie hier!', centerX, centerY);
    }
    
    animateShapes() {
        const rect = this.canvas.getBoundingClientRect();
        let x = 0;
        let y = rect.height / 2;
        let dx = 2;
        let dy = 1;
        let hue = 0;
        
        const animate = () => {
            // Clear trail
            this.ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
            this.ctx.fillRect(0, 0, rect.width, rect.height);
            
            // Draw circle
            this.ctx.beginPath();
            this.ctx.arc(x, y, 20, 0, Math.PI * 2);
            this.ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
            this.ctx.fill();
            
            // Update position
            x += dx;
            y += dy;
            hue += 2;
            
            // Bounce off walls
            if (x > rect.width - 20 || x < 20) dx = -dx;
            if (y > rect.height - 20 || y < 20) dy = -dy;
            
            // Continue animation
            if (hue < 360) {
                requestAnimationFrame(animate);
            }
        };
        
        animate();
    }
}

// Form Validation
class FormValidator {
    constructor(form) {
        this.form = form;
        this.init();
    }
    
    init() {
        this.form.addEventListener('submit', this.handleSubmit.bind(this));
        
        // Real-time validation
        elements.formInputs.forEach(input => {
            input.addEventListener('blur', () => this.validateField(input));
            input.addEventListener('input', () => this.clearError(input));
        });
    }
    
    handleSubmit(e) {
        e.preventDefault();
        
        if (this.validateForm()) {
            this.submitForm();
        } else {
            this.showFirstError();
        }
    }
    
    validateForm() {
        let isValid = true;
        
        elements.formInputs.forEach(input => {
            if (!this.validateField(input)) {
                isValid = false;
            }
        });
        
        return isValid;
    }
    
    validateField(field) {
        const value = field.value.trim();
        const type = field.type;
        const isRequired = field.hasAttribute('required');
        let isValid = true;
        
        // Required validation
        if (isRequired && !value) {
            this.showError(field, 'Dieses Feld ist erforderlich');
            isValid = false;
        }
        
        // Email validation
        if (type === 'email' && value) {
            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            if (!emailRegex.test(value)) {
                this.showError(field, 'Bitte geben Sie eine gültige E-Mail-Adresse ein');
                isValid = false;
            }
        }
        
        // Name validation
        if (field.id === 'name' && value) {
            if (value.length < 2) {
                this.showError(field, 'Der Name muss mindestens 2 Zeichen lang sein');
                isValid = false;
            }
        }
        
        if (isValid) {
            this.clearError(field);
        }
        
        return isValid;
    }
    
    showError(field, message) {
        field.classList.add('error');
        const errorElement = document.getElementById(`${field.id}-error`);
        if (errorElement) {
            errorElement.textContent = message;
            errorElement.style.display = 'block';
        }
    }
    
    clearError(field) {
        field.classList.remove('error');
        const errorElement = document.getElementById(`${field.id}-error`);
        if (errorElement) {
            errorElement.style.display = 'none';
        }
    }
    
    showFirstError() {
        const firstError = this.form.querySelector('.form-input.error');
        if (firstError) {
            firstError.focus();
            firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }
    }
    
    submitForm() {
        const formData = new FormData(this.form);
        const data = Object.fromEntries(formData);
        
        // Simulate API call
        this.showLoading();
        
        setTimeout(() => {
            this.showSuccess();
            this.form.reset();
        }, 1500);
    }
    
    showLoading() {
        const submitBtn = this.form.querySelector('button[type="submit"]');
        submitBtn.disabled = true;
        submitBtn.textContent = 'Wird gesendet...';
    }
    
    showSuccess() {
        const submitBtn = this.form.querySelector('button[type="submit"]');
        submitBtn.disabled = false;
        submitBtn.textContent = 'Gesendet!';
        submitBtn.classList.add('success');
        
        setTimeout(() => {
            submitBtn.textContent = 'Senden';
            submitBtn.classList.remove('success');
        }, 3000);
        
        // Show success message
        this.showMessage('Nachricht erfolgreich gesendet!', 'success');
    }
    
    showMessage(text, type = 'info') {
        const message = document.createElement('div');
        message.className = `message message-${type}`;
        message.textContent = text;
        
        this.form.appendChild(message);
        
        utils.animateIn(message);
        
        setTimeout(() => {
            message.remove();
        }, 5000);
    }
}

// Intersection Observer für Animationen
class ScrollAnimations {
    constructor() {
        this.init();
    }
    
    init() {
        const observerOptions = {
            threshold: 0.1,
            rootMargin: '0px 0px -50px 0px'
        };
        
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    this.animateElement(entry.target);
                    observer.unobserve(entry.target);
                }
            });
        }, observerOptions);
        
        // Beobachte Elemente
        elements.featureCards.forEach(card => {
            observer.observe(card);
        });
        
        // Hero Animation
        if (elements.heroTitle) {
            utils.animateIn(elements.heroTitle);
        }
        
        if (elements.heroActions) {
            setTimeout(() => {
                utils.animateIn(elements.heroActions);
            }, 300);
        }
    }
    
    animateElement(element) {
        utils.animateIn(element);
        
        // Pulse animation für Feature Cards
        if (element.classList.contains('feature-card')) {
            setTimeout(() => {
                element.classList.add('pulse');
                setTimeout(() => {
                    element.classList.remove('pulse');
                }, 2000);
            }, 1000);
        }
    }
}

// App Initialization
class App {
    constructor() {
        this.modules = {};
        this.init();
    }
    
    init() {
        // DOM ready check
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => this.start());
        } else {
            this.start();
        }
    }
    
    start() {
        console.log('🚀 Webentwicklung Demo gestartet');
        
        // Module initialisieren
        this.modules.navigation = new Navigation();
        
        if (elements.canvas) {
            this.modules.canvas = new CanvasDemo(elements.canvas);
        }
        
        if (elements.contactForm) {
            this.modules.form = new FormValidator(elements.contactForm);
        }
        
        this.modules.scrollAnimations = new ScrollAnimations();
        
        // Performance Monitoring
        this.initPerformanceMonitoring();
        
        // Service Worker Registration
        this.registerServiceWorker();
    }
    
    initPerformanceMonitoring() {
        // Page Load Performance
        window.addEventListener('load', () => {
            const perfData = performance.getEntriesByType('navigation')[0];
            const loadTime = perfData.loadEventEnd - perfData.loadEventStart;
            
            console.log(`⚡ Seite geladen in ${loadTime}ms`);
            
            // Langsame Ladezeiten warnen
            if (loadTime > 3000) {
                console.warn('⚠️ Langsame Ladezeit erkannt');
            }
        });
        
        // Largest Contentful Paint
        new PerformanceObserver((list) => {
            const entries = list.getEntries();
            const lastEntry = entries[entries.length - 1];
            console.log(`🎨 Largest Contentful Paint: ${lastEntry.startTime}ms`);
        }).observe({ entryTypes: ['largest-contentful-paint'] });
    }
    
    async registerServiceWorker() {
        if ('serviceWorker' in navigator) {
            try {
                const registration = await navigator.serviceWorker.register('/sw.js');
                console.log('✅ Service Worker registriert:', registration.scope);
            } catch (error) {
                console.log('❌ Service Worker Registrierung fehlgeschlagen:', error);
            }
        }
    }
}

// App starten
const app = new App();

// Export für Module-System
if (typeof module !== 'undefined' && module.exports) {
    module.exports = { App, Navigation, CanvasDemo, FormValidator, ScrollAnimations, utils };
}

4. Service Worker für Offline-Funktionalität

// sw.js - Service Worker für Caching und Offline-Funktionalität

const CACHE_NAME = 'webdev-demo-v1';
const urlsToCache = [
    '/',
    '/index.html',
    '/styles.css',
    '/script.js',
    '/logo.svg',
    '/favicon.svg'
];

// Service Worker Installation
self.addEventListener('install', (event) => {
    console.log('🔧 Service Worker installing...');
    
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then((cache) => {
                console.log('📦 Caching app shell');
                return cache.addAll(urlsToCache);
            })
            .then(() => {
                console.log('✅ App shell cached successfully');
                return self.skipWaiting();
            })
    );
});

// Service Worker Activation
self.addEventListener('activate', (event) => {
    console.log('🔄 Service Worker activating...');
    
    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cacheName) => {
                    if (cacheName !== CACHE_NAME) {
                        console.log('🗑️ Deleting old cache:', cacheName);
                        return caches.delete(cacheName);
                    }
                })
            );
        }).then(() => {
            console.log('✅ Service Worker activated');
            return self.clients.claim();
        })
    );
});

// Fetch Events - Network First mit Fallback zu Cache
self.addEventListener('fetch', (event) => {
    const { request } = event;
    const url = new URL(request.url);
    
    // Nur für HTTP/HTTPS-Anfragen
    if (url.protocol !== 'http:' && url.protocol !== 'https:') {
        return;
    }
    
    event.respondWith(
        caches.match(request)
            .then((response) => {
                // Cache Hit - return cached response
                if (response) {
                    console.log('📋 Serving from cache:', request.url);
                    return response;
                }
                
                // Network Request
                console.log('🌐 Fetching from network:', request.url);
                return fetch(request)
                    .then((response) => {
                        // Check if response is valid
                        if (!response || response.status !== 200 || response.type !== 'basic') {
                            return response;
                        }
                        
                        // Clone response for caching
                        const responseToCache = response.clone();
                        
                        // Cache successful responses
                        if (shouldCache(request)) {
                            caches.open(CACHE_NAME)
                                .then((cache) => {
                                    console.log('💾 Caching new resource:', request.url);
                                    cache.put(request, responseToCache);
                                });
                        }
                        
                        return response;
                    })
                    .catch(() => {
                        // Network failed - try cache
                        console.log('❌ Network failed, trying cache for:', request.url);
                        return caches.match(request);
                    });
            })
    );
});

// Helper function to determine if request should be cached
function shouldCache(request) {
    const url = new URL(request.url);
    
    // Don't cache API calls or external resources
    if (url.pathname.startsWith('/api/') || url.origin !== self.location.origin) {
        return false;
    }
    
    // Cache static assets
    const staticExtensions = ['.css', '.js', '.svg', '.png', '.jpg', '.jpeg', '.webp'];
    const hasStaticExtension = staticExtensions.some(ext => url.pathname.endsWith(ext));
    
    return hasStaticExtension || url.pathname === '/';
}

// Background Sync für Offline-Aktionen
self.addEventListener('sync', (event) => {
    if (event.tag === 'background-sync') {
        console.log('🔄 Background sync triggered');
        
        event.waitUntil(
            // Hier könnten Offline-Aktionen synchronisiert werden
            new Promise((resolve) => {
                setTimeout(() => {
                    console.log('✅ Background sync completed');
                    resolve();
                }, 1000);
            })
        );
    }
});

// Push Notifications
self.addEventListener('push', (event) => {
    console.log('📨 Push message received');
    
    const options = {
        body: event.data.text(),
        icon: '/logo.svg',
        badge: '/favicon.svg',
        vibrate: [100, 50, 100],
        data: {
            dateOfArrival: Date.now(),
            primaryKey: 1
        },
        actions: [
            {
                action: 'explore',
                title: 'Explore',
                icon: '/images/checkmark.png'
            },
            {
                action: 'close',
                title: 'Close',
                icon: '/images/xmark.png'
            }
        ]
    };
    
    event.waitUntil(
        self.registration.showNotification('WebDev Demo', options)
    );
});

// Notification Click Handling
self.addEventListener('notificationclick', (event) => {
    console.log('🔔 Notification clicked');
    
    event.notification.close();
    
    if (event.action === 'explore') {
        event.waitUntil(
            clients.openWindow('/')
        );
    }
});

HTML5 Semantic Elements Übersicht

ElementBeschreibungVerwendung
headerKopfbereichLogo, Navigation
navNavigationMenü, Links
mainHauptinhaltPrimärer Inhalt
sectionAbschnittThematische Blöcke
articleArtikelEigenständige Inhalte
asideSeitenleisteZusatzinformationen
footerFußbereichCopyright, Links

CSS3 Layout-Techniken

Flexbox

.container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
}

.item {
    flex: 1 1 300px;
    margin: 1rem;
}

Grid

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 2rem;
}

Container Queries

@container (min-width: 400px) {
    .card {
        display: grid;
        grid-template-columns: 1fr 2fr;
    }
}

JavaScript ES6+ Features

Arrow Functions

const add = (a, b) => a + b;
const users = data.map(item => item.name);

Template Literals

const message = `Hallo ${name}, du hast ${count} Nachrichten`;

Destructuring

const {name, email} = user;
const [first, second] = array;

Spread/Rest

const newArray = [...oldArray, newItem];
const sum = (...numbers) => numbers.reduce((a, b) => a + b);

Async/Await

async function fetchData() {
    try {
        const response = await fetch('/api/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error:', error);
    }
}

Responsive Design Breakpoints

/* Mobile First Approach */
/* Small Phones */
@media (min-width: 320px) { }

/* Large Phones */
@media (min-width: 480px) { }

/* Tablets */
@media (min-width: 768px) { }

/* Desktop */
@media (min-width: 1024px) { }

/* Large Desktop */
@media (min-width: 1200px) { }

DOM-Manipulation Methoden

MethodeBeschreibungBeispiel
querySelectorElement auswählendocument.querySelector('.class')
createElementElement erstellendocument.createElement('div')
appendChildElement hinzufügenparent.appendChild(child)
classListKlassen verwaltenelement.classList.add('active')
addEventListenerEvent bindenelement.addEventListener('click', handler)
setAttributeAttribut setzenelement.setAttribute('data-id', '123')

CSS3 Animationen

Transitions

.button {
    transition: all 0.3s ease-in-out;
}

.button:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

Keyframes

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

.element {
    animation: fadeIn 0.6s ease-out;
}

Web Performance Optimierung

Lazy Loading

// Images
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            img.removeAttribute('data-src');
            imageObserver.unobserve(img);
        }
    });
});

images.forEach(img => imageObserver.observe(img));

Code Splitting

// Dynamic Import
const loadModule = async () => {
    const module = await import('./heavy-module.js');
    module.doSomething();
};

Accessibility Best Practices

Semantic HTML

<nav aria-label="Hauptnavigation">
    <ul>
        <li><a href="#" aria-current="page">Home</a></li>
        <li><a href="#">About</a></li>
    </ul>
</nav>

ARIA Attributes

<button aria-expanded="false" aria-controls="menu">
    Menü
</button>
<div id="menu" hidden>
    <!-- Menu content -->
</div>

Keyboard Navigation

.focusable:focus {
    outline: 2px solid #3b82f6;
    outline-offset: 2px;
}

Vorteile und Nachteile

Vorteile moderner Webentwicklung

  • Cross-Plattform: Ein Code für alle Geräte
  • Responsive: Optimale Darstellung überall
  • Interaktiv: Rich User Experiences
  • SEO-freundlich: Suchmaschinenoptimiert
  • Zugänglich: Barrierefrei unterstützt

Nachteile

  • Komplexität: Viele Technologien zu lernen
  • Browser-Kompatibilität: Unterschiedliche Unterstützung
  • Performance: Optimierung erforderlich
  • Sicherheit: Schutzmechanismen nötig

Häufige Prüfungsfragen

  1. Was ist der Unterschied zwischen HTML, CSS und JavaScript? HTML strukturiert Inhalt, CSS gestaltet Aussehen, JavaScript ermöglicht Interaktivität.

  2. Erklären Sie Responsive Design! Anpassung der Darstellung an verschiedene Bildschirmgrößen durch Media Queries und flexible Layouts.

  3. Was ist das DOM und wie wird es manipuliert? DOM ist die programmierbare Repräsentation des HTML-Dokuments. Manipulation durch JavaScript-Methoden wie querySelector, createElement, appendChild.

  4. Wann verwendet man Flexbox vs Grid? Flexbox für eindimensionale Layouts (Zeilen/Spalten), Grid für zweidimensionale Layouts.

Wichtigste Quellen

  1. https://developer.mozilla.org/de/docs/Web
  2. https://www.w3.org/TR/html5/
  3. https://www.w3.org/Style/CSS/
Zurück zum Blog
Share: