kap1 web_eng (104 → 57 slides): kurs-intro + prüfungsleistung-übersicht, internet-timeline (4 milestones), URL→pixel-7-schritte, HTTP, onboarding (node 24 LTS via fnm, brew/winget paket-manager, VS Code/Chromium/Hoppscotch, git setup mit SSH-key, projekt-skeleton), HTML (anatomie, self-closing, grundgerüst, semantik-tabelle, native elemente details/dialog/input-types), A11y volle tiefe (BFSG+EAA 28.06.2025, WCAG-POUR, Perceivable/Operable/Understandable/Robust einzeln mit code, testen mit lighthouse/axe/manuell), CSS-vorschau (anatomie/selektoren/spezifizität/box-model/farben/einheiten/pseudos), JS-vorschau (ECMAScript-timeline/grundlagen/DOM/fetch), frameworks-übersicht (react/vue/svelte/astro counter-vergleich), build-tools/rendering-modi, selbstlernen erste-eigene-seite kap2 css_extended (13 → 28 slides): box-model + box-sizing global, flexbox basics+achsen+item-properties+typische-patterns, grid basics+areas+auto-layout, flexbox-vs-grid tabelle, mobile-first media queries, viewport-meta, fluid sizing mit clamp(), transitions (was performant), keyframe-animationen, prefers-reduced-motion pflicht, CSS-variablen + dark-mode-pattern, CSS functions (calc/clamp/gradient/oklch/filter), CSS-frameworks tabelle + tailwind pro/contra, selbstlernen flexboxfroggy+cssgridgarden kap3 nodejs_basics (~22 → 20 slides): was-ist-node + warum-node-tabelle, fnm versions-manager + node 24 LTS + .nvmrc, npm init + package.json (mit type:module), ESM modern + CJS legacy, built-in modules (node: prefix), HTTP-server eingebaut + express, REST mit express (GET/POST/PUT/DELETE-pattern), alternative frameworks tabelle (fastify/hono/koa), routing-pattern mit Router, fetch global ab node 18, error-handling res.ok, environment variables mit dotenv + niemals committen, selbstlernen mini-API kap4 nodejs_advanced (~24 → 22 slides): synchron-vs-asynchron, promise then-vs-async/await, sequenziell-vs-parallel + Promise.all, promise-methoden tabelle (all/allSettled/race/any), fs/promises lesen+schreiben, streams pipeline für große dateien, DB-übersicht SQLite/Postgres/MongoDB/Redis, better-sqlite3 prepared statements, ORM-übersicht (drizzle/prisma/knex), CRUD-pattern express+sqlite, auth-strategien tabelle, bcrypt für passwörter, JWT-pattern mit httpOnly+secure cookie, try/catch + error-klassen, globaler express-error-handler, selbstlernen REST+DB+auth kap5 testing (~23 → 23 slides): test-pyramide 70%/20%/10%, vitest setup + describe/it/expect, AAA-pattern, matchers tabelle, TDD red-green-refactor mit konkretem beispiel, supertest für API-integration, test-DB :memory: + lifecycle hooks, mocking mit vi.spyOn (sparsam), playwright E2E mit role-based-locators, E2E-vs-unit tradeoffs, coverage realistisch (80% gut), CI mit github-actions, selbstlernen tests-schreiben kap6 typescript (~30 → 19 slides): was-ist-TS + warum-tabelle, setup mit tsx + tsconfig.json + strict:true, basis-typen + any vermeiden, object-typen + interfaces + type-aliases, function-typen (Promise<T>), union + discriminated union + intersection, generics + constraints, built-in generics (Partial/Omit/Record), typ-inference (nicht über-annotieren), typen für REST-API mit express, zod runtime-validation + z.infer, any-vs-unknown-vs-never, best practices, selbstlernen API-zu-TS-migration kap7 docker (~24 → 24 slides): auf-meinem-rechner-läufts problem, container-vs-VM tabelle, docker basics (image/container/dockerfile/registry), dockerfile hallo-welt, schichten + cache-optimierung, multi-stage build, base-image-größen tabelle (alpine ~180MB vs node ~1.1GB), .dockerignore, compose.yml beispiel, compose-commands, networking (service-namen als hostnamen), volumes (named vs bind), env+secrets, github-actions docker-build, registry-übersicht, health-checks, best-practices, selbstlernen app-dockerizen kap8 best_practices (~30 → 28 slides): sinnvolle commits + conventional commits format, .gitignore template, branches+PRs workflow, README-template mit 6 sektionen, SOLID 5 prinzipien tabelle, S-single-responsibility + D-dependency-inversion mit code, 12-factor wichtigste (codebase/deps/config/processes/disposability), factor 3 config-in-env, factor 6 stateless-processes, SemVer MAJOR.MINOR.PATCH, package.json caret/tilde/exakt, code-reviews geben+nehmen + checkliste, doku-quellen tabelle (MDN/nodejs/npm/tc39/caniuse), stack-overflow gut-nutzen, AI-assistenten pro/contra (verstehen-nicht-kopieren), selbstlernen projekt-hygiene-check build geht durch alle 8 kapitel-html+pdf render-spot-check: cover-slide-dark-mode-invert, git-setup code-syntax-highlight, css-anatomie code-blocks — alle sauber kein deploy, nur build+verify
832 lines
17 KiB
Markdown
832 lines
17 KiB
Markdown
---
|
||
marp: true
|
||
theme: gaia
|
||
paginate: true
|
||
backgroundColor: #fff
|
||
header: "Web Engineering – DHBW Stuttgart"
|
||
footer: "Michael Czechowski – SoSe 2026"
|
||
title: Web Engineering
|
||
---
|
||
|
||
<style>
|
||
:root { --color-foreground: #1a1a2e; --color-highlight: #d63384; --color-dimmed: #4a4a6a; }
|
||
section.invert { --color-foreground: #fff; }
|
||
section { font-size: 1.4rem; }
|
||
h1 { color: #a02060; }
|
||
section.invert h1 { color: #fff; }
|
||
h2 { color: #1f2937; }
|
||
section.invert h2 { color: #f48fb1; }
|
||
pre { background: #0f0f23; color: #f48fb1; border-radius: 8px; border-left: 3px solid #d63384; }
|
||
pre code { background: transparent; color: inherit; }
|
||
code { background: #1a1a2e; color: #f48fb1; padding: 0.15em 0.4em; border-radius: 4px; }
|
||
a { color: var(--color-highlight); }
|
||
</style>
|
||
|
||
<!-- _class: invert -->
|
||
<!-- _header: '' -->
|
||
<!-- _backgroundColor: #000 -->
|
||
|
||

|
||
|
||
# Web Engineering
|
||
|
||
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
|
||
**Sommersemester 2026**
|
||
|
||
---
|
||
|
||
# Ressourcen zum Selbstlernen
|
||
|
||
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
|
||
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
|
||
- **MDN** — [developer.mozilla.org](https://developer.mozilla.org/de/)
|
||
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
|
||
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Herzlich Willkommen!
|
||
|
||
## 1. Sitzung: 08.05.2026
|
||
|
||
---
|
||
|
||
# Über mich
|
||
|
||

|
||
|
||
Michael Czechowski
|
||
|
||
- Software Engineer, ehemals freischaffend
|
||
- Lektor an HdM Stuttgart + DHBW
|
||
- librete.ch
|
||
|
||
---
|
||
|
||
# Vorlesungsplan (Auszug)
|
||
|
||
| Termin | Thema |
|
||
|--------|-------|
|
||
| 1 | Web Engineering (heute) |
|
||
| 2 | CSS Extended |
|
||
| 3 | Node.js Basics |
|
||
| 4 | Node.js Advanced |
|
||
| 5 | Testing |
|
||
| 6 | TypeScript |
|
||
| 7 | Docker |
|
||
| 8 | Best Practices |
|
||
|
||
---
|
||
|
||
# Prüfungsleistung — 75 P + 10 Bonus
|
||
|
||
**Projekt-Abgabe** statt Klausur.
|
||
|
||
| Bereich | Punkte |
|
||
|---------|-------:|
|
||
| Projekt-Struktur + README | 10 |
|
||
| Code-Qualität | 15 |
|
||
| Git-Hygiene | 10 |
|
||
| Tests | 10 |
|
||
| Docker | 10 |
|
||
| HTTP / API | 10 |
|
||
| Frontend + A11y | 10 |
|
||
| Präsentation + Bonus | 5 + 10 |
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Kontext: was ist „das Web"?
|
||
|
||
---
|
||
|
||
# Internet-Timeline
|
||
|
||
| Jahr | Was |
|
||
|------|-----|
|
||
| 1969 | ARPANET — 4 Knoten |
|
||
| 1971 | Email (Ray Tomlinson, `@`) |
|
||
| 1983 | TCP/IP-Standard |
|
||
| **1989** | **WWW** (Berners-Lee, CERN) |
|
||
| 1993 | Mosaic-Browser → Web wird populär |
|
||
|
||
---
|
||
|
||
# Das WWW (1989)
|
||
|
||
**Tim Berners-Lee am CERN.** Drei Standards:
|
||
|
||
- **HTTP** — Protokoll
|
||
- **HTML** — Format
|
||
- **URL** — Adresse
|
||
|
||
Patentfrei → Web konnte explodieren.
|
||
|
||
---
|
||
|
||
# Heute: physische Infrastruktur
|
||
|
||
- ~400 Unterseekabel
|
||
- 1,3 Mio km Glasfaser weltweit
|
||
- DE-CIX Frankfurt: größter Internet-Knoten (~12 Tbit/s)
|
||
|
||
Das Web ist **physisch.**
|
||
|
||
---
|
||
|
||
# URL → Pixel in 7 Schritten
|
||
|
||
1. **URL parsen** — Schema, Host, Port, Path
|
||
2. **DNS-Lookup** — Host-Name → IP
|
||
3. **TCP-Handshake** mit Server
|
||
4. **TLS-Handshake** (https)
|
||
5. **HTTP-Request** senden
|
||
6. Server antwortet mit **HTML + CSS + JS**
|
||
7. Browser **parsed + rendert** → Pixel
|
||
|
||
---
|
||
|
||
# HTTP — Anatomie
|
||
|
||
```http
|
||
GET /index.html HTTP/1.1
|
||
Host: librete.ch
|
||
User-Agent: Mozilla/5.0 ...
|
||
|
||
HTTP/1.1 200 OK
|
||
Content-Type: text/html
|
||
Content-Length: 1234
|
||
|
||
<!DOCTYPE html>...
|
||
```
|
||
|
||
**Statuscodes:** 200 OK · 301 Moved · 404 Not Found · 500 Server Error
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Onboarding
|
||
## Tools, Runtimes, Workflows
|
||
|
||
---
|
||
|
||
# Werkzeuge & Betriebssystem
|
||
|
||
| Bereich | Empfehlung |
|
||
|---------|------------|
|
||
| Editor | **VS Code** · JetBrains (edu lizenz frei) |
|
||
| Browser | **Chromium / Firefox** |
|
||
| Terminal | macOS Terminal · Linux Terminal · Windows Terminal |
|
||
| Paket-Manager | macOS: brew · Linux: apt/dnf · Windows: winget/scoop/choco |
|
||
| Versions-Control | Git + GitHub/Gitea |
|
||
|
||
---
|
||
|
||
# Node.js installieren
|
||
|
||
**Best Practice:** Versions-Manager statt Direkt-Install.
|
||
|
||
| OS | Empfehlung |
|
||
|----|------------|
|
||
| macOS | `brew install fnm` → `fnm install --lts` |
|
||
| Linux | `curl -fsSL https://fnm.vercel.app/install \| bash` |
|
||
| Windows | `winget install Schniz.fnm` |
|
||
|
||
**Aktuelle LTS:** Node 24.
|
||
|
||
---
|
||
|
||
# Warum Versions-Manager?
|
||
|
||
**Direkt-Install** (z.B. `brew install node`) bringt Probleme:
|
||
- Projekt-A braucht Node 18, Projekt-B braucht Node 22 → Konflikt
|
||
- Update bricht alte Projekte
|
||
- Kein automatisches Switching pro Projekt
|
||
|
||
**fnm / nvm / volta:** pro Projekt Node-Version, automatisch via `.nvmrc`.
|
||
|
||
---
|
||
|
||
# Alternative Runtimes
|
||
|
||
| Runtime | Stärke |
|
||
|---------|--------|
|
||
| **Node** | Standard, größtes Ökosystem |
|
||
| **Deno** | Sicher by default, TypeScript nativ |
|
||
| **Bun** | Schnell, all-in-one (runtime + bundler + tester) |
|
||
|
||
Für DHBW-Kurs: **Node 24 LTS.**
|
||
|
||
---
|
||
|
||
# Browser DevTools
|
||
|
||
**F12** öffnet das Power-Tool jeder Webentwicklung.
|
||
|
||
| Tab | Wofür |
|
||
|-----|-------|
|
||
| Elements | DOM-Baum inspizieren + live editieren |
|
||
| Console | JS ausführen, Errors lesen |
|
||
| Network | HTTP-Requests sehen, Latenz |
|
||
| Performance | Render + Memory profilen |
|
||
| Lighthouse | A11y · SEO · Perf-Audit |
|
||
|
||
---
|
||
|
||
# HTTP-Clients
|
||
|
||
Tools zum Testen von APIs:
|
||
|
||
- **curl** — CLI, überall
|
||
- **Hoppscotch** — Browser, Open Source
|
||
- **Postman** — GUI, kommerziell
|
||
- **VS Code REST Client** — Plugin
|
||
|
||
---
|
||
|
||
# Git Setup
|
||
|
||
```sh
|
||
git config --global user.name "Dein Name"
|
||
git config --global user.email "du@dhbw.de"
|
||
git config --global init.defaultBranch main
|
||
git config --global core.autocrlf input # Windows: true
|
||
```
|
||
|
||
**SSH-Key** für GitHub/Gitea ohne Passwort-Prompt:
|
||
```sh
|
||
ssh-keygen -t ed25519 -C "du@dhbw.de"
|
||
cat ~/.ssh/id_ed25519.pub # zu GitHub kopieren
|
||
```
|
||
|
||
---
|
||
|
||
# Projekt-Skeleton
|
||
|
||
```
|
||
mein-projekt/
|
||
├── .git/
|
||
├── .gitignore # node_modules/, .env, build/
|
||
├── README.md # was, wie, warum
|
||
├── package.json # npm metadata + scripts
|
||
├── src/ # eigener Code
|
||
├── public/ # statische Assets (für Web)
|
||
├── tests/ # Unit + Integration
|
||
└── Dockerfile # für Container-Deploy
|
||
```
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# HTML
|
||
## Hypertext Markup Language
|
||
|
||
---
|
||
|
||
# Was ist HTML?
|
||
|
||
**Tim Berners-Lee, 1989.** Struktur-Format des Webs.
|
||
|
||
**Syntax:** Tags mit Attributen umfassen Inhalt.
|
||
**Browser parst HTML** → DOM (Document Object Model) → rendert.
|
||
|
||
Plain-Text mit Tags. Lesbar mit jedem Editor.
|
||
|
||
---
|
||
|
||
# HTML-Anatomie
|
||
|
||
```html
|
||
<a href="https://librete.ch" target="_blank">Mein Link</a>
|
||
```
|
||
|
||
- `<a` — Opening-Tag mit Tag-Namen
|
||
- `href="..."` — Attribut (Name + Wert)
|
||
- `Mein Link` — Inhalt
|
||
- `</a>` — Closing-Tag
|
||
- Alles zusammen = **Element**
|
||
|
||
---
|
||
|
||
# Self-closing Tags
|
||
|
||
```html
|
||
<img src="foto.jpg" alt="Sonnenuntergang">
|
||
<br>
|
||
<input type="text" name="username">
|
||
<meta charset="utf-8">
|
||
<link rel="stylesheet" href="style.css">
|
||
```
|
||
|
||
Kein Closing-Tag. Inhalt aus Attributen + (für `<input>`) User-Eingabe.
|
||
|
||
---
|
||
|
||
# Document-Grundgerüst
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Meine Seite</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body>
|
||
<h1>Hallo Welt</h1>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
---
|
||
|
||
# Semantische HTML-Tags
|
||
|
||
| Tag | Bedeutung |
|
||
|-----|-----------|
|
||
| `<header>` | Kopfbereich (Logo, Nav) |
|
||
| `<nav>` | Navigation |
|
||
| `<main>` | Hauptinhalt |
|
||
| `<section>` | Thematischer Abschnitt |
|
||
| `<article>` | eigenständiger Inhalt |
|
||
| `<aside>` | Seiten-Inhalt |
|
||
| `<footer>` | Fußbereich |
|
||
|
||
**Pflicht** für SEO + A11y + Wartbarkeit.
|
||
|
||
---
|
||
|
||
# Native HTML-Elemente — nicht vergessen!
|
||
|
||
Bevor du eine Custom-Component baust: **gibt's das schon nativ?**
|
||
|
||
| Element | Was |
|
||
|---------|-----|
|
||
| `<details>` / `<summary>` | Accordion ohne JS |
|
||
| `<dialog>` | Modal mit Native Backdrop |
|
||
| `<input type="date">` | Date-Picker, native, A11y |
|
||
| `<input type="color">` | Color-Picker |
|
||
| `<input type="range">` | Slider |
|
||
| `<datalist>` | Autocomplete-Vorschläge |
|
||
| `<progress>` | Lade-Balken |
|
||
|
||
**Faustregel:** Native zuerst, Custom nur wenn nötig.
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Barrierefreiheit
|
||
## A11y — Accessibility
|
||
|
||
---
|
||
|
||
# BFSG + EAA — Pflicht ab 28.06.2025
|
||
|
||
**Barrierefreiheitsstärkungsgesetz** (DE) setzt **European Accessibility Act** (EU) um.
|
||
|
||
**Pflicht:**
|
||
- Online-Shops, Banken, Versicherungen
|
||
- E-Books, Buchungssysteme
|
||
- Smartphone-Apps mit kommerziellem Bezug
|
||
|
||
**Ausnahme:** < 10 Mitarbeiter + < 2 Mio € Umsatz.
|
||
|
||
**Strafe:** bis 100.000 € Bußgeld + Klage durch Behindertenverbände.
|
||
|
||
---
|
||
|
||
# Wie nutzen Menschen das Web?
|
||
|
||
- **Sehen:** Screen-Reader (NVDA, JAWS, VoiceOver)
|
||
- **Hören:** Untertitel + Transkripte
|
||
- **Motorik:** Tastatur statt Maus, Switch-Control
|
||
- **Kognitiv:** klare Sprache, viel Whitespace
|
||
- **Vorübergehend:** Sonne im Bildschirm, gebrochener Arm, ÖPNV-Lärm
|
||
|
||
~10 % der Bevölkerung haben relevante Beeinträchtigungen. *Du auch — irgendwann.*
|
||
|
||
---
|
||
|
||
# WCAG · 4 Prinzipien (POUR)
|
||
|
||
| Prinzip | Was |
|
||
|---------|-----|
|
||
| **P**erceivable | Alt-Text · Untertitel · Kontrast |
|
||
| **O**perable | Keyboard · Skip-Links |
|
||
| **U**nderstandable | klare Sprache · Fehler-Hilfe |
|
||
| **R**obust | semantisches HTML · Standards-konform |
|
||
|
||
**WCAG 2.1 Level AA** = Mindest-Standard für BFSG.
|
||
|
||
---
|
||
|
||
# Perceivable — wahrnehmbar
|
||
|
||
- **Alt-Text** für jedes Bild (`<img alt="...">`)
|
||
- **Untertitel** für jedes Video
|
||
- **Kontrast 4.5:1** für Text (Level AA)
|
||
- **Skalierbar** bis 200 %
|
||
|
||
```html
|
||
<img src="foto.jpg" alt="Sonnenuntergang am Bodensee">
|
||
<!-- LEER alt="" für rein dekorative Bilder -->
|
||
```
|
||
|
||
---
|
||
|
||
# Operable — bedienbar
|
||
|
||
- Alle interaktiven Elemente **mit Tastatur erreichbar**
|
||
- **Fokus sichtbar** (`:focus-visible` mit Outline)
|
||
- **Skip-Links** für Screen-Reader (Hauptnav überspringen)
|
||
- **Genug Zeit** für Aufgaben (Auto-Logout pausierbar)
|
||
|
||
```css
|
||
button:focus-visible {
|
||
outline: 3px solid hotpink;
|
||
outline-offset: 2px;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
# Understandable — verständlich
|
||
|
||
- **Lese-Niveau** angemessen (Level AA: 9. Klasse)
|
||
- **Klare Fehlermeldungen** (was war falsch, wie korrigieren)
|
||
- **Konsistente Navigation** (Header bleibt gleich)
|
||
- **`lang`-Attribut** im html-Element
|
||
|
||
```html
|
||
<html lang="de">
|
||
<p lang="en">This sentence is in English.</p>
|
||
</html>
|
||
```
|
||
|
||
---
|
||
|
||
# Robust — Tech-stabil
|
||
|
||
- **Semantisches HTML** statt div-Suppe
|
||
- **ARIA** *nur als Ergänzung*, nicht als Ersatz
|
||
- **Standards-konform** (Validator: validator.w3.org)
|
||
|
||
```html
|
||
<!-- ❌ semantisch falsch -->
|
||
<div onclick="...">Klick</div>
|
||
|
||
<!-- ✓ semantisch korrekt -->
|
||
<button onclick="...">Klick</button>
|
||
```
|
||
|
||
---
|
||
|
||
# A11y-Testen — Werkzeuge
|
||
|
||
| Tool | Was |
|
||
|------|-----|
|
||
| **Lighthouse** (Chrome DevTools) | automatischer Audit |
|
||
| **axe DevTools** | Plugin, präziser |
|
||
| **WAVE** | Browser-Plugin, visuell |
|
||
| **Manuell** | Maus weglegen, nur Tab |
|
||
| **Screen-Reader** | macOS: VoiceOver (Cmd+F5) · Win: NVDA |
|
||
|
||
**Automatisierte Tools** finden ~30 %. Rest = manuell.
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# CSS
|
||
## Cascading Style Sheets
|
||
|
||
*(Vertiefung in Kap 2 — CSS Extended)*
|
||
|
||
---
|
||
|
||
# CSS einbinden
|
||
|
||
```html
|
||
<!-- External (best practice) -->
|
||
<link rel="stylesheet" href="./style.css">
|
||
|
||
<!-- Internal -->
|
||
<style>
|
||
body { background: #fafafa; }
|
||
</style>
|
||
|
||
<!-- Inline (vermeiden) -->
|
||
<button style="background: hotpink">Klick</button>
|
||
```
|
||
|
||
---
|
||
|
||
# CSS-Anatomie
|
||
|
||
```css
|
||
button {
|
||
background-color: hotpink;
|
||
padding: 10px 20px;
|
||
border-radius: 8px;
|
||
}
|
||
```
|
||
|
||
- `button` = **Selektor** (welche Elemente)
|
||
- `background-color` = **Property**
|
||
- `hotpink` = **Value**
|
||
- alles in `{ }` = **Declaration Block**
|
||
|
||
---
|
||
|
||
# Selektoren
|
||
|
||
| Selektor | Was |
|
||
|----------|-----|
|
||
| `p` | alle `<p>` |
|
||
| `.btn` | alle mit `class="btn"` |
|
||
| `#header` | das Element mit `id="header"` |
|
||
| `button:hover` | Button beim Hover |
|
||
| `nav > a` | direkte `<a>` unter `<nav>` |
|
||
| `*` | alles |
|
||
|
||
---
|
||
|
||
# Spezifizität — wer gewinnt?
|
||
|
||
```css
|
||
p { color: blue; } /* 1 */
|
||
.notice { color: red; } /* 10 */
|
||
#warn { color: green; } /* 100 */
|
||
[style] /* inline */ /* 1000 */
|
||
```
|
||
|
||
**Inline > ID > Klasse > Element.** Bei Gleichstand: **letzte Regel.**
|
||
|
||
`!important` umgeht alles — *vermeiden.*
|
||
|
||
---
|
||
|
||
# Box-Model
|
||
|
||
```
|
||
┌──────────────────────┐
|
||
│ margin │
|
||
│ ┌────────────────┐ │
|
||
│ │ border │ │
|
||
│ │ ┌──────────┐ │ │
|
||
│ │ │ padding │ │ │
|
||
│ │ │ content │ │ │
|
||
│ │ └──────────┘ │ │
|
||
│ └────────────────┘ │
|
||
└──────────────────────┘
|
||
```
|
||
|
||
**Best Practice:** `* { box-sizing: border-box; }` global.
|
||
|
||
---
|
||
|
||
# Farben
|
||
|
||
| Notation | Beispiel |
|
||
|----------|----------|
|
||
| Hex | `#FF5733` |
|
||
| RGB | `rgb(255, 87, 51)` |
|
||
| RGBA | `rgb(255, 87, 51, 0.5)` |
|
||
| HSL | `hsl(11, 100%, 60%)` |
|
||
| OKLCH (modern) | `oklch(0.7 0.2 30)` |
|
||
| Schlüsselwort | `hotpink`, `tomato` |
|
||
|
||
---
|
||
|
||
# Einheiten
|
||
|
||
| Einheit | Was |
|
||
|---------|-----|
|
||
| `px` | Pixel, fix |
|
||
| `rem` | relativ zu Wurzel-Font (16 px default) |
|
||
| `em` | relativ zu Eltern-Font |
|
||
| `%` | relativ zur Eltern-Größe |
|
||
| `vw` / `vh` | Viewport-Breite/-Höhe |
|
||
| `ch` | Breite eines Zeichens |
|
||
|
||
**Faustregel:** Font + Spacing in `rem`. Layout in `%` oder `fr`.
|
||
|
||
---
|
||
|
||
# Pseudo-Klassen & -Elemente
|
||
|
||
```css
|
||
/* Pseudo-Klassen (Zustand) */
|
||
a:hover { color: hotpink; }
|
||
input:focus { outline: 2px solid; }
|
||
button:disabled { opacity: 0.5; }
|
||
li:nth-child(2n) { background: #eee; }
|
||
|
||
/* Pseudo-Elemente (Virtuelles) */
|
||
p::first-letter { font-size: 2em; }
|
||
.tooltip::after { content: " 💡"; }
|
||
```
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# JavaScript
|
||
## Die Sprache des Webs
|
||
|
||
*(Vertiefung in Kap 3+4 — Node.js)*
|
||
|
||
---
|
||
|
||
# ECMAScript
|
||
|
||
**ECMA International** (Schweiz) standardisiert die Sprache.
|
||
|
||
| Version | Jahr | Highlight |
|
||
|---------|------|-----------|
|
||
| ES5 | 2009 | strict mode, JSON |
|
||
| ES6 / 2015 | 2015 | `let` `const`, arrow, classes, modules |
|
||
| ES2017 | 2017 | async/await |
|
||
| ES2020 | 2020 | optional chaining `?.` |
|
||
| ES15 | 2024 | aktuell |
|
||
|
||
---
|
||
|
||
# JavaScript-Grundlagen
|
||
|
||
```javascript
|
||
// Variablen
|
||
const name = "Ada";
|
||
let alter = 56;
|
||
|
||
// Funktionen
|
||
const begrüßen = (name) => `Hallo ${name}`;
|
||
|
||
// Arrays + Objects
|
||
const fruits = ["A", "B"];
|
||
const user = { name: "Ada", admin: true };
|
||
|
||
// Schleifen
|
||
fruits.map(f => f.toUpperCase());
|
||
|
||
// async
|
||
async function laden() {
|
||
const res = await fetch('/api');
|
||
return res.json();
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
# DOM Manipulation
|
||
|
||
```javascript
|
||
// Element finden
|
||
const btn = document.querySelector('#myBtn');
|
||
|
||
// Inhalt ändern
|
||
btn.textContent = 'Neu';
|
||
btn.classList.add('active');
|
||
|
||
// Event-Handler
|
||
btn.addEventListener('click', () => {
|
||
console.log('Klick!');
|
||
});
|
||
|
||
// Element erzeugen
|
||
const li = document.createElement('li');
|
||
li.textContent = 'Item';
|
||
document.querySelector('ul').appendChild(li);
|
||
```
|
||
|
||
---
|
||
|
||
# Fetch + JSON
|
||
|
||
```javascript
|
||
// GET
|
||
const res = await fetch('https://api.github.com/users/torvalds');
|
||
const data = await res.json();
|
||
console.log(data.public_repos);
|
||
|
||
// POST
|
||
await fetch('/api/posts', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ title: 'Hallo', body: '...' })
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Frameworks-Vorschau
|
||
|
||
---
|
||
|
||
# Framework-Landschaft
|
||
|
||
| Framework | Typ | Use-Case |
|
||
|-----------|-----|----------|
|
||
| **React** | Library | dominant, große Community |
|
||
| **Vue 3** | Framework | sanfter Einstieg |
|
||
| **Svelte** | Compiler | kein Virtual DOM, kleines Bundle |
|
||
| **Astro** | Hybrid | Content-First, Multi-Framework |
|
||
| **Angular** | Framework | Enterprise, Google |
|
||
|
||
Alle: **Komponenten + reaktive State + Re-Render.**
|
||
|
||
---
|
||
|
||
# Counter — vier Wege
|
||
|
||
**Vanilla JS:**
|
||
```javascript
|
||
let count = 0;
|
||
btn.onclick = () => { count++; display.textContent = count; };
|
||
```
|
||
|
||
**React (JSX):**
|
||
```jsx
|
||
function Counter() {
|
||
const [count, setCount] = useState(0);
|
||
return <button onClick={() => setCount(count + 1)}>{count}</button>;
|
||
}
|
||
```
|
||
|
||
**Vue 3 (Composition):**
|
||
```vue
|
||
<script setup>const count = ref(0)</script>
|
||
<template><button @click="count++">{{ count }}</button></template>
|
||
```
|
||
|
||
**Svelte:**
|
||
```svelte
|
||
<script>let count = 0</script>
|
||
<button on:click={() => count++}>{count}</button>
|
||
```
|
||
|
||
---
|
||
|
||
# Build-Tools
|
||
|
||
| Tool | Stärke |
|
||
|------|--------|
|
||
| **Vite** | schnell, modern, Default für React/Vue/Svelte |
|
||
| **Webpack** | etabliert, mächtig, verbreitet |
|
||
| **Parcel** | zero-config |
|
||
| **Bun** | all-in-one, sehr schnell |
|
||
|
||
**Heute:** Vite ist der Default für neue Projekte.
|
||
|
||
---
|
||
|
||
# Rendering-Modi
|
||
|
||
| Modus | Wann |
|
||
|-------|------|
|
||
| **CSR** (Client-Side) | Single-Page-Apps (Dashboard, Editor) |
|
||
| **SSR** (Server-Side) | SEO + erste Latenz wichtig (News, Shop) |
|
||
| **SSG** (Static Site Gen) | reine Content-Sites (Blog, Doku) |
|
||
| **ISR** (Incremental SSG) | Hybrid: Content selten ändert |
|
||
|
||
Astro / Next.js / Nuxt unterstützen alle.
|
||
|
||
---
|
||
|
||
<!-- _class: aufgabe -->
|
||
|
||
# Selbstlernen — Erste eigene Seite
|
||
|
||
1. **Mappe anlegen** `meine-seite/`
|
||
2. `index.html` mit dem **Grundgerüst** (DOCTYPE, head, body, h1, p)
|
||
3. `style.css` daneben — mit Hotpink-Background
|
||
4. **VS Code Live Server** starten → im Browser öffnen
|
||
5. **DevTools** auf, F12, Tab Elements → DOM-Baum anschauen
|
||
|
||
**Bonus:** Lighthouse Audit laufen lassen. Welchen Score erreicht ihr?
|
||
|
||
---
|
||
|
||
# Zusammenfassung
|
||
|
||
**Heute gelernt:**
|
||
- Internet-Geschichte → WWW → URL→Pixel-7-Schritte
|
||
- Onboarding-Stack: Node (fnm), VS Code, Git, DevTools
|
||
- HTML: Anatomie, semantisch, A11y-Foundation
|
||
- A11y: BFSG/EAA-Pflicht, WCAG POUR
|
||
- CSS-Basics (Vertiefung in Kap 2)
|
||
- JS-Basics (Vertiefung in Kap 3+4)
|
||
- Framework-Landschaft (Vorschau)
|
||
|
||
**Nächste Stunde:** CSS deeper — Flexbox, Grid, Responsive, Animations.
|
||
|