Files
uni/slides/dhbw/02_css_extended.md

7.8 KiB
Raw Permalink Blame History

marp, theme, paginate, backgroundColor, header, footer
marp theme paginate backgroundColor header footer
true gaia true Web Engineering DHBW Stuttgart 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>

CSS: Extended


CSS Selectors Tag, Class, ID, Attribute

/* 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

/* 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

/* 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

/* 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

/* 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

/* 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

/* 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)

:root {
  --primary-color: #005f8a;
  --spacing: 20px;
  --radius: 8px;
}

.button {
  background: var(--primary-color);
  padding: var(--spacing);
  border-radius: var(--radius);
}

CSS Functions

/* 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

/* 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
#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

<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

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>

<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

<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.

<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

<progress value="70" max="100">70%</progress>

<!-- indeterminate -->
<progress></progress>
progress {
  width: 100%;
  height: 0.5rem;
}
progress::-webkit-progress-bar { background: #eee; }
progress::-webkit-progress-value { background: #005f8a; }

Form Validation Native

<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?