branch-coexist: 3 neue decks 223015b-2026 / 223015c-2026 / dhbw-2026 daneben main
per user-request einen branch der main-content UND rewrite-content trägt — saubere separierung statt symlink/merge-conflict. struktur: - slides/<course>/ → main-content restored, eigene assets (kein new-demo-leak) - slides/<course>-2026/ → rewrite-content, eigene assets (komplett kopiert + new demos) Makefile: COURSES += 223015b-2026 223015c-2026 dhbw-2026 mit eigenen NAME/KAPITEL/DEPLOY/KLAUSUR-konfig. Klausur für b+c=1, dhbw=leer. Deploy-paths /hdm/223015b-2026 etc. make build durchlaufen für alle 6 decks, 0 fehler. dedup: 223015c+dhbw assets identisch in beiden ordnern (kein neu-demos auf b ergänzt). 223015b 86 → 120 files in -2026 (= +34 neue eroeffner/usb-c-drei-achsen/container-vs-codec/etc).
No files matched your search
@@ -0,0 +1,228 @@
|
||||
---
|
||||
marp: true
|
||||
theme: gaia
|
||||
paginate: true
|
||||
backgroundColor: #fff
|
||||
header: "Grundlagen IT- und Internettechnik (223015c)"
|
||||
footer: "Michael Czechowski – HdM Stuttgart – SoSe 2026"
|
||||
title: Grundlagen IT- und Internettechnik
|
||||
---
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--color-foreground: #1a1a2e;
|
||||
--color-highlight: #d63384;
|
||||
--color-dimmed: #4a4a6a;
|
||||
}
|
||||
section.invert {
|
||||
--color-foreground: #fff;
|
||||
}
|
||||
section {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
h1 {
|
||||
color: #a02060;
|
||||
}
|
||||
section.invert h1 {
|
||||
color: #fff;
|
||||
}
|
||||
h2 {
|
||||
color: #1f2937;
|
||||
}
|
||||
pre {
|
||||
background: #0f0f23;
|
||||
color: #d63384;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid #d63384;
|
||||
}
|
||||
pre code {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
code {
|
||||
background: #1a1a2e;
|
||||
color: #d63384;
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
a {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
section.klausur {
|
||||
background: repeating-linear-gradient(
|
||||
135deg,
|
||||
#fce4ec,
|
||||
#fce4ec 40px,
|
||||
#fff 40px,
|
||||
#fff 80px
|
||||
) !important;
|
||||
}
|
||||
@media print {
|
||||
section.klausur {
|
||||
background: #fce4ec !important;
|
||||
}
|
||||
}
|
||||
section.aufgabe {
|
||||
background: #fce4ec !important;
|
||||
}
|
||||
section.aufgabe footer {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _header: '' -->
|
||||
<!-- _backgroundColor: #000 -->
|
||||
|
||||

|
||||
|
||||
# Grundlagen IT- und Internettechnik
|
||||
|
||||
**223015c** · Modul "Technik 1" · 1. Semester
|
||||
Digital- und Medienwirtschaft
|
||||
Hochschule der Medien Stuttgart
|
||||
|
||||
**Sommersemester 2026**
|
||||
|
||||
[https://librete.ch/hdm/223015c/](https://librete.ch/hdm/223015c/)
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Herzlich willkommen!
|
||||
## Einführung
|
||||
|
||||
---
|
||||
|
||||
# Über mich
|
||||
|
||||
**Michael Werner Czechowski**
|
||||
|
||||
- Systems and Platform Engineer
|
||||
- Schwerpunkte:
|
||||
- Web-Technologien, Barriere-Armut, Open Source
|
||||
- Hintergrund:
|
||||
- Philosophie (Uni Stuttgart)
|
||||
- Wirtschaftsinformatik (Leibniz-FH Hannover)
|
||||
- Kontakt: lb-czechowski@hdm-stuttgart.de
|
||||
|
||||
---
|
||||
|
||||
# Warum dieses Modul?
|
||||
|
||||
**Das Internet ist überall** – aber was steckt dahinter?
|
||||
|
||||
* Warum sehen Webseiten auf dem Handy anders aus?
|
||||
* Wie funktioniert eigentlich das Internet?
|
||||
* Wie erkennen Sie, ob eine Werbeagentur gute Arbeit leistet?
|
||||
* Was hat ein Unterseekabel mit meiner E-Mail zu tun?
|
||||
* **→ Die Technik dahinter verstehen und fundierte Entscheidungen treffen**
|
||||
|
||||
---
|
||||
|
||||
# Das Ziel
|
||||
|
||||
**Technische Grundlagen verstehen**, um fundierte Entscheidungen treffen zu können.
|
||||
|
||||
Als Digital- und MedienwirtschaftlerInnen werdet ihr täglich mit technischen Fragen konfrontiert:
|
||||
* Wie baue ich eine barrierearme Webseite?
|
||||
* Welches Protokoll für welchen Zweck?
|
||||
* Wie funktioniert das Web hinter den Kulissen?
|
||||
* **→ Mitreden können – und selbst Webseiten bauen!**
|
||||
|
||||
---
|
||||
|
||||
# Was Sie hier lernen werden
|
||||
|
||||
**In dieser Veranstaltung erwerben Sie folgende Kompetenzen:**
|
||||
|
||||
* Geschichte des Computers und Internets
|
||||
* HTML-Grundlagen und semantisches Markup
|
||||
* CSS für Layout und Gestaltung
|
||||
* Netzwerke und Protokolle (TCP/IP, DNS, HTTP(S))
|
||||
* "Barrierefreiheit" im Web
|
||||
* Grundlagen von JavaScript und Interaktivität
|
||||
|
||||
---
|
||||
|
||||
# Kurze Umfrage
|
||||
|
||||
**Bitte Hand heben:**
|
||||
* Wer hat schon mal eine Webseite gebaut?
|
||||
* Wer weiß, was HTML ist?
|
||||
* Wer hat schon mal CSS geschrieben?
|
||||
* Wer kennt den Unterschied zwischen Internet und WWW?
|
||||
* Wer hat schon mal mit JavaScript gearbeitet?
|
||||
|
||||
---
|
||||
|
||||
# Kursübersicht
|
||||
|
||||
**Kapitel:**
|
||||
|
||||
1. Geschichte, Grundlagen & **HTML**
|
||||
2. Netzwerke, Protokolle, **semantisches HTML** & **CSS**
|
||||
3. Interaktivität, Animationen & **JavaScript**
|
||||
|
||||
**Ziel:** "Gelernte Hilflosigkeit" ablegen
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: klausur -->
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
<!-- _backgroundColor: #fce4ec -->
|
||||
|
||||
# Prüfungsleistung
|
||||
|
||||
**Nach aktuellem Kenntnisstand:**
|
||||
|
||||
* 90 min insg. (Technik 1)
|
||||
* Schriftliche Klausur (digital)
|
||||
* Teils offene Fragen
|
||||
* So gut wie kein Coding/Programmieren
|
||||
* **Prüfungsrelevant:** Folien sind markiert mit anderem Hintergrund
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,786 @@
|
||||
---
|
||||
marp: true
|
||||
theme: gaia
|
||||
paginate: true
|
||||
backgroundColor: #fff
|
||||
header: "Grundlagen IT- und Internettechnik (223015c)"
|
||||
footer: "Michael Czechowski – HdM Stuttgart – SoSe 2026"
|
||||
title: "Kapitel 1: Geschichte, Grundlagen & HTML"
|
||||
---
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--color-foreground: #1a1a2e;
|
||||
--color-highlight: #d63384;
|
||||
--color-dimmed: #4a4a6a;
|
||||
}
|
||||
section.invert { --color-foreground: #fff; }
|
||||
section { font-size: 1.7rem; }
|
||||
h1 { color: #a02060; }
|
||||
section.invert h1 { color: #fff; }
|
||||
h2 { color: #1f2937; }
|
||||
pre {
|
||||
background: #0f0f23;
|
||||
color: #d63384;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid #d63384;
|
||||
}
|
||||
pre code { background: transparent; color: inherit; }
|
||||
code {
|
||||
background: #0f0f23;
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
||||
}
|
||||
section code:not(.hljs) { color: #d63384 !important; }
|
||||
section code.hljs { color: #f8f8f8 !important; }
|
||||
a { color: var(--color-highlight); }
|
||||
section.klausur {
|
||||
background: repeating-linear-gradient(
|
||||
135deg,
|
||||
#fce4ec,
|
||||
#fce4ec 40px,
|
||||
#fff 40px,
|
||||
#fff 80px
|
||||
) !important;
|
||||
}
|
||||
@media print {
|
||||
section.klausur { background: #fce4ec !important; }
|
||||
}
|
||||
section.aufgabe { background: #fce4ec !important; }
|
||||
section.aufgabe footer { display: none; }
|
||||
section.erklaerung { font-size: 1.1rem; }
|
||||
section.erklaerung h1 { font-size: 1.5rem; color: #a02060; margin-bottom: 0.3rem; }
|
||||
section.erklaerung ul, section.erklaerung ol { font-size: 1.0rem; line-height: 1.4; }
|
||||
section.erklaerung p { font-size: 1.0rem; line-height: 1.4; }
|
||||
section.erklaerung table { font-size: 0.9rem; }
|
||||
</style>
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
<!-- _backgroundColor: black -->
|
||||
|
||||

|
||||
|
||||
# Kapitel 1
|
||||
## Geschichte, Grundlagen & HTML
|
||||
|
||||
223015c · Grundlagen IT- und Internettechnik
|
||||
HdM Stuttgart · SoSe 2026
|
||||
|
||||
[https://librete.ch/hdm/223015c/](https://librete.ch/hdm/223015c/)
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# „Du tippst `librete.ch` ein. Was alles dahinter steht."
|
||||
|
||||
<!--
|
||||
Eröffner-Hook. Studis kennen das Tippen einer URL aus dem Alltag.
|
||||
|
||||
Aber: was passiert wirklich? Ein ganzer Stapel von Schichten:
|
||||
1. Browser parst die URL
|
||||
2. DNS findet die IP-Adresse zu librete.ch
|
||||
3. TCP-Handshake mit dem Server in Frankfurt
|
||||
4. TLS-Handshake für https
|
||||
5. HTTP-Request wird gesendet
|
||||
6. Server antwortet mit HTML
|
||||
7. Browser parst HTML + CSS + JS und rendert Pixel
|
||||
|
||||
Dieser ganze Stack ist 70 Jahre Computing-Geschichte. Wir packen ihn in diesem Kapitel an einem Ende an — bei den Pionieren des Rechnens — und enden beim HTML-Tag, das auf eurem Bildschirm landet.
|
||||
|
||||
In Kap 2 wird der Netzwerk-Teil aufgepackt (TCP/IP, DNS, HTTP), in Kap 3 das Interaktive (JavaScript).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Die Pioniere des Computings
|
||||
|
||||
<!--
|
||||
Wir starten bei den Personen, die die Grundlagen geschaffen haben — von der ersten Programmidee bis zur Architektur, die wir heute noch nutzen.
|
||||
|
||||
6 Personen, eine pro Folie. Keine Galerie-Inflation.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
# Ada Lovelace (1815–1852)
|
||||
|
||||
**Erster Algorithmus in der Geschichte.**
|
||||
|
||||
Babbage entwarf 1830er die *Analytical Engine* — eine programmierbare Rechenmaschine. Ada Lovelace beschrieb 1843, wie man Bernoulli-Zahlen damit berechnen könnte.
|
||||
|
||||
→ **Ihre Notes sind der erste publizierte Algorithmus, der für eine Maschine geschrieben wurde.**
|
||||
|
||||
<!--
|
||||
Ada Lovelace war Mathematikerin und Tochter von Lord Byron. Sie übersetzte einen italienischen Aufsatz über die Analytical Engine — und fügte „Notes" hinzu, die länger waren als das Original.
|
||||
|
||||
In Note G beschrieb sie eine Schritt-für-Schritt-Anleitung, wie die Maschine eine mathematische Sequenz berechnen würde. Das gilt heute als erster Algorithmus.
|
||||
|
||||
Sie war auch die Erste, die erkannte: die Analytical Engine könnte mehr als nur Zahlen. Man könnte Musik, Texte, jede Form von Logik darüber abbilden. Eine erstaunliche Voraussicht — fast 100 Jahre vor Turing.
|
||||
|
||||
Die Programmiersprache „Ada" (1980, vom US-Verteidigungsministerium) wurde nach ihr benannt.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
# Herman Hollerith (1860–1929)
|
||||
|
||||
**Lochkarte als Datenträger.**
|
||||
|
||||
1890er: US-Volkszählung. Hollerith entwickelt eine Maschine, die Daten auf Lochkarten speichert und liest. **8 Jahre Auswertung → 1 Jahr.**
|
||||
|
||||
→ Seine Firma wird 1911 zu **CTR**, 1924 zu **IBM**.
|
||||
|
||||
<!--
|
||||
Vor Hollerith dauerte die US-Volkszählung 8 Jahre — bis zur nächsten. Hollerith's Maschine brachte das auf 1 Jahr.
|
||||
|
||||
Lochkarten waren bis in die 1980er der Standard-Datenträger. Programme wurden auf Lochkarten gestanzt und in Stapeln zum Rechenzentrum gebracht. „Batch processing".
|
||||
|
||||
IBM (1924 unter Thomas J. Watson Sr.) wurde aus Hollerith's Firma. Watson prägte den Slogan "THINK", der noch heute zu IBM-Logos gehört.
|
||||
|
||||
Schatten: IBM lieferte in den 1930er Jahren Tabelliermaschinen auch ins NS-Deutschland, wo sie für die Volkszählungen und später für die Lager-Buchhaltung eingesetzt wurden. Edwin Black hat das 2001 in „IBM and the Holocaust" dokumentiert. Wichtig: das ist Teil der IT-Geschichte, nicht ein Anhang.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
# Alan Turing (1912–1954)
|
||||
|
||||
**Theoretisches Fundament moderner Computer.**
|
||||
|
||||
* **1936** — Turing-Maschine
|
||||
* **1940er** — Bletchley Park, Enigma-Bruch (geheim bis 1974)
|
||||
* **1950** — Turing-Test
|
||||
|
||||
<!--
|
||||
Alan Turing ist der Vater der theoretischen Informatik.
|
||||
|
||||
Die Turing-Maschine ist ein mathematisches Modell:
|
||||
- Ein unendliches Band als Speicher
|
||||
- Ein Lese-/Schreibkopf
|
||||
- Ein Regelsatz für Zustandsübergänge
|
||||
|
||||
Damit beweist Turing 1936, dass es prinzipiell unentscheidbare Probleme gibt (Halteproblem). Und dass es eine „universelle" Maschine geben kann, die jede andere Maschine simulieren kann.
|
||||
|
||||
In Bletchley Park wendet er das Konzept praktisch an: gemeinsam mit anderen baut er die „Bombe", eine elektromechanische Maschine, die Enigma-Schlüssel durchprobiert. Geheim bis 1974 — Großbritannien verriet jahrzehntelang nicht, dass sie deutsche Funksprüche entschlüsseln konnten.
|
||||
|
||||
Tragisches Ende: Turing wurde 1952 wegen Homosexualität verurteilt und chemisch kastriert. 1954 Selbstmord. 2009 erst offizielle Entschuldigung der britischen Regierung.
|
||||
|
||||
Heute trägt der ACM Turing Award (der „Informatik-Nobelpreis") seinen Namen.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
# John von Neumann (1903–1957)
|
||||
|
||||
**Die Architektur, die wir heute noch nutzen.**
|
||||
|
||||
1945: das **EDVAC-Papier** — Daten und Programm im selben Speicher.
|
||||
|
||||
Vorher: ENIAC musste für jedes neue Programm **physisch umgekabelt** werden. 6.000 Schalter, oft Wochen.
|
||||
|
||||
Nachher: einfach den Speicher überschreiben.
|
||||
|
||||
<!--
|
||||
John von Neumann war einer der bedeutendsten Universalwissenschaftler des 20. Jahrhunderts — Mathematik, Physik, Wirtschaft, Spieltheorie, Computing.
|
||||
|
||||
Sein „First Draft of a Report on the EDVAC" (1945) wurde unautorisiert von Herman Goldstine verteilt. Da der Bericht nur von Neumann's Namen trug, wurde die darin beschriebene Architektur als „Von-Neumann-Architektur" bekannt — obwohl maßgebliche Vorarbeit von Eckert und Mauchly stammte. Bis heute kontrovers.
|
||||
|
||||
Die zentrale Innovation: „stored-program" — Daten und Code im gleichen Speicher, addressierbar wie Daten. Damit können Programme als Daten manipuliert werden (Compiler, Debugger, JIT) — heute selbstverständlich, damals revolutionär.
|
||||
|
||||
Auch beteiligt: Manhattan-Projekt (Implosions-Linsen für die Atombombe). Zwiespältig.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Von-Neumann-Architektur · 5 Komponenten
|
||||
|
||||
| # | Komponente | Aufgabe |
|
||||
|---|------------|---------|
|
||||
| 1 | **Steuerwerk** (Control Unit) | holt Befehl, entscheidet was zu tun ist |
|
||||
| 2 | **Rechenwerk** (ALU) | führt Rechnung / Vergleich aus |
|
||||
| 3 | **Speicher** (Memory) | hält Daten *und* Programm |
|
||||
| 4 | **Eingabe / Ausgabe** (I/O) | Tastatur, Bildschirm, Netzwerk |
|
||||
| 5 | **Bus** (Verbindung) | transportiert Daten zwischen allen |
|
||||
|
||||
**Schlüssel:** Speicher hält *beides* — Daten + Programm. (Stored Program.)
|
||||
|
||||
<!--
|
||||
Klausurfähig: die 5 Komponenten und ihre Aufgaben benennen.
|
||||
|
||||
Wo seht ihr das in eurem eigenen Gerät?
|
||||
- Steuerwerk + Rechenwerk = CPU
|
||||
- Speicher = RAM (flüchtig) + SSD (persistent)
|
||||
- I/O = USB-Ports, Display, Audio
|
||||
- Bus = im Chip (Intern), zwischen Chips (PCIe, USB)
|
||||
|
||||
Die Architektur ist seit 1945 stabil. Quantencomputer brechen sie auf (kein klassisches stored program). Aber jeder PC, Mac, Smartphone, jeder Server, jede Spielkonsole folgt ihr noch immer.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Hopper, Booth, Hamilton
|
||||
|
||||
**Grace Hopper** (1906–1992): erster *Compiler* (1952). „Submarine of code." US Navy Admiral.
|
||||
|
||||
**Kathleen Booth** (1922–2022): erste **Assembly Language** (1947). Notation für Maschinen-Befehle.
|
||||
|
||||
**Margaret Hamilton** (*1936): leitete die Software für **Apollo 11**. Prägte den Begriff „Software Engineering".
|
||||
|
||||
<!--
|
||||
Drei Personen, die wichtige Schichten oberhalb der Hardware geschaffen haben:
|
||||
|
||||
Grace Hopper:
|
||||
- Arbeitete an Mark I (Harvard)
|
||||
- Erfand den ersten Compiler (A-0, 1952) — Mensch-lesbare Sprache → Maschinen-Code
|
||||
- Hat den Begriff „Bug" populär gemacht (echter Motte im Mark II 1947 gefunden, ins Logbuch geklebt)
|
||||
- Wurde später US Navy Rear Admiral
|
||||
|
||||
Kathleen Booth:
|
||||
- Erste praktische Assembly Language für die ARC (All-purpose Electronic Computer) am Birkbeck College London
|
||||
- Vor ihr musste man Befehle in Binär eintippen
|
||||
- Ihre Notation (z.B. ADD R1, R2) ist im Prinzip noch heute in jeder Assembly-Sprache
|
||||
|
||||
Margaret Hamilton:
|
||||
- Leitete die On-board Software für Apollo 11 (1969, Mondlandung)
|
||||
- Berühmt: 5 Minuten vor Mondlandung gibt es Alarm 1202 + 1201 — ihre Software hat Prioritäten richtig gesetzt und die wichtige Aufgabe fortgesetzt
|
||||
- Sie und ihr Team prägten den Begriff „Software Engineering" 1968 — vorher gab es das als Disziplin nicht
|
||||
|
||||
Lektionen für heute: Programmierung ist nicht Hardware. Es ist eine eigenständige Disziplin mit ingenieurmäßiger Strenge. Hamilton's Berkeley-Adoptierung des Begriffs „Engineering" war damals nicht selbstverständlich.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Vom Militär zum Netz
|
||||
|
||||
<!--
|
||||
Pivot. Wir verlassen die einzelne Maschine und schauen, wie viele Maschinen miteinander verbunden wurden.
|
||||
|
||||
Das Internet entsteht im Kalten Krieg als militärisches Forschungsprojekt — und wird zum globalen Netz.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Kalter Krieg: das Problem der Kommunikation
|
||||
|
||||
**Atomare Bedrohung** in den 1960ern.
|
||||
|
||||
Klassisches Telefonnetz ist **zentral** — ein Knoten down, ganzer Bezirk down.
|
||||
|
||||
**Paul Baran** (RAND, 1962): wenn das Netz **dezentral** ist und Daten in kleinen Paketen reisen, überlebt es einzelne Ausfälle.
|
||||
|
||||
→ **Packet Switching** statt **Circuit Switching.**
|
||||
|
||||
<!--
|
||||
Hintergrund: USA und UdSSR im Kalten Krieg. Telefon-Netz war zentral organisiert — ein paar Backbone-Stationen, wenn die ausfielen war alles tot.
|
||||
|
||||
Paul Baran beim RAND-Think-Tank schlug 1962 vor: zerteilt Nachrichten in kleine Pakete, jedes Paket findet eigenständig seinen Weg durch ein Mesh-Netzwerk. Wenn ein Knoten ausfällt, finden Pakete einen anderen Pfad.
|
||||
|
||||
Das ist die Geburt von „packet switching" — heute Grundlage des gesamten Internets.
|
||||
|
||||
ARPANET (1969) ist die erste praktische Umsetzung. 4 Knoten anfangs: UCLA, Stanford, UCSB, Utah. Erste Nachricht: „LOGIN" — Maschine crasht nach „LO".
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Internet-Timeline · 4 Milestones
|
||||
|
||||
| Jahr | Was | Was hat es verändert |
|
||||
|------|-----|----------------------|
|
||||
| **1969** | ARPANET | Erstes paket-vermitteltes Netzwerk, 4 Knoten |
|
||||
| **1971** | Email (Ray Tomlinson) | Erste Nutzung des `@`-Zeichens |
|
||||
| **1983** | TCP/IP | Wurde Standard-Protokoll des ARPANET |
|
||||
| **1989** | **WWW** (Berners-Lee, CERN) | HTML, HTTP, URL — das Web wie wir es kennen |
|
||||
|
||||
1993: Mosaic-Browser → Internet wird *populär*.
|
||||
|
||||
<!--
|
||||
Klausurfähig: die 4 Meilensteine und ihre Bedeutung.
|
||||
|
||||
Anmerkungen:
|
||||
- 1969 ARPANET: noch militärisch + Forschung. Wenige Knoten.
|
||||
- 1971 Email: Ray Tomlinson schickt die erste E-Mail mit @-Zeichen, das er gewählt hat um „User AT Maschine" zu trennen. Heute auf jedem Tastatur als Standard.
|
||||
- 1983 TCP/IP: Vint Cerf + Bob Kahn. ARPANET wechselt am 1. Jan 1983 von NCP zu TCP/IP. Das ist die „Geburt des modernen Internets" im technischen Sinne.
|
||||
- 1989 WWW: Tim Berners-Lee am CERN. Er erfindet HTTP (Protokoll), HTML (Markup) und URL (Adress-System) — drei Standards, eine Person.
|
||||
- 1993 Mosaic: erste GUI-Browser, der Bilder im Text-Fluss anzeigen konnte. Damit explodierte die Web-Nutzung.
|
||||
|
||||
Internet ist nicht Web — Internet ist das Netzwerk, Web ist eine Anwendung darauf. Aber im Volksmund verwechselt.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
# Tim Berners-Lee + das WWW (1989)
|
||||
|
||||
**CERN, Genf.** Berners-Lee schlägt ein „Hypertext-System" für die interne Wissenschaftler-Kommunikation vor.
|
||||
|
||||
Sein Memo „Information Management: A Proposal" wird abgelehnt. Er baut es trotzdem.
|
||||
|
||||
**Drei Standards:**
|
||||
- **HTTP** (Protokoll)
|
||||
- **HTML** (Format)
|
||||
- **URL** (Adresse)
|
||||
|
||||
1991: erste Website (`info.cern.ch`). Bis heute online.
|
||||
|
||||
<!--
|
||||
Berners-Lee arbeitete am CERN als Informatiker, hatte aber Frustration mit der Fragmentierung der internen Dokumentation. Sein System sollte alle Dokumente verbindbar machen.
|
||||
|
||||
Sein erstes Memo wurde mit „vague but exciting" beantwortet. Er bekam keine offizielle Finanzierung, baute den ersten Webserver + Webbrowser dennoch.
|
||||
|
||||
Diese drei Standards sind bis heute das Web:
|
||||
- HTTP: wie geht eine Anfrage über das Netz
|
||||
- HTML: wie sieht ein Dokument aus
|
||||
- URL: wo finde ich ein Dokument
|
||||
|
||||
Berners-Lee gab das alles **patentfrei** frei. Hätte er die Standards verkauft, wäre das Web vermutlich nie groß geworden — andere Standards (Microsoft Blackbird, AOL-Pages, Apple eWorld) sind alle gescheitert.
|
||||
|
||||
2004 wurde er von Queen Elizabeth zum Sir geadelt. 2016 ACM Turing Award.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# 1,3 Mio km Unterseekabel
|
||||
|
||||

|
||||
|
||||
Das Internet ist **physisch.**
|
||||
|
||||
400+ Unterseekabel transportieren ~99% des interkontinentalen Datenverkehrs.
|
||||
|
||||
**DE-CIX Frankfurt:** einer der größten Internet-Knoten der Welt. >12 Tbit/s im Peak.
|
||||
|
||||
→ Auch eure WhatsApp-Nachricht nach New York fließt durch ein Glasfaserkabel im Atlantik.
|
||||
|
||||
<!--
|
||||
Internet ist nicht „die Cloud" — die Cloud ist Hardware in Rechenzentren, die mit Glasfaser-Kabeln verbunden sind.
|
||||
|
||||
Unterseekabel:
|
||||
- ~400 aktive Kabel weltweit, ~1,3 Mio km Länge gesamt
|
||||
- Werden von Spezialschiffen verlegt
|
||||
- Lebensdauer ~25 Jahre
|
||||
- Glasfaser-Stränge mit Verstärkern alle ~50–100 km
|
||||
- Ein einziges Kabel kann 100+ Tbit/s übertragen
|
||||
|
||||
Großbritannien-USA: TAT-1 (1956), erst Telefon. Heute: MAREA (2018), Marea, Dunant — alle mehrere Tbit/s.
|
||||
|
||||
DE-CIX Frankfurt:
|
||||
- Internet Exchange Point (IXP) — Punkt, wo viele ISPs sich treffen und Daten austauschen
|
||||
- Größter IXP der Welt nach Datenverkehr
|
||||
- ~1.000 Mitglieder (ISPs, Content-Provider)
|
||||
- ~12 Tbit/s im Peak
|
||||
|
||||
Frankfurt hat sich aus historischen Gründen entwickelt (Banken brauchten gute Netzwerk-Anbindung). Heute strategisch wichtig — wer Frankfurt kontrolliert, kontrolliert einen Großteil des europäischen Traffic.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Vom Internet zum Browser-Render
|
||||
|
||||
<!--
|
||||
Pivot. Wir haben gesehen, wie Daten durch das Netzwerk reisen.
|
||||
|
||||
Jetzt: was bekommt der Browser eigentlich vom Server? Antwort: HTML.
|
||||
|
||||
Dann: wie ist HTML aufgebaut, was sind die wichtigsten Tags, wie schreibe ich eine gültige Webseite?
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Was bekommt der Browser?
|
||||
|
||||
Wenn ihr `librete.ch` eintippt, schickt der Server:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<title>Librete</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Willkommen</h1>
|
||||
<p>Dies ist HTML.</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Der Browser **parsed** das, rendert es als Pixel, und ihr seht eine Seite.
|
||||
|
||||
<!--
|
||||
HTML = Hypertext Markup Language. „Hypertext" weil Tags Links zu anderen Dokumenten erlauben.
|
||||
|
||||
Das Beispiel zeigt:
|
||||
- DOCTYPE-Deklaration (sagt dem Browser: das ist HTML5)
|
||||
- html-Element als Wurzel
|
||||
- head: Meta-Informationen (Titel, Encoding, CSS-Links)
|
||||
- body: das, was angezeigt wird
|
||||
- Heading-Tag h1
|
||||
- Paragraph-Tag p
|
||||
|
||||
Nichts Magisches dran. Plain-Text mit Tags drum. Studis könnten das in Notepad oder TextEdit schreiben und sofort im Browser öffnen.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# HTML-Anatomie
|
||||
|
||||
```html
|
||||
<a href="https://librete.ch">Mein Link</a>
|
||||
```
|
||||
|
||||
| Bestandteil | Was |
|
||||
|-------------|-----|
|
||||
| `<a` | **Opening-Tag** mit Tag-Namen |
|
||||
| `href="https://..."` | **Attribut** (Name + Wert) |
|
||||
| `>` | Ende des Opening-Tags |
|
||||
| `Mein Link` | **Inhalt** des Elements |
|
||||
| `</a>` | **Closing-Tag** |
|
||||
|
||||
Alles zusammen = ein **Element.**
|
||||
|
||||
<!--
|
||||
Klausurfähig. Studis sollen die Bestandteile eines HTML-Elements unterscheiden können:
|
||||
- Opening-Tag
|
||||
- Closing-Tag
|
||||
- Attribute (Name=Wert)
|
||||
- Inhalt
|
||||
- Element = alles zusammen
|
||||
|
||||
Achtung: einige Tags sind „self-closing" und haben keinen Closing-Tag:
|
||||
- `<img src="..." alt="...">`
|
||||
- `<br>`
|
||||
- `<input>`
|
||||
- `<meta>`
|
||||
|
||||
Diese werden auf der nächsten Folie behandelt.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Wichtige Attribute
|
||||
|
||||
| Attribut | Wo | Bedeutung |
|
||||
|----------|----|-----------|
|
||||
| `id` | jedes Element | eindeutige ID auf der Seite |
|
||||
| `class` | jedes Element | für CSS (mehrere möglich) |
|
||||
| `href` | `<a>`, `<link>` | Ziel-URL |
|
||||
| `src` | `<img>`, `<script>` | Quell-URL |
|
||||
| `alt` | `<img>` | **Alt-Text für A11y!** |
|
||||
| `title` | jedes Element | Tooltip beim Hover |
|
||||
| `lang` | meist `<html>` | Sprache des Inhalts |
|
||||
|
||||
<!--
|
||||
Diese Attribute begegnen Studis täglich — wenn auch unbemerkt.
|
||||
|
||||
`alt`-Text auf Bildern ist a11y-Pflicht. Wer das vergisst, macht die Seite für Blinde unlesbar. Screen-Reader liest stattdessen `alt`-Wert vor.
|
||||
|
||||
`class` vs `id`:
|
||||
- id: einmal auf der Seite (Anker, JS-Hook)
|
||||
- class: beliebig oft (Style-Gruppen)
|
||||
|
||||
`lang="de"` auf html-Element sagt Screen-Readers, in welcher Sprache der Inhalt ist — wichtig für korrekte Aussprache.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# 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">
|
||||
```
|
||||
|
||||
Diese Tags haben **kein Closing**. Sie sind „leer" — der Browser-Render erzeugt das Pixel-Resultat allein aus dem Opening-Tag.
|
||||
|
||||
<!--
|
||||
Self-closing Tags:
|
||||
- img: Bild einfügen
|
||||
- br: Zeilenumbruch
|
||||
- hr: horizontale Linie
|
||||
- input: Eingabefeld
|
||||
- meta: Metadaten im head
|
||||
- link: Verbindung zu CSS/Favicon
|
||||
|
||||
Streng XML-konform würde man `<br />` schreiben (mit / vor >). HTML5 erlaubt beides. Modern üblich: ohne /.
|
||||
|
||||
Wichtig: vergesst nicht den `alt`-Text für `<img>` — A11y.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Document-Struktur: das 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>
|
||||
<!-- alle sichtbaren Inhalte -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
<!--
|
||||
Klausurfähig: die DOCTYPE + head + body-Struktur reproduzieren können.
|
||||
|
||||
Was passiert wo?
|
||||
- DOCTYPE: sagt dem Browser „das ist HTML5". Ohne DOCTYPE: Quirks-Mode (alte Browser-Verhaltensweisen).
|
||||
- html-Element + lang: Wurzel-Element + Sprache
|
||||
- head: alles, was *nicht* sichtbar ist (Meta, Title, CSS-Links, Scripts)
|
||||
- meta charset: sagt Browser, wie die Byte zu interpretieren sind (UTF-8 = international, alle Sprachen)
|
||||
- meta viewport: für Mobile-Rendering, ohne zoomt iPhone alles auf 980px
|
||||
- title: Browser-Tab-Titel + Lesezeichen-Name
|
||||
- link stylesheet: CSS einbinden
|
||||
- body: alle sichtbaren Inhalte
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Visualisierung des Grundgerüsts.
|
||||
|
||||
Pädagogisches Ziel: Studis sollen das Muster „<head> = unsichtbares Meta, <body> = sichtbares Drinnen" verinnerlichen.
|
||||
|
||||
Faustregel: alles, was den Inhalt der Seite betrifft → body. Alles, was die Seite *beschreibt* → head.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Semantische HTML-Tags
|
||||
|
||||
| Tag | Bedeutung | Beispiel |
|
||||
|-----|-----------|----------|
|
||||
| `<header>` | Kopfbereich (Logo, Nav) | oben auf der Seite |
|
||||
| `<nav>` | Navigations-Menü | Hauptmenü |
|
||||
| `<main>` | Hauptinhalt | das eigentliche Thema |
|
||||
| `<section>` | Thematischer Abschnitt | Kapitel der Seite |
|
||||
| `<article>` | eigenständiger Inhalt | Blog-Post, News-Beitrag |
|
||||
| `<aside>` | Seiten-Inhalt | Sidebar, Werbung |
|
||||
| `<footer>` | Fußbereich | Impressum, Copyright |
|
||||
|
||||
**Vorteil:** Screen-Reader, Suchmaschinen + andere Entwickler verstehen die Struktur.
|
||||
|
||||
<!--
|
||||
Klausurfähig: die 7 semantischen Tags und ihre Bedeutung.
|
||||
|
||||
Vor HTML5 (2008) gab es nur `<div>`. Man hat alles in div verpackt und mit Klassen markiert: `<div class="header">`. Funktioniert visuell — aber Maschinen (Screen-Reader, Suchmaschinen) verstehen nichts.
|
||||
|
||||
Mit semantischen Tags:
|
||||
- Screen-Reader kann „Hauptnavigation überspringen" anbieten
|
||||
- Google versteht, was Haupt-Inhalt der Seite ist (SEO-Boost)
|
||||
- Andere Entwickler lesen den Code schneller
|
||||
|
||||
Faustregel: wenn ein Tag den *Zweck* eines Bereichs ausdrückt — semantisch. Wenn nur Styling — div.
|
||||
|
||||
Drei A11y-relevante Anti-Patterns:
|
||||
- `<div onclick="...">` statt `<button>` (Tastatur nicht erreichbar)
|
||||
- `<a href="javascript:void(0)">` statt `<button>` (semantisch falsch)
|
||||
- alles in `<div>` (keine Hierarchie für Screen-Reader)
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Häufige inline-Tags
|
||||
|
||||
| Tag | Was |
|
||||
|-----|-----|
|
||||
| `<a>` | Hyperlink |
|
||||
| `<strong>` | wichtig (fett dargestellt) |
|
||||
| `<em>` | hervorgehoben (kursiv) |
|
||||
| `<span>` | semantisch neutrale Inline-Container |
|
||||
| `<code>` | Inline-Code |
|
||||
| `<br>` | Zeilenumbruch |
|
||||
| `<img>` | Bild |
|
||||
|
||||
**vs Block-Tags:** `<h1>`–`<h6>`, `<p>`, `<div>`, `<ul>`/`<ol>`/`<li>`, `<table>`, alle semantischen.
|
||||
|
||||
<!--
|
||||
Block-Tags brechen automatisch eine neue Zeile, Inline-Tags nicht.
|
||||
|
||||
Wichtig pädagogisch:
|
||||
- `<strong>` ist semantisch (wichtig), nicht stilistisch (fett). Wenn ihr nur fett wollt → CSS, nicht `<b>`.
|
||||
- `<em>` (emphasized) vs `<i>` (italic) — gleiche Unterscheidung
|
||||
- `<span>` ist der „div" für Inline — semantisch neutral, nur zum Markieren
|
||||
|
||||
Browser stylen die Tags per Default:
|
||||
- strong → fett
|
||||
- em → kursiv
|
||||
- h1 → groß+fett
|
||||
- p → Absatz mit Margin
|
||||
|
||||
Aber das kann mit CSS überschrieben werden. Daher: Tags semantisch wählen, dann mit CSS gestalten.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Listen, Bilder, Links
|
||||
|
||||
```html
|
||||
<!-- Unsortierte Liste -->
|
||||
<ul>
|
||||
<li>Erstes Item</li>
|
||||
<li>Zweites Item</li>
|
||||
</ul>
|
||||
|
||||
<!-- Bild mit Alt-Text -->
|
||||
<img src="./foto.jpg" alt="Sonnenuntergang über Stuttgart">
|
||||
|
||||
<!-- Link -->
|
||||
<a href="https://hdm-stuttgart.de" target="_blank" rel="noopener">
|
||||
HdM Stuttgart
|
||||
</a>
|
||||
```
|
||||
|
||||
<!--
|
||||
Drei sehr häufige Patterns:
|
||||
|
||||
Listen:
|
||||
- `<ul>` unsortiert (Bullet Points)
|
||||
- `<ol>` sortiert (Nummern)
|
||||
- `<li>` für jedes Item
|
||||
|
||||
Bilder:
|
||||
- src: Pfad zum Bild
|
||||
- alt: Alt-Text — Pflicht für A11y
|
||||
- Bild-Pfad relativ oder absolut
|
||||
|
||||
Links:
|
||||
- href: Ziel-URL
|
||||
- target="_blank": neuer Tab (sparsam einsetzen)
|
||||
- rel="noopener": Sicherheits-Best-Practice für target="_blank"
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Formulare: Inputs + Labels
|
||||
|
||||
```html
|
||||
<form>
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" id="name" name="name" required>
|
||||
|
||||
<label for="email">E-Mail:</label>
|
||||
<input type="email" id="email" name="email">
|
||||
|
||||
<button type="submit">Absenden</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
**Immer:** `<label>` mit `for` → `<input>` mit gleichem `id`. **Pflicht für A11y.**
|
||||
|
||||
<!--
|
||||
Formulare sind kritisch für A11y. Screen-Reader liest den Label-Text vor dem Input vor, damit der Nutzer weiß, was eingegeben werden soll.
|
||||
|
||||
Verbindung Label-Input:
|
||||
- `<label for="name">` muss zum `<input id="name">` passen
|
||||
- Alternative: Input INSIDE Label
|
||||
- Ohne Label: nur Placeholder-Text → A11y-Mangel
|
||||
|
||||
Input-Types (HTML5):
|
||||
- text, email, tel, url, password, number, date, time, color, range, search
|
||||
|
||||
Browser validiert automatisch (z.B. type="email" zeigt Fehler wenn kein @ drin).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Das Dokument-Objekt-Modell (DOM): HTML im Speicher des Browsers als Baum.
|
||||
|
||||
Jeder Tag wird zu einem Element-Node. Der Browser baut diesen Baum beim Parsing auf.
|
||||
|
||||
JavaScript (Kap 3) kann diesen Baum manipulieren — Elemente erzeugen, ändern, entfernen.
|
||||
|
||||
Vorgriff: `document.querySelector('h1').textContent = 'Neuer Text'` ändert den Inhalt eines H1.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: aufgabe -->
|
||||
|
||||
# Selbstlernen — Inspector live
|
||||
|
||||
1. Öffnet eure **Lieblings-Webseite**
|
||||
2. **Rechtsklick → Untersuchen** (oder F12)
|
||||
3. Tab **Elements / Inspector** öffnen
|
||||
4. **HTML-Baum** durchklicken
|
||||
5. Findet: das `<header>`, das `<main>`, mindestens ein `<a href="...">`
|
||||
|
||||
**Bonus:** Element auswählen → in der Console: `$0.style.background = 'pink'`. *Was passiert?*
|
||||
|
||||
<!--
|
||||
Aufgabe ist niederschwellig und zugleich erkenntnisreich.
|
||||
|
||||
Ziel: Studis erleben, dass jede Webseite aus HTML-Tags besteht. Es ist nichts Magisches dahinter.
|
||||
|
||||
DevTools-Tipps für die Vorlesung:
|
||||
- F12 öffnet DevTools in den meisten Browsern
|
||||
- Elements-Tab zeigt den live DOM
|
||||
- $0 ist eine Referenz zum aktuell selektierten Element (für Console-Experimente)
|
||||
- Style-Edit live im Inspector — schöne erste Erfahrung mit „selber CSS schreiben"
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Zusammenfassung
|
||||
|
||||
**Pioniere:** Lovelace (erster Algorithmus), Hollerith (Lochkarte), Turing (Theorie), von Neumann (Architektur), Hopper/Booth/Hamilton (Sprache + SoftwareEng).
|
||||
|
||||
**Internet:** ARPANET 1969 → TCP/IP 1983 → WWW 1989. Heute physisch über 1,3 Mio km Unterseekabel.
|
||||
|
||||
**HTML:** Tag-Struktur (`<tag attr>Inhalt</tag>`). Document-Grundgerüst (DOCTYPE + head + body). Semantische Tags (`header`, `nav`, `main`, …) als A11y-Foundation.
|
||||
|
||||
→ **In Kap 2:** wie reisen die Bytes durchs Netz — und wie wird HTML mit CSS hübsch + barrierefrei?
|
||||
|
||||
<!--
|
||||
Recap.
|
||||
|
||||
Zwei Strangs in diesem Kapitel:
|
||||
1. Wie wurde Computing erfunden? (Pioniere → Von-Neumann-Architektur)
|
||||
2. Wie wurde es vernetzt? (ARPANET → WWW)
|
||||
|
||||
Beides mündet in das, was Studis tagtäglich sehen: HTML in einem Browser.
|
||||
|
||||
Anschluss zu Kap 2:
|
||||
- Netzwerk-Tiefe: TCP/IP-Schichten, IP/MAC/Port, DNS, HTTP, der ganze „URL bis Pixel"-Ablauf
|
||||
- Visuelle Tiefe: CSS, Box-Model, Flexbox, Grid
|
||||
- A11y-Tiefe: BFSG, WCAG POUR, semantisches HTML + ARIA
|
||||
|
||||
In Kap 3 dann das Dynamische: JavaScript, DOM-Manipulation, Events.
|
||||
-->
|
||||
@@ -0,0 +1,901 @@
|
||||
---
|
||||
marp: true
|
||||
theme: gaia
|
||||
paginate: true
|
||||
backgroundColor: #fff
|
||||
header: "Grundlagen IT- und Internettechnik (223015c)"
|
||||
footer: "Michael Czechowski – HdM Stuttgart – SoSe 2026"
|
||||
title: "Kapitel 3: Interaktivität & JavaScript"
|
||||
---
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--color-foreground: #1a1a2e;
|
||||
--color-highlight: #d63384;
|
||||
--color-dimmed: #4a4a6a;
|
||||
}
|
||||
section.invert { --color-foreground: #fff; }
|
||||
section { font-size: 1.7rem; }
|
||||
h1 { color: #a02060; }
|
||||
section.invert h1 { color: #fff; }
|
||||
h2 { color: #1f2937; }
|
||||
pre {
|
||||
background: #0f0f23;
|
||||
color: #d63384;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid #d63384;
|
||||
}
|
||||
pre code { background: transparent; color: inherit; }
|
||||
code {
|
||||
background: #0f0f23;
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
||||
}
|
||||
section code:not(.hljs) { color: #d63384 !important; }
|
||||
section code.hljs { color: #f8f8f8 !important; }
|
||||
a { color: var(--color-highlight); }
|
||||
section.aufgabe { background: #fce4ec !important; }
|
||||
section.aufgabe footer { display: none; }
|
||||
section.erklaerung { font-size: 1.1rem; }
|
||||
section.erklaerung h1 { font-size: 1.5rem; color: #a02060; margin-bottom: 0.3rem; }
|
||||
</style>
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Kapitel 3
|
||||
## Interaktivität & JavaScript
|
||||
|
||||
<!--
|
||||
Eine Stunde, eine Frage: *Was passiert, wenn HTML + CSS da sind und nichts reagiert?*
|
||||
|
||||
JavaScript (JS) macht Webseiten interaktiv:
|
||||
- DOM manipulieren (Elemente ändern, hinzufügen, entfernen)
|
||||
- Auf Events reagieren (Klick, Tastendruck, Scroll)
|
||||
- Daten holen (fetch) + speichern (localStorage)
|
||||
- Animationen, dynamische UI, SPA-Frameworks
|
||||
|
||||
Per Klausur-Themen-Vorschlag: JavaScript ist nicht klausurrelevant. Lernziele auf Verstehen-Niveau (Code-Lesen, nicht Code-Schreiben).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# „Statisch ist langweilig"
|
||||
|
||||
<!--
|
||||
Hook: eine reine HTML+CSS-Seite reagiert auf nichts. Klick auf Button → nichts passiert (außer Form-Submit).
|
||||
|
||||
JS bringt das Reagieren rein. Daher der Name „Interaktivität".
|
||||
|
||||
Beispiele aus dem Alltag:
|
||||
- Dropdown-Menü, das aufklappt
|
||||
- Dark-Mode-Toggle
|
||||
- „Mehr laden"-Button ohne Page-Reload
|
||||
- Live-Validierung in Formularen
|
||||
- Maps, die zoomen
|
||||
- Spotify-Player, der weitermacht beim Wechseln der Seite
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Was kann JavaScript?
|
||||
|
||||
| Kann | Beispiel |
|
||||
|------|----------|
|
||||
| DOM ändern | Element-Text, -Klasse, -Inhalt manipulieren |
|
||||
| Events behandeln | Klick, Tastendruck, Scroll, Submit |
|
||||
| Daten holen | `fetch()` API-Anfragen |
|
||||
| Daten lokal speichern | `localStorage`, `sessionStorage` |
|
||||
| Animationen | `requestAnimationFrame`, CSS-Animationen triggern |
|
||||
| Web-APIs nutzen | Geolocation, Camera, Audio, Notification |
|
||||
|
||||
**Aus Sicherheitsgründen NICHT:** willkürlich Dateien auf der Platte lesen/schreiben.
|
||||
|
||||
<!--
|
||||
JavaScript läuft im Browser-Sandkasten. Es darf:
|
||||
- alles am DOM ändern
|
||||
- Daten an Server schicken (mit CORS-Beschränkungen)
|
||||
- LocalStorage für ~5-10 MB nutzen
|
||||
- Mit User-Erlaubnis: GPS, Kamera, Mikrofon, Push-Notifications
|
||||
|
||||
JS darf NICHT (ohne User-Aktion):
|
||||
- Beliebige Dateien lesen oder schreiben (FileSystem-Access nur mit User-Picker)
|
||||
- Auf andere Tabs / Fenster zugreifen (Same-Origin-Policy)
|
||||
- Direkt zu beliebigen Servern verbinden (CORS-Schutz)
|
||||
|
||||
Außerhalb des Browsers: Node.js erlaubt JS, alles zu tun was eine Programmiersprache normal kann (Files, Netzwerk, Kindprozesse). Davon später (in DHBW-Modul).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# JavaScript-Timeline
|
||||
|
||||
| Jahr | Was |
|
||||
|------|-----|
|
||||
| **1995** | Brendan Eich entwickelt JS in 10 Tagen für Netscape |
|
||||
| 1997 | ECMAScript-1 standardisiert (offizieller Name) |
|
||||
| 2009 | **Node.js** — JS auch außerhalb des Browsers |
|
||||
| **2015** | ES6 (große Erneuerung: `let`, `const`, arrow functions, classes, modules) |
|
||||
| 2017+ | jährliche Updates (ES2017, ES2018, …) |
|
||||
| heute | TypeScript als statisch-getypter Aufsatz |
|
||||
|
||||
JS ist die **am weitesten verbreitete** Programmiersprache der Welt.
|
||||
|
||||
<!--
|
||||
Brendan Eich bekam 10 Tage um JavaScript zu entwickeln — daher viele frühe Quirks (`null` ist ein object, `0 == "0"` ist true). Diese Quirks bleiben aus Kompatibilitätsgründen.
|
||||
|
||||
Node.js (2009) hat alles verändert: JS ist nicht mehr nur Browser-Spielzeug, sondern serverseitig nutzbar. Heute laufen viele große Websites auf Node-Backend (Netflix, LinkedIn, Walmart).
|
||||
|
||||
ES6 (2015) brachte JS auf moderne Sprachen-Niveau:
|
||||
- `let` und `const` statt `var`
|
||||
- Arrow functions: `(x) => x * 2`
|
||||
- Classes (Syntax-Sugar für Prototyp-Vererbung)
|
||||
- Modules: import/export
|
||||
|
||||
Seitdem: jährliche Updates mit kleineren Features.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# JavaScript einbinden
|
||||
|
||||
```html
|
||||
<!-- External (best practice) -->
|
||||
<script src="./app.js"></script>
|
||||
|
||||
<!-- Inline (für kleine Snippets) -->
|
||||
<script>
|
||||
console.log('Hallo Welt');
|
||||
</script>
|
||||
|
||||
<!-- Modern: als Modul -->
|
||||
<script type="module" src="./main.js"></script>
|
||||
```
|
||||
|
||||
**Modern:** als ES-Modul mit `type="module"`. Erlaubt `import` / `export`.
|
||||
|
||||
<!--
|
||||
Drei Wege, JS in HTML einzubinden:
|
||||
1. External via `<script src="...">` — Best Practice für nicht-triviale Apps
|
||||
2. Inline mit `<script>...</script>` — für ganz kleine Snippets, ok
|
||||
3. ES-Modul mit `type="module"` — für moderne Apps mit import/export
|
||||
|
||||
Wichtig: Script-Position
|
||||
- `<script>` im `<head>` ohne Defer/Async: blockiert das Rendern
|
||||
- `<script defer>` im head: parallel laden, vor DOMContentLoaded ausführen
|
||||
- `<script async>`: parallel laden, sofort ausführen (gefährlich für Reihenfolge)
|
||||
- `<script>` am Ende des `<body>`: erst nach HTML-Parsing
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Die Browser-Konsole ist die wichtigste JS-Spielwiese für Anfänger.
|
||||
|
||||
DevTools öffnen (F12), Tab „Console":
|
||||
- `console.log('Hallo')` → Hallo
|
||||
- `1 + 1` → 2
|
||||
- `let x = 10` → undefined, dann `x` → 10
|
||||
- `document.title` → aktueller Tab-Titel
|
||||
- `document.body.style.background = 'pink'` → Hintergrund wird pink
|
||||
|
||||
Studis können in der Konsole alles erst mal ausprobieren, bevor sie eine richtige .js-Datei schreiben.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Variablen — Daten speichern
|
||||
|
||||
```javascript
|
||||
let name = "Ada"; // veränderlich
|
||||
const PI = 3.14159; // konstant
|
||||
var alt = "vermeiden"; // pre-ES6, hat skopen-bugs
|
||||
|
||||
// Verändern:
|
||||
name = "Grace"; // OK
|
||||
PI = 3.0; // FEHLER: const kann nicht überschrieben werden
|
||||
```
|
||||
|
||||
**Faustregel:** `const` als Default. Nur `let`, wenn man umzuweisen plant. Niemals `var`.
|
||||
|
||||
<!--
|
||||
Variable-Deklaration:
|
||||
- `let`: Block-skopisch, veränderlich
|
||||
- `const`: Block-skopisch, nicht-überschreibbar
|
||||
- `var`: function-skopisch, hat historische Bugs — vermeiden
|
||||
|
||||
`const` heißt nicht „unveränderlich" — bei Objekten/Arrays kann der Inhalt verändert werden, nur die Referenz nicht.
|
||||
|
||||
```javascript
|
||||
const list = [1, 2, 3];
|
||||
list.push(4); // OK — Array selbst ist mutiert
|
||||
list = []; // FEHLER — Referenz kann nicht überschrieben werden
|
||||
```
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Datentypen
|
||||
|
||||
```javascript
|
||||
let text = "Hallo"; // string
|
||||
let zahl = 42; // number
|
||||
let ist_an = true; // boolean
|
||||
let nichts = null; // null
|
||||
let nicht_gesetzt; // undefined
|
||||
let liste = [1, 2, 3]; // array
|
||||
let objekt = { x: 1 }; // object
|
||||
|
||||
typeof text // "string"
|
||||
typeof liste // "object" (auch arrays sind objects)
|
||||
```
|
||||
|
||||
**6 Grund-Typen** + objects/arrays.
|
||||
|
||||
<!--
|
||||
JavaScript ist dynamisch typisiert: eine Variable kann verschiedene Typen halten.
|
||||
|
||||
`typeof` zeigt den Typ. Arrays und Objects sind beide „object" — historische Quirks.
|
||||
|
||||
Modern: TypeScript fügt statische Typen drüber:
|
||||
```typescript
|
||||
let zahl: number = 42;
|
||||
let text: string = "Hallo";
|
||||
```
|
||||
|
||||
Das ist ein Aufsatz, der zu JavaScript kompiliert wird.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Arrays = geordnete Listen.
|
||||
|
||||
```javascript
|
||||
let früchte = ["Apfel", "Banane", "Kirsche"];
|
||||
|
||||
früchte[0] // "Apfel"
|
||||
früchte.length // 3
|
||||
früchte.push("Datte") // hängt an
|
||||
früchte.includes("Banane") // true
|
||||
früchte.indexOf("Kirsche") // 2
|
||||
|
||||
// Array-Methoden:
|
||||
früchte.map(f => f.toUpperCase()) // ["APFEL", ...]
|
||||
früchte.filter(f => f.length > 5) // ["Banane", "Kirsche"]
|
||||
früchte.forEach(f => console.log(f))
|
||||
```
|
||||
|
||||
Alles 0-indiziert.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Objekte = Sammlung von Key-Value-Paaren.
|
||||
|
||||
```javascript
|
||||
let person = {
|
||||
name: "Ada",
|
||||
alt: 56,
|
||||
hobbies: ["Mathe", "Schach"]
|
||||
};
|
||||
|
||||
person.name // "Ada"
|
||||
person["name"] // "Ada" (gleich wie oben)
|
||||
person.alt = 57 // ändern
|
||||
|
||||
// Schlüssel:
|
||||
Object.keys(person) // ["name", "alt", "hobbies"]
|
||||
```
|
||||
|
||||
JSON ist Objekt-Notation.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Funktionen
|
||||
|
||||
```javascript
|
||||
// Function declaration
|
||||
function gruessen(name) {
|
||||
return "Hallo " + name;
|
||||
}
|
||||
|
||||
// Arrow function (modern, kompakt)
|
||||
const gruessen = (name) => "Hallo " + name;
|
||||
|
||||
// Mit mehreren Zeilen
|
||||
const summe = (a, b) => {
|
||||
const result = a + b;
|
||||
return result;
|
||||
};
|
||||
|
||||
gruessen("Ada") // "Hallo Ada"
|
||||
summe(3, 4) // 7
|
||||
```
|
||||
|
||||
<!--
|
||||
Funktionen sind in JS „first-class" — können als Variable, als Argument, als Rückgabe-Wert verwendet werden.
|
||||
|
||||
Arrow Functions sind die moderne Form (ES6+):
|
||||
- Kürzer
|
||||
- Kein eigener `this`-Kontext
|
||||
- Implizites Return bei One-Liner
|
||||
|
||||
Best Practice: arrow functions als default, function declaration wenn man hoisting braucht.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Schleifen — Wiederholungen.
|
||||
|
||||
```javascript
|
||||
// for-Schleife (klassisch)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
console.log(i); // 0, 1, 2, 3, 4
|
||||
}
|
||||
|
||||
// for...of (über Array)
|
||||
for (const frucht of ["A", "B", "C"]) {
|
||||
console.log(frucht);
|
||||
}
|
||||
|
||||
// forEach (Array-Methode)
|
||||
[1, 2, 3].forEach(n => console.log(n));
|
||||
|
||||
// map (transformieren)
|
||||
[1, 2, 3].map(n => n * 2); // [2, 4, 6]
|
||||
|
||||
// filter (auswählen)
|
||||
[1, 2, 3, 4].filter(n => n > 2); // [3, 4]
|
||||
```
|
||||
|
||||
Modern: bevorzuge map/filter/forEach über klassische for-Loops.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Kontrollstrukturen
|
||||
|
||||
```javascript
|
||||
// if / else
|
||||
if (age >= 18) {
|
||||
console.log("erwachsen");
|
||||
} else if (age >= 14) {
|
||||
console.log("jugendlich");
|
||||
} else {
|
||||
console.log("kind");
|
||||
}
|
||||
|
||||
// Ternärer Operator (Kurzform)
|
||||
const status = age >= 18 ? "erwachsen" : "kind";
|
||||
|
||||
// switch (mehrere Werte)
|
||||
switch (browser) {
|
||||
case "Chrome": return "Blink";
|
||||
case "Safari": return "WebKit";
|
||||
case "Firefox": return "Gecko";
|
||||
default: return "unknown";
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
Bedingungen mit if/else if/else — wie in vielen Sprachen.
|
||||
|
||||
Ternärer Operator ist ein Kurzschluss für einfache if/else: `condition ? a : b`.
|
||||
|
||||
switch für viele Werte, oft mit return statt break. Aber: modern oft durch Map oder Object-Lookup ersetzt:
|
||||
```javascript
|
||||
const engine = { Chrome: "Blink", Safari: "WebKit" }[browser];
|
||||
```
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Das DOM
|
||||
## HTML im Speicher des Browsers
|
||||
|
||||
<!--
|
||||
Pivot. Bis hier war JS allgemeine Programmierung. Jetzt: JS im Web-Kontext.
|
||||
|
||||
DOM = Document Object Model. Browser bauen aus HTML einen JavaScript-zugreifbaren Baum. JS kann diesen Baum manipulieren.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
DOM als Baum-Struktur.
|
||||
|
||||
Jedes HTML-Element wird zu einem JS-Object. Diese Objects sind verbunden:
|
||||
- parent: das Eltern-Element
|
||||
- children: die Kind-Elemente
|
||||
- nextSibling, previousSibling: die Nachbarn
|
||||
|
||||
Wenn JS den DOM ändert, ändert sich SOFORT die Anzeige.
|
||||
|
||||
Wichtig: JS kann nicht das HTML auf der Festplatte ändern — nur das DOM IM BROWSER. Wenn die Seite neu geladen wird, ist alles weg.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Elemente finden
|
||||
|
||||
```javascript
|
||||
// EIN Element (erstes match)
|
||||
const heading = document.querySelector('h1');
|
||||
const btn = document.querySelector('#submit-button');
|
||||
const card = document.querySelector('.card');
|
||||
|
||||
// MEHRERE Elemente (NodeList)
|
||||
const allButtons = document.querySelectorAll('button');
|
||||
const allCards = document.querySelectorAll('.card');
|
||||
|
||||
// Iterieren
|
||||
allButtons.forEach(btn => console.log(btn.textContent));
|
||||
```
|
||||
|
||||
`querySelector(...)` nimmt **denselben Selektor wie CSS.**
|
||||
|
||||
<!--
|
||||
querySelector + querySelectorAll sind die modernen Wege, Elemente im DOM zu finden.
|
||||
|
||||
CSS-Selektoren wiederverwendbar:
|
||||
- `'h1'` — alle h1
|
||||
- `'#header'` — Element mit id
|
||||
- `'.card'` — Elemente mit class
|
||||
- `'nav > a'` — direkte Kinder
|
||||
- `'input[type="email"]'` — Attribut-Selektor
|
||||
|
||||
Alternative ältere Methoden (querySelector ersetzt sie alle):
|
||||
- `getElementById('header')`
|
||||
- `getElementsByClassName('card')`
|
||||
- `getElementsByTagName('h1')`
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Elemente manipulieren — drei Hauptzugriffe:
|
||||
|
||||
```javascript
|
||||
const el = document.querySelector('.greeting');
|
||||
|
||||
// Text-Inhalt
|
||||
el.textContent = 'Hallo Welt';
|
||||
|
||||
// HTML-Inhalt (gefährlich — XSS-Risiko bei User-Input!)
|
||||
el.innerHTML = '<strong>Achtung!</strong>';
|
||||
|
||||
// Attribute
|
||||
el.setAttribute('href', 'https://librete.ch');
|
||||
el.getAttribute('class');
|
||||
|
||||
// Klassen
|
||||
el.classList.add('active');
|
||||
el.classList.remove('hidden');
|
||||
el.classList.toggle('open');
|
||||
```
|
||||
|
||||
innerHTML ist mächtig, aber bei User-Input gefährlich — XSS-Angriffe möglich. Lieber textContent + createElement.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Elemente neu erzeugen:
|
||||
|
||||
```javascript
|
||||
const newP = document.createElement('p');
|
||||
newP.textContent = 'Frisch gemacht';
|
||||
newP.classList.add('notice');
|
||||
|
||||
document.body.appendChild(newP);
|
||||
|
||||
// Elemente entfernen
|
||||
const old = document.querySelector('.old-stuff');
|
||||
old.remove();
|
||||
```
|
||||
|
||||
Verwendung: To-Do-Items dynamisch hinzufügen, Chat-Nachrichten anzeigen, Modal öffnen.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Events
|
||||
## Auf User-Aktionen reagieren
|
||||
|
||||
<!--
|
||||
Events = Ereignisse, die im Browser passieren:
|
||||
- click, dblclick
|
||||
- input, change (Form-Elemente)
|
||||
- submit (Form)
|
||||
- keydown, keyup
|
||||
- scroll, resize
|
||||
- load, DOMContentLoaded
|
||||
|
||||
JS kann auf Events „lauschen" und reagieren.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Event-Listener: callback function wird ausgeführt, wenn Event passiert.
|
||||
|
||||
```javascript
|
||||
const btn = document.querySelector('#myBtn');
|
||||
|
||||
btn.addEventListener('click', () => {
|
||||
console.log('Klick!');
|
||||
btn.textContent = 'Geklickt';
|
||||
});
|
||||
|
||||
// Mit Event-Objekt
|
||||
btn.addEventListener('click', (event) => {
|
||||
console.log(event.target); // welches Element
|
||||
console.log(event.clientX); // Maus-X-Koordinate
|
||||
});
|
||||
|
||||
// Mehrere Listener auf einem Element möglich
|
||||
btn.addEventListener('click', handler1);
|
||||
btn.addEventListener('click', handler2);
|
||||
```
|
||||
|
||||
Modern: addEventListener statt onclick-Attribut.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Häufige Events
|
||||
|
||||
| Event | Wo | Wann |
|
||||
|-------|----|----|
|
||||
| `click` | jedes Element | Maus-Klick |
|
||||
| `input` | input, textarea, select | bei jedem Tastendruck |
|
||||
| `change` | input, select | wenn Wert verändert (bei blur) |
|
||||
| `submit` | form | wenn Form abgeschickt wird |
|
||||
| `keydown` | document, input | beim Tastendruck |
|
||||
| `scroll` | window, scrollbare Elemente | beim Scrollen |
|
||||
| `load` | window | wenn Seite + Resources geladen |
|
||||
| `DOMContentLoaded` | document | wenn DOM bereit (vor Bildern) |
|
||||
|
||||
<!--
|
||||
Pro Event-Typ andere Anwendung:
|
||||
- input vs change: input feuert bei jedem Tastendruck, change erst wenn der Cursor das Feld verlässt
|
||||
- submit auf form: erlaubt preventDefault um Standard-Verhalten zu unterbinden
|
||||
- load: alles geladen (Bilder, CSS) — oft zu spät für JS
|
||||
- DOMContentLoaded: DOM ready — best practice, JS hier starten
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
preventDefault: verhindert die Standard-Reaktion.
|
||||
|
||||
```javascript
|
||||
// Form ohne page-reload submitten
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault(); // verhindert Standard-Reload
|
||||
// stattdessen: fetch + JSON
|
||||
});
|
||||
|
||||
// Link, der nicht navigieren soll
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
// stattdessen: Modal öffnen
|
||||
});
|
||||
```
|
||||
|
||||
Wichtig für moderne Single-Page-Apps — Navigation wird komplett von JS gesteuert.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
Dark-Mode-Toggle — Klassiker.
|
||||
|
||||
```javascript
|
||||
const toggle = document.querySelector('#darkmode-toggle');
|
||||
const body = document.body;
|
||||
|
||||
toggle.addEventListener('click', () => {
|
||||
body.classList.toggle('dark-mode');
|
||||
});
|
||||
```
|
||||
|
||||
CSS:
|
||||
```css
|
||||
body.dark-mode {
|
||||
background: #1a1a2e;
|
||||
color: #fff;
|
||||
}
|
||||
```
|
||||
|
||||
In ~10 Zeilen Code + ein bisschen CSS. Erste „echte" interaktive App für Anfänger.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
To-Do-Liste — der „Hello World" der Web-Apps.
|
||||
|
||||
```javascript
|
||||
const form = document.querySelector('#todo-form');
|
||||
const input = document.querySelector('#todo-input');
|
||||
const list = document.querySelector('#todo-list');
|
||||
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const text = input.value.trim();
|
||||
if (!text) return;
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.textContent = text;
|
||||
list.appendChild(li);
|
||||
|
||||
input.value = '';
|
||||
});
|
||||
```
|
||||
|
||||
Konzepte zusammen:
|
||||
- Form-Submit + preventDefault
|
||||
- Element erzeugen (createElement)
|
||||
- Element anhängen (appendChild)
|
||||
- Form zurücksetzen
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
fetch — Daten holen.
|
||||
|
||||
```javascript
|
||||
fetch('https://api.github.com/users/torvalds')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data.name); // "Linus Torvalds"
|
||||
console.log(data.public_repos);
|
||||
})
|
||||
.catch(error => console.error(error));
|
||||
|
||||
// Mit async/await (moderne syntax)
|
||||
async function ladeUser() {
|
||||
const res = await fetch('https://api.github.com/users/torvalds');
|
||||
const data = await res.json();
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
Modern: async/await statt then-Chains.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
localStorage — Daten persistent speichern (im Browser).
|
||||
|
||||
```javascript
|
||||
// Speichern (nur Strings möglich)
|
||||
localStorage.setItem('username', 'Ada');
|
||||
|
||||
// Laden
|
||||
const name = localStorage.getItem('username');
|
||||
|
||||
// Object speichern: erst JSON
|
||||
const settings = { darkmode: true, lang: 'de' };
|
||||
localStorage.setItem('settings', JSON.stringify(settings));
|
||||
|
||||
// Laden: JSON parsen
|
||||
const saved = JSON.parse(localStorage.getItem('settings'));
|
||||
|
||||
// Löschen
|
||||
localStorage.removeItem('username');
|
||||
localStorage.clear(); // alles weg
|
||||
```
|
||||
|
||||
5-10 MB pro Origin. Bleibt zwischen Sessions. Nicht für sensible Daten (nicht verschlüsselt).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Frameworks
|
||||
## Wann braucht man die?
|
||||
|
||||
<!--
|
||||
Frameworks sind „voll-tooled" Abstraktionen über die DOM-API.
|
||||
|
||||
Wenn der Code mehr als ~500 Zeilen hat, wird vanilla DOM-Manipulation unübersichtlich. Frameworks helfen mit:
|
||||
- Komponentenmodell
|
||||
- Reactive State (Daten ändert sich, UI passt automatisch an)
|
||||
- Routing
|
||||
- Tools (Build, Linter, Tests)
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# React · Vue · Angular · Svelte
|
||||
|
||||
| Framework | Typ | Stärke |
|
||||
|-----------|-----|--------|
|
||||
| **React** | Library (mit Ökosystem) | dominierend, große Community |
|
||||
| **Vue** | Framework | sanfter Einstieg, gute Doku |
|
||||
| **Angular** | Framework | „Enterprise"-Setup, Google |
|
||||
| **Svelte** | Compiler | kein Virtual DOM, kleine Bundle |
|
||||
| **Astro** | Hybrid | Static-First, Multi-Framework |
|
||||
|
||||
Alle: **Komponenten** als Konzept. **State** verändert sich → UI re-rendert.
|
||||
|
||||
<!--
|
||||
Übersicht ohne Galerie-Inflation.
|
||||
|
||||
Aktuelle Markt-Verteilung (2025-2026):
|
||||
- React: ~40% (mit Next.js Framework drum herum)
|
||||
- Vue: ~15-20% (Vue 3 + Nuxt)
|
||||
- Angular: ~10% (in Enterprise)
|
||||
- Svelte: ~5% (wächst stark)
|
||||
- Astro: ~3% (für Content-sites)
|
||||
- Vanilla: ~25% (klein-Projekte, Landing Pages)
|
||||
|
||||
Konzeptionell sind alle ähnlich: Komponenten, State, Re-Render.
|
||||
|
||||
Studis sollen wissen DASS es Frameworks gibt, aber für 223015c nicht im Detail. Tiefere Behandlung in Webentwicklung-Modulen (z.B. DHBW-Curriculum).
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Library vs. Framework
|
||||
|
||||
| | Library | Framework |
|
||||
|--|---------|-----------|
|
||||
| Wer ruft | **du** rufst die Library | das Framework ruft **dich** |
|
||||
| Beispiel | jQuery, React (offiziell), Lodash | Angular, Vue, Next.js, Astro |
|
||||
| Vorteil | mehr Freiheit | mehr Struktur |
|
||||
| Nachteil | mehr Setup-Arbeit | weniger Flexibilität |
|
||||
|
||||
**„Inversion of Control":** Library = du kontrollierst, Framework = es kontrolliert dich.
|
||||
|
||||
<!--
|
||||
Begriffsklärung:
|
||||
- Library: Sammlung von Funktionen. Du entscheidest wann/wie sie aufgerufen werden. Beispiel: `_.map(...)` von Lodash.
|
||||
- Framework: Skelett, das deinen Code aufruft. Du füllst nur die richtigen Stellen. Beispiel: Angular Component Lifecycle Hooks.
|
||||
|
||||
Grenzen sind unscharf. React positioniert sich als Library, wird mit Next.js als Framework ergänzt. Vue mit/ohne Nuxt.
|
||||
|
||||
Faustregel: wenn du `npm run dev` für etwas Eigenes brauchst, ist es ein Framework.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: aufgabe -->
|
||||
|
||||
# Selbstlernen — eigenes Mini-Projekt
|
||||
|
||||
Wähle eines:
|
||||
|
||||
**A. Dark-Mode-Toggle** — Button auf einer Seite, der `dark`-Klasse am body togglet. localStorage merkt den Zustand.
|
||||
|
||||
**B. To-Do-App** — Form, das neue Items zur Liste hinzufügt. localStorage für Persistenz.
|
||||
|
||||
**C. API-Visualisierung** — fetch zu `jsonplaceholder.typicode.com/users` und Daten als Liste rendern.
|
||||
|
||||
**Bonus:** mit GitHub Pages deployen → öffentlich zugängliche URL.
|
||||
|
||||
<!--
|
||||
Niederschwellige Praxis-Aufgabe. ~30-60 Minuten pro Variante.
|
||||
|
||||
Tools:
|
||||
- VS Code als Editor
|
||||
- Live-Server-Extension oder einfach Doppelklick auf HTML-Datei
|
||||
- Browser-DevTools für Debug
|
||||
|
||||
Lernziele:
|
||||
- Eigenes Mini-Projekt produzieren
|
||||
- DOM-Manipulation in Praxis
|
||||
- Events handhaben
|
||||
- API-Anfrage stellen (Variante C)
|
||||
- Code öffentlich teilen (Bonus mit GitHub Pages)
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
# Zusammenfassung
|
||||
|
||||
**Was JS macht:** DOM manipulieren · Events behandeln · Daten holen + speichern.
|
||||
|
||||
**Was JS NICHT macht (ohne User-Aktion):** willkürliche Datei-/Hardware-Zugriffe.
|
||||
|
||||
**Patterns:** querySelector → manipulate → addEventListener.
|
||||
|
||||
**Frameworks (React, Vue, …):** Abstraktion + State + Komponenten — für Projekte ab ~500 Zeilen.
|
||||
|
||||
→ **Du hast jetzt:** verstanden wie Daten reisen (Kap 2), wie sie dargestellt werden (HTML+CSS, Kap 1+2), und wie sie *interaktiv* werden (JS, Kap 3). Das ganze moderne Web in drei Kapiteln.
|
||||
|
||||
<!--
|
||||
Recap Kap 3 + Synthese des ganzen Kurses.
|
||||
|
||||
Ende des Kurses:
|
||||
- Pioniere → Architektur → Internet → HTML → CSS → A11y → JS
|
||||
- Studis haben einen vollständigen mentalen Bauplan des Webs
|
||||
|
||||
Anschluss:
|
||||
- Webentwicklung-Module: tieferer Stack (React, Node, Datenbanken, Deployment)
|
||||
- DHBW-Module: Industrie-Praxis-Stack
|
||||
|
||||
Klausur:
|
||||
- Hauptsächlich Kap 1+2 (Geschichte, Netzwerk, HTML, CSS, A11y)
|
||||
- JS nur konzeptionell (Block J auf Verstehen-Niveau)
|
||||
-->
|
||||
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 926 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 486 KiB |
|
After Width: | Height: | Size: 359 KiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 470 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 315 KiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 131 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: __TITLE__</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">__URL__</span>
|
||||
</div>
|
||||
<iframe src="__SRC__"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: a11y-error</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/email-form.html</span>
|
||||
</div>
|
||||
<iframe src="./a11y-error.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Fehlermeldung</title>
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; padding: 1.2rem; }
|
||||
label { display: block; margin-bottom: 4px; font-weight: 600; }
|
||||
input {
|
||||
font: inherit;
|
||||
padding: 6px 10px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid #d63384;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#email-error {
|
||||
color: #d63384;
|
||||
font-size: 0.9em;
|
||||
margin-top: 6px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<label for="email">E-Mail-Adresse</label>
|
||||
<input id="email" type="email" aria-describedby="email-error" value="michael@">
|
||||
<p id="email-error" role="alert">
|
||||
Bitte geben Sie eine gültige E-Mail-Adresse ein.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: a11y-focus</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/focus.html</span>
|
||||
</div>
|
||||
<iframe src="./a11y-focus.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Fokus-Indikator</title>
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; padding: 1.4rem; font-size: 1rem; }
|
||||
button { font: inherit; padding: 10px 18px; margin: 8px 0; display: block; border: 1.5px solid #d1d5db; background: #fff; border-radius: 4px; cursor: pointer; }
|
||||
button:focus-visible, button.is-focused {
|
||||
outline: 3px solid #d63384;
|
||||
outline-offset: 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p><strong>Tab-Taste drücken:</strong></p>
|
||||
<button class="is-focused">Erster Button</button>
|
||||
<button>Zweiter Button</button>
|
||||
<button>Dritter Button</button>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: a11y-semantic</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/klick.html</span>
|
||||
</div>
|
||||
<iframe src="./a11y-semantic.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>div vs button</title>
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; padding: 1.2rem; }
|
||||
h3 { margin: 0.8rem 0 0.4rem; font-size: 1rem; }
|
||||
.bad { color: #b91c1c; }
|
||||
.good { color: #15803d; }
|
||||
.button {
|
||||
display: inline-block;
|
||||
background: #e5e7eb;
|
||||
border: 1px solid #9ca3af;
|
||||
padding: 6px 14px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button { font: inherit; padding: 6px 14px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h3 class="bad">Schlecht (div)</h3>
|
||||
<div class="button" onclick="alert('!')">Klick mich</div>
|
||||
<p><small>❌ Tab überspringt, kein Enter, kein Screenreader</small></p>
|
||||
|
||||
<h3 class="good">Gut (button)</h3>
|
||||
<button type="button">Klick mich</button>
|
||||
<p><small>✅ Tastatur + Screenreader eingebaut</small></p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 49 KiB |
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ARP</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 30px; display: inline-block; }
|
||||
.row { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; }
|
||||
.actor {
|
||||
background: #1a1a2e;
|
||||
color: #fff;
|
||||
padding: 10px 16px;
|
||||
border-radius: 6px;
|
||||
font-weight: 700;
|
||||
min-width: 160px;
|
||||
text-align: center;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.laptop { background: #1e40af; }
|
||||
.router { background: #c2410c; }
|
||||
.arrow-right, .arrow-left {
|
||||
width: 0; height: 0;
|
||||
border-top: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
}
|
||||
.arrow-right { border-left: 14px solid #d63384; }
|
||||
.arrow-left { border-right: 14px solid #15803d; }
|
||||
.bubble {
|
||||
padding: 10px 14px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.95rem;
|
||||
max-width: 460px;
|
||||
}
|
||||
.ask { background: #fce7f3; border: 2px solid #d63384; color: #7c2d12; }
|
||||
.reply { background: #dcfce7; border: 2px solid #15803d; color: #14532d; }
|
||||
.meta {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
opacity: 0.7;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row">
|
||||
<div class="actor laptop">Laptop</div>
|
||||
<div class="arrow-right"></div>
|
||||
<div class="bubble ask">
|
||||
<div class="meta">Broadcast</div>
|
||||
"Wer hat die IP 192.168.1.1? Sag mir deine MAC!"
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="bubble reply">
|
||||
<div class="meta">Antwort</div>
|
||||
"Das bin ich! Meine MAC ist 11:22:33:44:55:66"
|
||||
</div>
|
||||
<div class="arrow-left"></div>
|
||||
<div class="actor router">Router</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 41 KiB |
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Box-Modell Diagramm</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 40px; display: inline-block; box-sizing: border-box; }
|
||||
.layer {
|
||||
padding-top: 38px;
|
||||
padding-bottom: 30px;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.layer::before {
|
||||
position: absolute;
|
||||
top: 8px; left: 14px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.margin { background: #fde68a; }
|
||||
.margin::before { content: "margin"; color: #92400e; }
|
||||
.border { background: #fca5a5; }
|
||||
.border::before { content: "border"; color: #991b1b; }
|
||||
.padding { background: #86efac; }
|
||||
.padding::before { content: "padding"; color: #166534; }
|
||||
.content {
|
||||
background: #93c5fd;
|
||||
width: 260px;
|
||||
height: 110px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #1e3a8a;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layer margin">
|
||||
<div class="layer border">
|
||||
<div class="layer padding">
|
||||
<div class="content">content</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: button</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/button.html</span>
|
||||
</div>
|
||||
<iframe src="./button.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Button</title>
|
||||
</head>
|
||||
<body>
|
||||
<button>Add to favorites</button>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,180 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Byte-Fluss: Bit → Hex → ASCII</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #1a1a2e;
|
||||
--muted: #6b7280;
|
||||
--border: #cbd5e1;
|
||||
--bg-soft: #f8fafc;
|
||||
--byte-border: #94a3b8;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
|
||||
body { padding: 22px 28px; }
|
||||
h1 { text-align: center; margin: 0 0 4px; font-size: 1.55rem; }
|
||||
.sub { text-align: center; color: var(--muted); margin-bottom: 18px; font-size: 0.95rem; }
|
||||
|
||||
.stage { display: flex; flex-direction: column; align-items: center; gap: 8px; max-width: 920px; margin: 0 auto; }
|
||||
|
||||
.file {
|
||||
width: 100%; box-sizing: border-box;
|
||||
border: 2px solid var(--dark);
|
||||
border-radius: 10px;
|
||||
background: var(--bg-soft);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
.file .head {
|
||||
background: var(--dark); color: #fff; padding: 8px 14px;
|
||||
font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700;
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
}
|
||||
.file .head .name { font-family: ui-monospace, monospace; }
|
||||
.file .head .meta { font-weight: 400; opacity: 0.7; text-transform: none; letter-spacing: 0; font-size: 0.85em; }
|
||||
.file .body { padding: 12px 14px; }
|
||||
|
||||
.row-bytes { display: flex; gap: 6px; margin-bottom: 6px; flex-wrap: nowrap; }
|
||||
.row-bytes:last-child { margin-bottom: 0; }
|
||||
|
||||
.byte-bin {
|
||||
border: 1px solid var(--byte-border);
|
||||
border-radius: 4px;
|
||||
padding: 4px 7px;
|
||||
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
||||
font-size: 0.92rem;
|
||||
font-weight: 700;
|
||||
background: #fff;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.byte-hex {
|
||||
border: 1px solid var(--byte-border);
|
||||
border-radius: 4px;
|
||||
padding: 6px 0;
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
background: #fff;
|
||||
min-width: 88px;
|
||||
text-align: center;
|
||||
}
|
||||
.byte-ascii {
|
||||
border: 1px solid var(--byte-border);
|
||||
border-radius: 4px;
|
||||
padding: 6px 0;
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
background: #fff;
|
||||
min-width: 88px;
|
||||
text-align: center;
|
||||
}
|
||||
.byte-ascii.np { color: var(--muted); font-style: italic; }
|
||||
|
||||
.truncate { color: var(--muted); font-family: ui-monospace, monospace; padding: 4px 6px; font-weight: 700; align-self: center; }
|
||||
|
||||
.arrow-stack { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 4px 0; }
|
||||
.arrow {
|
||||
width: 0; height: 0;
|
||||
border-left: 11px solid transparent;
|
||||
border-right: 11px solid transparent;
|
||||
border-top: 14px solid var(--hl);
|
||||
}
|
||||
.arrow-label {
|
||||
font-size: 0.78rem; color: var(--hl); font-weight: 700;
|
||||
text-transform: uppercase; letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.legend {
|
||||
margin-top: 12px;
|
||||
display: flex; gap: 14px; flex-wrap: wrap; justify-content: center;
|
||||
font-size: 0.85rem; color: var(--muted);
|
||||
}
|
||||
.legend strong { color: var(--dark); }
|
||||
.legend code { background: var(--bg-soft); border: 1px solid var(--border); padding: 1px 6px; border-radius: 3px; font-family: ui-monospace, monospace; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>1 Byte = 8 Bit = 2 Hex = 1 ASCII-Zeichen</h1>
|
||||
<div class="sub">Dieselbe Datei — dieselben Byte, drei Schreibweisen. Jeder Rahmen = ein Byte.</div>
|
||||
|
||||
<div class="stage">
|
||||
|
||||
<!-- Stage 1: Bitstream -->
|
||||
<div class="file">
|
||||
<div class="head"><span class="name">datei.bin</span><span class="meta">Roh-Bit · 8 Bit pro Rahmen</span></div>
|
||||
<div class="body">
|
||||
<div class="row-bytes">
|
||||
<span class="byte-bin">01001000</span><span class="byte-bin">01100101</span><span class="byte-bin">01101100</span><span class="byte-bin">01101100</span><span class="byte-bin">01101111</span><span class="byte-bin">00101100</span><span class="byte-bin">00100000</span><span class="byte-bin">01010111</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-bin">01101111</span><span class="byte-bin">01110010</span><span class="byte-bin">01101100</span><span class="byte-bin">01100100</span><span class="byte-bin">00100001</span><span class="byte-bin">00100000</span><span class="byte-bin">01001000</span><span class="byte-bin">01101111</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-bin">01110111</span><span class="byte-bin">00100000</span><span class="byte-bin">01100001</span><span class="byte-bin">01110010</span><span class="byte-bin">01100101</span><span class="byte-bin">00100000</span><span class="byte-bin">01111001</span><span class="byte-bin">01101111</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-bin">01110101</span><span class="byte-bin">00111111</span><span class="byte-bin">00001010</span><span class="truncate">… (weitere Byte)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-stack">
|
||||
<div class="arrow-label">je 8 Bit → 2 Hex-Ziffern</div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
|
||||
<!-- Stage 2: Hex -->
|
||||
<div class="file">
|
||||
<div class="head"><span class="name">datei.hex</span><span class="meta">Hex-Sicht · 2 Hex-Ziffern pro Rahmen</span></div>
|
||||
<div class="body">
|
||||
<div class="row-bytes">
|
||||
<span class="byte-hex">48</span><span class="byte-hex">65</span><span class="byte-hex">6C</span><span class="byte-hex">6C</span><span class="byte-hex">6F</span><span class="byte-hex">2C</span><span class="byte-hex">20</span><span class="byte-hex">57</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-hex">6F</span><span class="byte-hex">72</span><span class="byte-hex">6C</span><span class="byte-hex">64</span><span class="byte-hex">21</span><span class="byte-hex">20</span><span class="byte-hex">48</span><span class="byte-hex">6F</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-hex">77</span><span class="byte-hex">20</span><span class="byte-hex">61</span><span class="byte-hex">72</span><span class="byte-hex">65</span><span class="byte-hex">20</span><span class="byte-hex">79</span><span class="byte-hex">6F</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-hex">75</span><span class="byte-hex">3F</span><span class="byte-hex">0A</span><span class="truncate">…</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-stack">
|
||||
<div class="arrow-label">je 1 Byte → 1 Zeichen</div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
|
||||
<!-- Stage 3: ASCII -->
|
||||
<div class="file">
|
||||
<div class="head"><span class="name">datei.txt</span><span class="meta">Text-Sicht · 1 ASCII-Zeichen pro Rahmen</span></div>
|
||||
<div class="body">
|
||||
<div class="row-bytes">
|
||||
<span class="byte-ascii">H</span><span class="byte-ascii">e</span><span class="byte-ascii">l</span><span class="byte-ascii">l</span><span class="byte-ascii">o</span><span class="byte-ascii">,</span><span class="byte-ascii np">␣</span><span class="byte-ascii">W</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-ascii">o</span><span class="byte-ascii">r</span><span class="byte-ascii">l</span><span class="byte-ascii">d</span><span class="byte-ascii">!</span><span class="byte-ascii np">␣</span><span class="byte-ascii">H</span><span class="byte-ascii">o</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-ascii">w</span><span class="byte-ascii np">␣</span><span class="byte-ascii">a</span><span class="byte-ascii">r</span><span class="byte-ascii">e</span><span class="byte-ascii np">␣</span><span class="byte-ascii">y</span><span class="byte-ascii">o</span>
|
||||
</div>
|
||||
<div class="row-bytes">
|
||||
<span class="byte-ascii">u</span><span class="byte-ascii">?</span><span class="byte-ascii np">↵</span><span class="truncate">…</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
<span><code>␣</code> = Leerzeichen (0x20)</span>
|
||||
<span><code>↵</code> = Zeilenumbruch (0x0A, nicht druckbar)</span>
|
||||
<span><strong>Byte ändern sich nicht.</strong> Nur die Anzeige.</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 77 KiB |
@@ -0,0 +1,185 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Byte → Nibble → Hex</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #1a1a2e;
|
||||
--muted: #6b7280;
|
||||
--border: #cbd5e1;
|
||||
--bg-soft: #f8fafc;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
|
||||
body { padding: 28px 32px; }
|
||||
h1 { text-align: center; margin: 0 0 4px; font-size: 1.55rem; }
|
||||
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 0.95rem; }
|
||||
|
||||
.stage { display: flex; flex-direction: column; align-items: center; gap: 6px; }
|
||||
|
||||
.level { display: flex; flex-direction: column; align-items: center; }
|
||||
.label { font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 6px; font-weight: 600; }
|
||||
|
||||
/* Level 1: whole byte */
|
||||
.byte {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 8px 14px;
|
||||
border: 2px solid var(--dark);
|
||||
border-radius: 8px;
|
||||
background: var(--bg-soft);
|
||||
}
|
||||
.byte .bit { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 1.3rem; font-weight: 700; padding: 4px 8px; min-width: 22px; text-align: center; }
|
||||
.byte .sep { width: 2px; background: var(--hl); margin: 2px 6px; border-radius: 2px; }
|
||||
|
||||
/* Split arrows */
|
||||
.split { display: flex; justify-content: space-between; width: 360px; margin: 2px 0; }
|
||||
.split .arrow {
|
||||
width: 0; height: 0;
|
||||
border-left: 9px solid transparent;
|
||||
border-right: 9px solid transparent;
|
||||
border-top: 12px solid var(--hl);
|
||||
}
|
||||
|
||||
/* Level 2: two nibbles */
|
||||
.nibbles { display: flex; gap: 80px; }
|
||||
.nibble {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 6px;
|
||||
padding: 10px 14px;
|
||||
border: 2px solid var(--hl);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
.nibble .bits { display: flex; gap: 4px; font-family: ui-monospace, monospace; font-size: 1.15rem; font-weight: 700; }
|
||||
.nibble .bits span { padding: 2px 6px; min-width: 20px; text-align: center; }
|
||||
.nibble .meta { font-size: 0.78rem; color: var(--muted); }
|
||||
|
||||
.single-arrow {
|
||||
width: 0; height: 0;
|
||||
border-left: 9px solid transparent;
|
||||
border-right: 9px solid transparent;
|
||||
border-top: 12px solid var(--hl);
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/* Level 3: hex digits */
|
||||
.hex-digits { display: flex; gap: 80px; }
|
||||
.hex-digit {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 4px;
|
||||
padding: 8px 22px;
|
||||
border: 2px solid var(--dark);
|
||||
border-radius: 8px;
|
||||
background: var(--dark);
|
||||
color: var(--hl);
|
||||
}
|
||||
.hex-digit .digit { font-family: ui-monospace, monospace; font-size: 2rem; font-weight: 800; line-height: 1; }
|
||||
.hex-digit .meta { font-size: 0.72rem; color: #f3f4f6; opacity: 0.7; }
|
||||
|
||||
/* Merge down to byte */
|
||||
.merge {
|
||||
display: flex; justify-content: center; margin-top: 2px;
|
||||
}
|
||||
.merge-v {
|
||||
display: grid;
|
||||
grid-template-columns: 60px 60px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.merge-v .line {
|
||||
height: 20px;
|
||||
border-right: 2px solid var(--hl);
|
||||
}
|
||||
.merge-v .line.l { border-right: none; border-left: 2px solid var(--hl); }
|
||||
.bottom-bar { height: 2px; background: var(--hl); width: 120px; }
|
||||
|
||||
/* Final result */
|
||||
.result {
|
||||
margin-top: 14px;
|
||||
padding: 14px 22px;
|
||||
background: #fef3f8;
|
||||
border-left: 4px solid var(--hl);
|
||||
border-radius: 4px;
|
||||
font-size: 1.05rem;
|
||||
text-align: center;
|
||||
max-width: 640px;
|
||||
}
|
||||
.result code { background: var(--dark); color: var(--hl); padding: 2px 8px; border-radius: 4px; font-family: ui-monospace, monospace; font-weight: 700; }
|
||||
.result strong { color: var(--hl); }
|
||||
|
||||
.math {
|
||||
margin-top: 10px;
|
||||
font-size: 0.95rem;
|
||||
color: var(--dark);
|
||||
text-align: center;
|
||||
}
|
||||
.math .eq { font-family: ui-monospace, monospace; font-weight: 700; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>1 Byte → 2 Nibble → 2 Hex-Ziffern</h1>
|
||||
<div class="sub">Jedes Byte lässt sich sauber halbieren – und 4 Bit passen exakt auf eine Hex-Ziffer.</div>
|
||||
|
||||
<div class="stage">
|
||||
<!-- Level 1 -->
|
||||
<div class="level">
|
||||
<div class="label">1 Byte · 8 Bit · 2⁸ = 256 Werte</div>
|
||||
<div class="byte">
|
||||
<span class="bit">0</span><span class="bit">1</span><span class="bit">0</span><span class="bit">0</span>
|
||||
<span class="sep"></span>
|
||||
<span class="bit">1</span><span class="bit">1</span><span class="bit">0</span><span class="bit">1</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="split">
|
||||
<div class="arrow"></div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
|
||||
<!-- Level 2 -->
|
||||
<div class="level">
|
||||
<div class="label">2 Nibble · je 4 Bit · 2⁴ = 16 Werte</div>
|
||||
<div class="nibbles">
|
||||
<div class="nibble">
|
||||
<div class="bits"><span>0</span><span>1</span><span>0</span><span>0</span></div>
|
||||
<div class="meta">= 4 (dez)</div>
|
||||
</div>
|
||||
<div class="nibble">
|
||||
<div class="bits"><span>1</span><span>1</span><span>0</span><span>1</span></div>
|
||||
<div class="meta">= 13 (dez)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="split">
|
||||
<div class="arrow"></div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
|
||||
<!-- Level 3 -->
|
||||
<div class="level">
|
||||
<div class="label">2 Hex-Ziffern · Symbole 0–F</div>
|
||||
<div class="hex-digits">
|
||||
<div class="hex-digit">
|
||||
<div class="digit">4</div>
|
||||
<div class="meta">Nibble → 1 Ziffer</div>
|
||||
</div>
|
||||
<div class="hex-digit">
|
||||
<div class="digit">D</div>
|
||||
<div class="meta">13 → D</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result">
|
||||
<code>01001101</code> (bin) = <code>4D</code> (hex) = <strong>77</strong> (dez) = <strong>"M"</strong> (ASCII)
|
||||
</div>
|
||||
|
||||
<div class="math">
|
||||
<span class="eq">16 × 16 = 256</span> · <span class="eq">2⁴ × 2⁴ = 2⁸</span> · Darum passt Hex so gut zu Bytes.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</content>
|
||||
</invoke>
|
||||
|
After Width: | Height: | Size: 97 KiB |
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Client/Server Ports</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 30px; display: inline-block; }
|
||||
.endpoint {
|
||||
border: 2px solid #4a4a6a;
|
||||
border-radius: 6px;
|
||||
padding: 18px 24px;
|
||||
margin-bottom: 24px;
|
||||
min-width: 380px;
|
||||
background: #f3f4f6;
|
||||
}
|
||||
.endpoint.client { background: #dbeafe; border-color: #1e40af; }
|
||||
.endpoint.server { background: #fed7aa; border-color: #c2410c; }
|
||||
.role {
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.client .role { color: #1e3a8a; }
|
||||
.server .role { color: #7c2d12; }
|
||||
.addr {
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 1.4rem;
|
||||
color: #0f172a;
|
||||
}
|
||||
.port {
|
||||
background: #fde68a;
|
||||
color: #7c2d12;
|
||||
padding: 1px 8px;
|
||||
border-radius: 4px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.label {
|
||||
margin-top: 6px;
|
||||
font-size: 0.85rem;
|
||||
color: #4a4a6a;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="endpoint client">
|
||||
<div class="role">Client</div>
|
||||
<div class="addr">141.62.xxx.xxx:<span class="port">52431</span></div>
|
||||
<div class="label">↳ zufälliger Port vom OS</div>
|
||||
</div>
|
||||
<div class="endpoint server">
|
||||
<div class="role">Server</div>
|
||||
<div class="addr">212.132.79.37:<span class="port">443</span></div>
|
||||
<div class="label">↳ HTTPS-Standardport</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: Kontrast</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/contrast.html</span>
|
||||
</div>
|
||||
<iframe src="./contrast-levels.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Kontrast-Stufen</title>
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; padding: 1.6rem; margin: 0; }
|
||||
.row {
|
||||
background: #fff;
|
||||
padding: 22px 20px;
|
||||
margin-bottom: 14px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
}
|
||||
.sample {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
flex: 1;
|
||||
}
|
||||
.meta {
|
||||
text-align: right;
|
||||
font-size: 0.85rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ratio {
|
||||
font-family: ui-monospace, monospace;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
color: #1a1a2e;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.fail { background: #fee2e2; color: #991b1b; }
|
||||
.aa-large { background: #fed7aa; color: #7c2d12; }
|
||||
.aa { background: #dcfce7; color: #166534; }
|
||||
.aaa { background: #bbf7d0; color: #14532d; }
|
||||
.hint {
|
||||
margin-top: 14px;
|
||||
font-size: 0.78rem;
|
||||
color: #6b7280;
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
}
|
||||
.hint a { color: #d63384; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row" style="background: #fff;">
|
||||
<div class="sample" style="color: #aaaaaa;">Barrierefrei lesen</div>
|
||||
<div class="meta">
|
||||
<div class="ratio">2.3:1</div>
|
||||
<span class="badge fail">✗ Fail</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="background: #fff;">
|
||||
<div class="sample" style="color: #949494;">Barrierefrei lesen</div>
|
||||
<div class="meta">
|
||||
<div class="ratio">3:1</div>
|
||||
<span class="badge aa-large">AA Large</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="background: #fff;">
|
||||
<div class="sample" style="color: #767676;">Barrierefrei lesen</div>
|
||||
<div class="meta">
|
||||
<div class="ratio">4.5:1</div>
|
||||
<span class="badge aa">✓ AA</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="background: #fff;">
|
||||
<div class="sample" style="color: #595959;">Barrierefrei lesen</div>
|
||||
<div class="meta">
|
||||
<div class="ratio">7:1</div>
|
||||
<span class="badge aaa">✓ AAA</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="background: #fff;">
|
||||
<div class="sample" style="color: #1a1a1a;">Barrierefrei lesen</div>
|
||||
<div class="meta">
|
||||
<div class="ratio">16:1</div>
|
||||
<span class="badge aaa">✓ AAA+</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hint">Check: webaim.org/resources/contrastchecker</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 76 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-anatomie</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/anatomie.html</span>
|
||||
</div>
|
||||
<iframe src="./css-anatomie.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CSS Anatomie</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; }
|
||||
p { color: blue; font-size: 16px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Dieser Absatz ist blau und 16 Pixel groß.</p>
|
||||
<p>Alle p-Elemente werden gleich gestylt.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-box-model</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/box-model.html</span>
|
||||
</div>
|
||||
<iframe src="./css-box-model.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Box-Modell</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; background: #fff; }
|
||||
.box { display: inline-block; }
|
||||
.layer {
|
||||
padding-top: 22px;
|
||||
padding-bottom: 18px;
|
||||
padding-left: 18px;
|
||||
padding-right: 18px;
|
||||
position: relative;
|
||||
}
|
||||
.layer::before {
|
||||
position: absolute;
|
||||
top: 4px; left: 8px;
|
||||
font-size: 0.75em;
|
||||
font-weight: 600;
|
||||
}
|
||||
.margin { background: #fde68a; }
|
||||
.margin::before { content: "margin"; color: #92400e; }
|
||||
.border { background: #fca5a5; }
|
||||
.border::before { content: "border"; color: #991b1b; }
|
||||
.padding { background: #86efac; }
|
||||
.padding::before { content: "padding"; color: #166534; }
|
||||
.content {
|
||||
background: #93c5fd;
|
||||
width: 140px;
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #1e3a8a;
|
||||
font-weight: 600;
|
||||
}
|
||||
pre { background: #f3f4f6; padding: 10px; border-radius: 4px; font-size: 0.85em; margin-top: 1rem; font-family: ui-monospace, monospace; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
<div class="layer margin">
|
||||
<div class="layer border">
|
||||
<div class="layer padding">
|
||||
<div class="content">content</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<pre>.box {
|
||||
width: 140px;
|
||||
padding: 18px;
|
||||
border: 18px solid;
|
||||
margin: 18px;
|
||||
}</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-colors</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/colors.html</span>
|
||||
</div>
|
||||
<iframe src="./css-colors.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Farben</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; font-size: 14px; }
|
||||
.swatch { display: flex; align-items: center; margin-bottom: 8px; }
|
||||
.chip { width: 40px; height: 40px; border-radius: 4px; margin-right: 12px; border: 1px solid #e5e7eb; }
|
||||
code { background: #f3f4f6; padding: 2px 6px; border-radius: 3px; font-family: ui-monospace, monospace; font-size: 0.85em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="swatch"><div class="chip" style="background: red;"></div><code>color: red;</code></div>
|
||||
<div class="swatch"><div class="chip" style="background: rebeccapurple;"></div><code>color: rebeccapurple;</code></div>
|
||||
<div class="swatch"><div class="chip" style="background: #FF0000;"></div><code>#FF0000</code></div>
|
||||
<div class="swatch"><div class="chip" style="background: rgb(255, 0, 0);"></div><code>rgb(255, 0, 0)</code></div>
|
||||
<div class="swatch"><div class="chip" style="background: rgba(255, 0, 0, 0.5);"></div><code>rgba(255, 0, 0, 0.5)</code></div>
|
||||
<div class="swatch"><div class="chip" style="background: hsl(0, 100%, 50%);"></div><code>hsl(0, 100%, 50%)</code></div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-combinators</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/combinators.html</span>
|
||||
</div>
|
||||
<iframe src="./css-combinators.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Kombinatoren</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; font-size: 14px; }
|
||||
article p { line-height: 1.6; background: #fef3c7; padding: 4px; }
|
||||
nav > a { text-decoration: none; color: #d63384; margin-right: 10px; font-weight: 600; }
|
||||
h2 + p { font-size: 1.2em; color: #065f46; }
|
||||
p.wichtig { color: red; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="#">Link</a><a href="#">Link</a>
|
||||
</nav>
|
||||
<article>
|
||||
<h2>Artikel-Überschrift</h2>
|
||||
<p>Direkt nach h2 (größer, grün).</p>
|
||||
<p>Normaler Absatz im article (gelb).</p>
|
||||
<p class="wichtig">Wichtig (rot).</p>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-pseudo-classes</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/pseudo-classes.html</span>
|
||||
</div>
|
||||
<iframe src="./css-pseudo-classes.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Pseudo-Klassen</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; font-size: 14px; }
|
||||
a { color: #2563eb; }
|
||||
a:hover, a.is-hovered { color: red; text-decoration: underline; }
|
||||
a:visited, a.is-visited { color: purple; }
|
||||
input:focus, input.is-focused { border-color: blue; outline: 2px solid blue; }
|
||||
input { padding: 4px 8px; border: 1px solid #9ca3af; border-radius: 3px; }
|
||||
ul { list-style: none; padding: 0; }
|
||||
li { padding: 6px 10px; }
|
||||
li:first-child, li.is-first { font-weight: bold; }
|
||||
li:nth-child(odd), li.is-odd { background: #eee; }
|
||||
h3 { margin: 0.6rem 0 0.3rem; font-size: 0.95rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h3>:hover / :visited</h3>
|
||||
<a href="#" class="is-hovered">Link mit Hover</a> ·
|
||||
<a href="#" class="is-visited">Besuchter Link</a>
|
||||
|
||||
<h3>:focus</h3>
|
||||
<input class="is-focused" value="fokussiert">
|
||||
|
||||
<h3>:first-child, :nth-child(odd)</h3>
|
||||
<ul>
|
||||
<li class="is-first is-odd">Erster (bold, zebra)</li>
|
||||
<li>Zweiter</li>
|
||||
<li class="is-odd">Dritter (zebra)</li>
|
||||
<li>Vierter</li>
|
||||
<li class="is-odd">Fünfter (zebra)</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 57 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-pseudo-elements</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/pseudo-elements.html</span>
|
||||
</div>
|
||||
<iframe src="./css-pseudo-elements.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Pseudo-Elemente</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; font-size: 14px; }
|
||||
.required::before {
|
||||
content: "* ";
|
||||
color: red;
|
||||
}
|
||||
p.drop { line-height: 1.5; }
|
||||
p.drop::first-letter {
|
||||
font-size: 3em;
|
||||
font-weight: bold;
|
||||
color: #d63384;
|
||||
float: left;
|
||||
line-height: 0.9;
|
||||
padding-right: 6px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
label { display: block; margin-top: 10px; }
|
||||
input { padding: 4px 8px; border: 1px solid #9ca3af; border-radius: 3px; margin-top: 3px; }
|
||||
h3 { margin: 0.6rem 0 0.3rem; font-size: 0.95rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h3>::before (Pflichtfeld-Sternchen)</h3>
|
||||
<label class="required">E-Mail-Adresse</label>
|
||||
<input type="email">
|
||||
|
||||
<h3>::first-letter (Initial-Buchstabe)</h3>
|
||||
<p class="drop">Lorem ipsum dolor sit amet. Der erste Buchstabe wird per CSS hervorgehoben – kein extra HTML nötig.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 54 KiB |
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Responsive Container</title>
|
||||
<style>
|
||||
body { padding: 0; margin: 0; font-family: system-ui, sans-serif; background: #fff; }
|
||||
.container {
|
||||
padding: 1rem;
|
||||
background: white;
|
||||
color: #111;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
border: 1px solid #d1d5db;
|
||||
}
|
||||
.container::before { content: "< 768px — weiß, padding 1rem"; }
|
||||
@media (min-width: 768px) {
|
||||
.container { padding: 2rem; background: red; color: white; border: none; }
|
||||
.container::before { content: "≥ 768px — rot, padding 2rem"; }
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container { background: green; }
|
||||
.container::before { content: "≥ 1024px — grün"; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-responsive</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/responsive.html</span>
|
||||
</div>
|
||||
<iframe src="./css-responsive.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Responsive Design – 3 Viewports</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; font-family: system-ui, sans-serif; background: #fff; }
|
||||
body { padding: 1rem; }
|
||||
.viewport {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #9ca3af;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bar {
|
||||
background: #e5e7eb;
|
||||
padding: 4px 10px;
|
||||
font-size: 11px;
|
||||
color: #374151;
|
||||
font-family: ui-monospace, monospace;
|
||||
border-bottom: 1px solid #9ca3af;
|
||||
}
|
||||
iframe { display: block; width: 100%; border: 0; }
|
||||
.vp-mobile iframe { width: 360px; }
|
||||
.vp-tablet iframe { width: 800px; }
|
||||
.vp-desktop iframe { width: 1100px; }
|
||||
.vp-mobile { width: 362px; }
|
||||
.scroll { overflow: hidden; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="viewport vp-mobile">
|
||||
<div class="bar">Mobile @ 360px</div>
|
||||
<div class="scroll"><iframe src="./css-responsive-container.html" height="80"></iframe></div>
|
||||
</div>
|
||||
<div class="viewport vp-tablet">
|
||||
<div class="bar">Tablet @ 800px</div>
|
||||
<div class="scroll" style="overflow-x: auto;"><iframe src="./css-responsive-container.html" height="100"></iframe></div>
|
||||
</div>
|
||||
<div class="viewport vp-desktop">
|
||||
<div class="bar">Desktop @ 1100px</div>
|
||||
<div class="scroll" style="overflow-x: auto;"><iframe src="./css-responsive-container.html" height="100"></iframe></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-selector-class</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/selector-class.html</span>
|
||||
</div>
|
||||
<iframe src="./css-selector-class.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Klassen-Selektor</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; }
|
||||
.wichtig { color: red; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p class="wichtig">Dieser Text ist wichtig.</p>
|
||||
<p>Dieser nicht.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-selector-element</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/selector-element.html</span>
|
||||
</div>
|
||||
<iframe src="./css-selector-element.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Element-Selektor</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; }
|
||||
p { color: gray; font-family: Georgia, serif; }
|
||||
h1, h2, h3 { font-family: sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Überschrift (sans-serif)</h1>
|
||||
<p>Absatz: grau, Georgia (serif).</p>
|
||||
<h2>Untertitel (sans-serif)</h2>
|
||||
<p>Noch ein grauer Absatz.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-selector-id</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/selector-id.html</span>
|
||||
</div>
|
||||
<iframe src="./css-selector-id.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ID-Selektor</title>
|
||||
<style>
|
||||
body { padding: 0; margin: 0; font-family: system-ui, sans-serif; }
|
||||
#hauptnavigation {
|
||||
background: #333;
|
||||
padding: 1rem;
|
||||
color: white;
|
||||
}
|
||||
#hauptnavigation a { color: #fff; margin-right: 1rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="hauptnavigation">
|
||||
<a href="#">Home</a>
|
||||
<a href="#">Kurse</a>
|
||||
<a href="#">Kontakt</a>
|
||||
</nav>
|
||||
<p style="padding: 1rem;">Rest der Seite.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: css-specificity</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/specificity.html</span>
|
||||
</div>
|
||||
<iframe src="./css-specificity.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Spezifität</title>
|
||||
<style>
|
||||
body { padding: 1.2rem; font-family: system-ui, sans-serif; }
|
||||
p { color: blue; } /* 0,0,0,1 */
|
||||
.text { color: green; } /* 0,0,1,0 */
|
||||
#intro { color: red; } /* 0,1,0,0 */
|
||||
code { background: #f3f4f6; padding: 1px 5px; border-radius: 3px; font-size: 0.9em; }
|
||||
.row { margin-bottom: 10px; }
|
||||
.label { color: #6b7280; font-size: 0.85em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row">
|
||||
<p>Nur <code>p</code>: <strong>blau</strong></p>
|
||||
<span class="label">0,0,0,1</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="text">Nur <code>.text</code>: <strong>grün</strong> schlägt p</p>
|
||||
<span class="label">0,0,1,0 > 0,0,0,1</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p id="intro" class="text">ID <code>#intro</code>: <strong>rot</strong> schlägt alles</p>
|
||||
<span class="label">0,1,0,0 > 0,0,1,0</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Decapsulation Stack</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 30px; display: inline-block; }
|
||||
.stack { display: flex; flex-direction: column; gap: 0; }
|
||||
.layer {
|
||||
border: 2px solid;
|
||||
border-radius: 6px;
|
||||
padding: 10px 18px;
|
||||
min-width: 540px;
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.layer-name { font-weight: 700; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.8; }
|
||||
.layer-desc { font-family: ui-monospace, monospace; margin-top: 3px; }
|
||||
.check { margin-top: 3px; font-size: 0.85rem; font-style: italic; }
|
||||
.http { background: #e0e7ff; border-color: #4f46e5; color: #3730a3; }
|
||||
.tcp { background: #dbeafe; border-color: #1e40af; color: #1e3a8a; }
|
||||
.ip { background: #dcfce7; border-color: #15803d; color: #14532d; }
|
||||
.eth { background: #fed7aa; border-color: #c2410c; color: #7c2d12; }
|
||||
.bit { background: #e5e7eb; border-color: #4b5563; color: #1f2937; }
|
||||
.arrow {
|
||||
align-self: center;
|
||||
width: 0; height: 0;
|
||||
border-left: 9px solid transparent;
|
||||
border-right: 9px solid transparent;
|
||||
border-top: 12px solid #d63384;
|
||||
margin: 2px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stack">
|
||||
<div class="layer bit">
|
||||
<div class="layer-name">Physical</div>
|
||||
<div class="layer-desc">Bits empfangen</div>
|
||||
</div>
|
||||
<div class="arrow"></div>
|
||||
<div class="layer eth">
|
||||
<div class="layer-name">Ethernet-Frame</div>
|
||||
<div class="check">MAC = meine MAC? ✓ auspacken</div>
|
||||
</div>
|
||||
<div class="arrow"></div>
|
||||
<div class="layer ip">
|
||||
<div class="layer-name">IP-Paket</div>
|
||||
<div class="check">Ziel-IP = meine IP? ✓ auspacken</div>
|
||||
</div>
|
||||
<div class="arrow"></div>
|
||||
<div class="layer tcp">
|
||||
<div class="layer-name">TCP-Segment</div>
|
||||
<div class="check">Port 52431 = mein Browser? ✓ auspacken</div>
|
||||
</div>
|
||||
<div class="arrow"></div>
|
||||
<div class="layer http">
|
||||
<div class="layer-name">HTTP-Response</div>
|
||||
<div class="layer-desc">"HTTP/1.1 200 OK ..."</div>
|
||||
<div class="check">→ Browser rendert Seite</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: details-closed</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/details.html</span>
|
||||
</div>
|
||||
<iframe src="./details-closed.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Details/Summary</title>
|
||||
</head>
|
||||
<body>
|
||||
<details>
|
||||
<summary>Klick mich!</summary>
|
||||
<p>Dieser Text war versteckt.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: details-open</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/details.html</span>
|
||||
</div>
|
||||
<iframe src="./details-open.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Details/Summary (offen)</title>
|
||||
</head>
|
||||
<body>
|
||||
<details open>
|
||||
<summary>Klick mich!</summary>
|
||||
<p>Dieser Text war versteckt.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview: dialog</title>
|
||||
<style>
|
||||
:root {
|
||||
--hl: #d63384;
|
||||
--dark: #0f0f23;
|
||||
--chrome: #1a1a2e;
|
||||
--muted: #4a4a6a;
|
||||
}
|
||||
html, body { margin: 0; padding: 0; background: var(--dark); font-family: system-ui, -apple-system, sans-serif; }
|
||||
.browser { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 18px; }
|
||||
.window { background: #fff; border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.35); overflow: hidden; border: 2px solid var(--hl); }
|
||||
.chrome { background: var(--chrome); border-bottom: 2px solid var(--hl); padding: 10px 14px; display: flex; align-items: center; gap: 7px; }
|
||||
.dot { width: 11px; height: 11px; border-radius: 50%; opacity: 0.9; }
|
||||
.r { background: #ff5f56; } .y { background: #ffbd2e; } .g { background: #27c93f; }
|
||||
.url { flex: 1; margin-left: 12px; background: var(--dark); border: 1px solid var(--hl); border-radius: 6px; padding: 5px 10px; font: 12px/1.3 ui-monospace, "SF Mono", Menlo, monospace; color: var(--hl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
iframe { display: block; width: 100%; height: 700px; border: 0; background: #fff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="browser">
|
||||
<div class="window">
|
||||
<div class="chrome">
|
||||
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
|
||||
<span class="url">file:///beispiel/dialog.html</span>
|
||||
</div>
|
||||
<iframe src="./dialog.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<dialog open>
|
||||
<p>Greetings, one and all!</p>
|
||||
<form method="dialog">
|
||||
<button>OK</button>
|
||||
</form>
|
||||
</dialog>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,129 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>DNS-Lookup Sequence</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 30px; display: inline-block; }
|
||||
.diagram { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; min-width: 900px; }
|
||||
.actor {
|
||||
background: #1a1a2e;
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
font-weight: 700;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.lifeline {
|
||||
border-left: 2px dashed #9ca3af;
|
||||
margin-left: 50%;
|
||||
height: 480px;
|
||||
position: relative;
|
||||
}
|
||||
.msg {
|
||||
position: absolute;
|
||||
padding: 6px 10px;
|
||||
background: #f3f4f6;
|
||||
border: 1px solid #4a4a6a;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.arrow-right {
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
background: #d63384;
|
||||
}
|
||||
.arrow-right::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -1px; top: -4px;
|
||||
border-left: 8px solid #d63384;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
}
|
||||
.arrow-left {
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
background: #15803d;
|
||||
}
|
||||
.arrow-left::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -1px; top: -4px;
|
||||
border-right: 8px solid #15803d;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
}
|
||||
.arrow-label {
|
||||
position: absolute;
|
||||
font-size: 0.75rem;
|
||||
background: #fff;
|
||||
padding: 1px 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ask { color: #7c2d12; }
|
||||
.reply { color: #14532d; font-style: italic; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="diagram">
|
||||
<div class="actor">Ihr Laptop</div>
|
||||
<div class="actor">Resolver</div>
|
||||
<div class="actor">Root (.)</div>
|
||||
<div class="actor">.de-Server</div>
|
||||
<div class="actor">HdM-NS</div>
|
||||
<!-- lifelines (5 cols) -->
|
||||
<div style="position: relative; grid-column: 1 / span 5; height: 520px;">
|
||||
<!-- vertical dashed lines per actor at 10%, 30%, 50%, 70%, 90% -->
|
||||
<div style="position: absolute; left: 10%; top: 0; bottom: 0; border-left: 2px dashed #9ca3af;"></div>
|
||||
<div style="position: absolute; left: 30%; top: 0; bottom: 0; border-left: 2px dashed #9ca3af;"></div>
|
||||
<div style="position: absolute; left: 50%; top: 0; bottom: 0; border-left: 2px dashed #9ca3af;"></div>
|
||||
<div style="position: absolute; left: 70%; top: 0; bottom: 0; border-left: 2px dashed #9ca3af;"></div>
|
||||
<div style="position: absolute; left: 90%; top: 0; bottom: 0; border-left: 2px dashed #9ca3af;"></div>
|
||||
|
||||
<!-- Laptop → Resolver at y=20 -->
|
||||
<div style="position: absolute; left: 10%; top: 20px; width: 20%; height: 2px; background: #d63384;"></div>
|
||||
<div style="position: absolute; left: 30%; top: 16px; transform: translateX(-100%);"><div style="border-left: 8px solid #d63384; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 12%; top: 0; font-size: 0.75rem; color: #7c2d12;">"Wo ist www.hdm-stuttgart.de?"</div>
|
||||
|
||||
<!-- Resolver → Root at y=90 -->
|
||||
<div style="position: absolute; left: 30%; top: 90px; width: 20%; height: 2px; background: #d63384;"></div>
|
||||
<div style="position: absolute; left: 50%; top: 86px; transform: translateX(-100%);"><div style="border-left: 8px solid #d63384; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 70px; font-size: 0.75rem; color: #7c2d12;">"Wer verwaltet .de?"</div>
|
||||
|
||||
<!-- Root → Resolver at y=150 -->
|
||||
<div style="position: absolute; left: 30%; top: 150px; width: 20%; height: 2px; background: #15803d;"></div>
|
||||
<div style="position: absolute; left: 30%; top: 146px;"><div style="border-right: 8px solid #15803d; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 130px; font-size: 0.75rem; color: #14532d; font-style: italic;">"Frag 194.0.0.53"</div>
|
||||
|
||||
<!-- Resolver → .de at y=220 -->
|
||||
<div style="position: absolute; left: 30%; top: 220px; width: 40%; height: 2px; background: #d63384;"></div>
|
||||
<div style="position: absolute; left: 70%; top: 216px; transform: translateX(-100%);"><div style="border-left: 8px solid #d63384; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 200px; font-size: 0.75rem; color: #7c2d12;">"Wer verwaltet hdm-stuttgart.de?"</div>
|
||||
|
||||
<!-- .de → Resolver at y=280 -->
|
||||
<div style="position: absolute; left: 30%; top: 280px; width: 40%; height: 2px; background: #15803d;"></div>
|
||||
<div style="position: absolute; left: 30%; top: 276px;"><div style="border-right: 8px solid #15803d; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 260px; font-size: 0.75rem; color: #14532d; font-style: italic;">"Frag Nameserver der HdM"</div>
|
||||
|
||||
<!-- Resolver → HdM at y=350 -->
|
||||
<div style="position: absolute; left: 30%; top: 350px; width: 60%; height: 2px; background: #d63384;"></div>
|
||||
<div style="position: absolute; left: 90%; top: 346px; transform: translateX(-100%);"><div style="border-left: 8px solid #d63384; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 330px; font-size: 0.75rem; color: #7c2d12;">"Welche IP hat www?"</div>
|
||||
|
||||
<!-- HdM → Resolver at y=410 -->
|
||||
<div style="position: absolute; left: 30%; top: 410px; width: 60%; height: 2px; background: #15803d;"></div>
|
||||
<div style="position: absolute; left: 30%; top: 406px;"><div style="border-right: 8px solid #15803d; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 32%; top: 390px; font-size: 0.75rem; color: #14532d; font-style: italic;">"212.132.79.37"</div>
|
||||
|
||||
<!-- Resolver → Laptop at y=480 -->
|
||||
<div style="position: absolute; left: 10%; top: 480px; width: 20%; height: 2px; background: #15803d;"></div>
|
||||
<div style="position: absolute; left: 10%; top: 476px;"><div style="border-right: 8px solid #15803d; border-top: 5px solid transparent; border-bottom: 5px solid transparent;"></div></div>
|
||||
<div style="position: absolute; left: 12%; top: 460px; font-size: 0.75rem; color: #14532d; font-style: italic;">"IP ist 212.132.79.37"</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 73 KiB |
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>DNS-Hierarchie</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 20px; display: inline-block; }
|
||||
svg { display: block; }
|
||||
.node rect { fill: #fef3c7; stroke: #ca8a04; stroke-width: 2; rx: 6; }
|
||||
.node.root rect { fill: #fde68a; stroke: #b45309; }
|
||||
.node.leaf rect { fill: #dbeafe; stroke: #1e40af; }
|
||||
.node text { font-family: ui-monospace, monospace; font-weight: 700; font-size: 15px; fill: #713f12; }
|
||||
.node.leaf text { fill: #1e3a8a; }
|
||||
.line { stroke: #d63384; stroke-width: 2; fill: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<svg width="620" height="520" viewBox="0 0 620 520">
|
||||
<!-- Root -->
|
||||
<g class="node root">
|
||||
<rect x="250" y="10" width="120" height="44"/>
|
||||
<text x="310" y="38" text-anchor="middle">. (Root)</text>
|
||||
</g>
|
||||
<!-- Lines from Root to .de, .com, .org -->
|
||||
<line class="line" x1="310" y1="54" x2="70" y2="120"/>
|
||||
<line class="line" x1="310" y1="54" x2="310" y2="120"/>
|
||||
<line class="line" x1="310" y1="54" x2="550" y2="120"/>
|
||||
<!-- .de -->
|
||||
<g class="node">
|
||||
<rect x="20" y="120" width="100" height="44"/>
|
||||
<text x="70" y="148" text-anchor="middle">.de</text>
|
||||
</g>
|
||||
<!-- .com -->
|
||||
<g class="node">
|
||||
<rect x="260" y="120" width="100" height="44"/>
|
||||
<text x="310" y="148" text-anchor="middle">.com</text>
|
||||
</g>
|
||||
<!-- .org -->
|
||||
<g class="node">
|
||||
<rect x="500" y="120" width="100" height="44"/>
|
||||
<text x="550" y="148" text-anchor="middle">.org</text>
|
||||
</g>
|
||||
<!-- Line .de → hdm-stuttgart -->
|
||||
<line class="line" x1="70" y1="164" x2="70" y2="210"/>
|
||||
<line class="line" x1="70" y1="210" x2="220" y2="210"/>
|
||||
<line class="line" x1="220" y1="210" x2="220" y2="250"/>
|
||||
<!-- hdm-stuttgart -->
|
||||
<g class="node">
|
||||
<rect x="120" y="250" width="200" height="44"/>
|
||||
<text x="220" y="278" text-anchor="middle">hdm-stuttgart</text>
|
||||
</g>
|
||||
<!-- Line hdm → www -->
|
||||
<line class="line" x1="220" y1="294" x2="220" y2="340"/>
|
||||
<!-- www -->
|
||||
<g class="node leaf">
|
||||
<rect x="170" y="340" width="100" height="44"/>
|
||||
<text x="220" y="368" text-anchor="middle">www</text>
|
||||
</g>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>DOM-Baum</title>
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
||||
body { padding: 30px; display: inline-block; }
|
||||
.tree { display: flex; flex-direction: column; align-items: center; }
|
||||
.node {
|
||||
background: #dbeafe;
|
||||
border: 2px solid #1e40af;
|
||||
color: #1e3a8a;
|
||||
padding: 7px 16px;
|
||||
border-radius: 6px;
|
||||
font-family: ui-monospace, monospace;
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.root { background: #e0e7ff; border-color: #4f46e5; color: #3730a3; }
|
||||
.content { background: #dcfce7; border-color: #15803d; color: #14532d; font-weight: 400; font-style: italic; }
|
||||
.level { display: flex; gap: 28px; margin-top: 10px; align-items: flex-start; }
|
||||
.col { display: flex; flex-direction: column; align-items: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="tree">
|
||||
<div class="node root">document</div>
|
||||
<svg width="200" height="24"><line x1="100" y1="0" x2="100" y2="24" stroke="#d63384" stroke-width="2"/></svg>
|
||||
<div class="node root"><html></div>
|
||||
<svg width="380" height="26">
|
||||
<line x1="190" y1="0" x2="90" y2="26" stroke="#d63384" stroke-width="2"/>
|
||||
<line x1="190" y1="0" x2="290" y2="26" stroke="#d63384" stroke-width="2"/>
|
||||
</svg>
|
||||
<div class="level">
|
||||
<div class="col">
|
||||
<div class="node"><head></div>
|
||||
<svg width="120" height="22"><line x1="60" y1="0" x2="60" y2="22" stroke="#d63384" stroke-width="2"/></svg>
|
||||
<div class="node"><title></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="node"><body></div>
|
||||
<svg width="220" height="26">
|
||||
<line x1="110" y1="0" x2="55" y2="26" stroke="#d63384" stroke-width="2"/>
|
||||
<line x1="110" y1="0" x2="165" y2="26" stroke="#d63384" stroke-width="2"/>
|
||||
</svg>
|
||||
<div class="level">
|
||||
<div class="node"><h1></div>
|
||||
<div class="node"><p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 23 KiB |