Files
uni/slides/dhbw/02_css_extended.md

444 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering DHBW Stuttgart"
footer: "Michael Czechowski SoSe 2026"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #005f8a;
--color-dimmed: #4a6a7a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.7rem;
}
h1 {
color: #005f8a;
}
section.invert h1 {
color: #fff;
}
pre {
background: #0f1e2e;
color: #00b4d8;
border-radius: 8px;
border-left: 3px solid #005f8a;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a3a4a;
color: #00b4d8;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# CSS: Extended
---
# CSS Selectors Tag, Class, ID, Attribute
```css
/* Tag */
p { color: #333; }
/* Class */
.button { background: blue; }
/* ID */
#header { height: 60px; }
/* Attribute */
input[type="text"] { border: 1px solid #ccc; }
input[disabled] { background: #eee; }
```
---
# CSS Selectors Attribut-Selektoren
```css
/* presence */
[disabled] { opacity: 0.5; }
/* exact value */
[type="email"] { border-color: blue; }
/* contains word */
[class~="btn"] { cursor: pointer; }
/* starts with */
[href^="https"] { color: green; }
/* ends with */
[src$=".png"] { border: 1px solid #ccc; }
/* contains substring */
[class*="icon"] { padding-left: 20px; }
```
---
# CSS Combinators
```css
/* Child (direkt) */
div > p { margin: 0; }
/* Descendant (Nachkomme) */
div p { margin: 0; }
/* Next Sibling */
h1 + p { font-size: 1.2em; }
/* Subsequent Sibling */
h1 ~ p { color: #666; }
/* Selector List */
h1, h2, h3 { font-weight: bold; }
```
---
# Pseudo Classes
```css
/* User Interaction */
:hover { color: red; }
:active { background: blue; }
:focus { outline: 2px solid orange; }
/* Structure */
:first-child { margin-left: 0; }
:last-child { margin-right: 0; }
:nth-child(odd) { background: #f9f9f9; }
/* Links */
:visited { color: purple; }
:link { color: blue; }
```
---
# Pseudo Classes More
```css
/* Form States */
:valid { border-color: green; }
:invalid { border-color: red; }
:placeholder-shown { color: #999; }
/* Content */
:before { content: "→ "; }
:after { content: " [Wichtig]"; }
:first-letter { font-size: 2em; }
:first-line { font-weight: bold; }
/* NOT */
:not(.disabled) { pointer-events: auto; }
:not(:last-child) { border-bottom: 1px solid #ccc; }
```
---
# Shorthand Properties
```css
/* margin: top right bottom left */
margin: 10px 20px 10px 20px;
/* centering */
margin: 0 auto;
/* padding same */
padding: 20px;
/* border: width style color */
border: 1px solid #333;
/* background: color image position/size repeat */
background: #fff url(logo.png) 0 0 no-repeat;
/* font: style variant weight size/line-height family */
font: italic normal bold 16px/1.5 Arial, sans-serif;
```
---
# Flexbox Shorthands
```css
/* flex: grow shrink basis */
flex: 1 0 auto;
/* place-items: align-items justify-items */
place-items: center stretch;
/* place-content: align-content justify-content */
place-content: space-between center;
/* gap: row-gap column-gap */
gap: 20px 40px;
```
---
# CSS Custom Properties (Variables)
```css
:root {
--primary-color: #005f8a;
--spacing: 20px;
--radius: 8px;
}
.button {
background: var(--primary-color);
padding: var(--spacing);
border-radius: var(--radius);
}
```
---
# CSS Functions
```css
/* calc */
width: calc(100% - 40px);
/* min/max/clamp */
width: min(100%, 600px);
font-size: clamp(14px, 2vw, 20px);
/* var with fallback */
color: var(--text-color, #333);
/* rgb/rgba/hsl/hsla */
color: hsl(200, 100%, 50%);
background: rgba(0, 0, 0, 0.5);
```
---
# Transition & Animation
```css
/* transition: property duration timing-function */
transition: all 0.3s ease-in-out;
transition: background 0.2s, transform 0.1s;
/* animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-out;
}
```
---
# CSS Specificity
Welcher Selektor gewinnt? **Punktezählung:**
```
ID 0,1,0,0
Class / Attr / Pseudo-Class 0,0,1,0
Tag / Pseudo-Element 0,0,0,1
Inline Style 1,0,0,0
!important setzt alles außer Kraft
```
```css
#main .btn:hover /* 0,1,2,0 */
.btn.primary /* 0,0,2,0 */
button[type="submit"] /* 0,0,1,1 */
```
→ Faustregel: möglichst flach. `!important` vermeiden.
---
# CSS Frameworks
| Framework | Stil |
|-----------|------|
| **Bootstrap** | Komponenten + Grid, opinionated |
| **Tailwind CSS** | Utility-First, atomar |
| **Bulma** | klassisch, ohne JS |
| **shadcn/ui** | kopierbare Komponenten (Tailwind-basiert) |
| **Flowbite** | Tailwind-Komponentenbib. |
---
# Tailwind CSS Beispiel
```html
<button class="bg-blue-600 hover:bg-blue-700
text-white font-semibold
px-4 py-2 rounded-lg
transition shadow-sm">
Klick mich
</button>
```
- Keine eigenen CSS-Klassen mehr
- JIT-Compiler erzeugt nur genutzte Klassen
- Design-System via `tailwind.config.js`
---
<!-- _class: invert -->
<!-- _backgroundColor: #001520 -->
# No JavaScript, No Cry
## Native HTML statt JS-Komponenten
---
# Native HTML Was früher JS brauchte
| Komponente | Native Alternative |
|------------|--------------------|
| Accordion / Collapsible | `<details>` + `<summary>` |
| Modal / Dialog | `<dialog>` |
| Date Picker | `<input type="date">` |
| Time Picker | `<input type="time">` |
| Color Picker | `<input type="color">` |
| Range Slider | `<input type="range">` |
| Progress Bar | `<progress>` |
| Auto-Complete | `<datalist>` |
→ Baseline Widely Available (Chrome, Firefox, Safari, Edge).
---
# `<details>` + `<summary>`
```html
<details>
<summary>Mehr Infos</summary>
<p>Hier steht der ausklappbare Inhalt.</p>
</details>
```
- Keine Zeile JS
- Tastatur-zugänglich
- Animierbar mit `::details-content` (CSS only)
---
# `<dialog>` Native Modal
```html
<dialog id="myDialog">
<form method="dialog">
<p>Wirklich löschen?</p>
<button value="cancel">Abbrechen</button>
<button value="ok">OK</button>
</form>
</dialog>
<button onclick="myDialog.showModal()">Öffnen</button>
```
- `showModal()` blockt Hintergrund + ESC schließt
- Backdrop via `dialog::backdrop`
- Form mit `method="dialog"` schließt + liefert `returnValue`
---
# `<input type="date">` & Co.
```html
<input type="date" min="2026-01-01" max="2026-12-31">
<input type="time" step="60">
<input type="color" value="#005f8a">
<input type="range" min="0" max="100" step="5" value="50">
<input type="number" min="1" max="300">
```
- Plattform-native UI (Touch-Datepicker auf Mobile)
- Validierung "for free"
- Locale-Awareness vom Browser
---
# `<progress>` Native Progress Bar
```html
<progress value="70" max="100">70%</progress>
<!-- indeterminate -->
<progress></progress>
```
```css
progress {
width: 100%;
height: 0.5rem;
}
progress::-webkit-progress-bar { background: #eee; }
progress::-webkit-progress-value { background: #005f8a; }
```
---
# Form Validation Native
```html
<form>
<input type="email" required
pattern=".+@dhbw\.de"
title="Bitte DHBW-Mail eingeben">
<input type="password" minlength="8" required>
<button>Login</button>
</form>
```
- `required`, `min`, `max`, `pattern`, `step`
- `:invalid` / `:valid` CSS-Pseudoklassen
- `form.checkValidity()` / `input.setCustomValidity()`
---
# Wann doch JS?
- Komplexe Interaktion über mehrere Komponenten
- State, der nicht ins DOM gehört
- Async / Server-Sync
- Animationen mit komplexer Logik
- Cross-Browser-Polyfills (selten heute)
**Default: HTML/CSS. JS nur wenn nötig.**
---
# Fragen?
1. Was bedeutet `div > p` vs `div p`?
2. Wann nutzt du `nth-child(even)`?
3. Warum `--variable` statt direkt `#fff`?