Zum Inhalt springen

CSS-Grundlagen

SAP Implementation Consulting & ERP - Startupistan Deutschland · Block I · Lernnotizen zur Wiederholung.


HTML baut die Struktur einer Seite auf - was jedes Element ist. Für sich allein sieht das schlicht und ungestaltet aus, und genau das ist HTML, das seine eine Aufgabe korrekt erfüllt, kein Zeichen dafür, dass etwas kaputt ist. CSS - Cascading Style Sheets - ist die zweite Sprache: Sie beschreibt, wie diese Struktur aussieht. Farben, Schriften, Größen, Abstände, Layout - all das steckt in CSS.

Zerlege den Namen in zwei Teile:

  • Style Sheets - Dateien voller Gestaltungsregeln, getrennt gehalten von den Inhalten, die sie gestalten.
  • Cascading - die Art, wie CSS Konflikte auflöst. Mehrere Regeln können dasselbe Element gleichzeitig anvisieren, und eine feste Reihenfolge entscheidet, welche gewinnt.

Eines gleich klarstellen: CSS ist keine Programmiersprache. Es gibt keine Schleifen, keine Entscheidungen, keine Logik - nur Deklarationen, die sagen „das soll so aussehen“, die der Browser dann anwendet. Genau deshalb ist es vom ersten Tag an zugänglich.


CSS kann eine Seite auf drei Wegen erreichen. Für echte Arbeit nutze ich einen davon, aber ich muss alle drei erkennen, weil sie mir in der Praxis begegnen.

WegWie es eingebunden wirdGeltungsbereichWofür man es nutzt
Inlinestyle-Attribut an einem Elementgenau dieses eine ElementHTML-E-Mails, schnelle Tests, werkzeuggenerierter Markup
Intern<style>-Block im <head>genau diese eine Seiteechte Einzeldatei-Seiten, kleine Demos
Externseparate .css-Datei, aus dem <head> verlinktjede Seite, die sie verlinktalles Echte - der Standard

Der externe Weg wird so verbunden, mit einem link-Element im Head - rel benennt die Beziehung (ein Stylesheet), href enthält die Adresse:

<link rel="stylesheet" href="styles.css">

Warum extern gewinnt, in drei konkreten Gründen:

  • Eine Datei gestaltet jede Seite. Ändere eine Farbe einmal, und sie ändert sich überall. Bei internen Styles bedeuten drei Seiten drei Kopien, die still auseinanderdriften.
  • Inhaltsdateien bleiben Inhalt. Das HTML bleibt lesbar für das, was es ist.
  • Browser cachen es. Ein wiederkehrender Besucher hat das Stylesheet bereits und lädt es nicht erneut herunter, wodurch Seiten schneller laden.

Alles in einem Stylesheet ist aus einer einzigen, sich wiederholenden Form gebaut. Ihre vier Teile haben genaue Namen, denn Dokumentation, DevTools und jede Fehlersuche verwenden diese Wörter.

body { /* selector - welche Elemente das anvisiert */
background-color: #faf5ee; /* declaration: property + value, endet mit ; */
color: #2f2a25; /* property = welcher Aspekt · value = die Einstellung */
} /* die geschweiften Klammern { } halten den Deklarationsblock */
  • Der Selektor (body) sagt, auf welche Elemente die Regel angewendet wird.
  • Der Deklarationsblock ist alles zwischen den geschweiften Klammern.
  • Jede Deklaration ist ein property: value;-Paar, mit einem Semikolon beendet.
  • Die Eigenschaft benennt, welcher Aspekt gestaltet werden soll; der Wert legt ihn fest.

Ein Selektor plus sein Deklarationsblock ist ein Ruleset. Ein Stylesheet ist einfach eine Stapelung von Rulesets, von oben nach unten.

Die zwei stillen Defekte. CSS meldet niemals Fehler an die Seite - es überspringt, was es nicht parsen kann, und macht weiter. Stille ist nicht dasselbe wie Korrektheit.

  • Fehlendes Semikolon - der Parser lässt die kaputte Zeile in die nächste Deklaration laufen und verwirft beide. Symptom: eine Gestaltung funktioniert, die nächste geheimnisvollerweise nicht. Das Erste, was man prüft: das Semikolon in der Zeile darüber.
  • Fehlende schließende geschweifte Klammer - bricht jedes Ruleset danach in der Datei. Symptom: alles unterhalb eines bestimmten Punktes stirbt auf einmal. Die Klammer-Einfärbung des Editors zeigt es sofort an, wenn ich hinschaue.

Der Selektor ist der Punkt, an dem ein Ruleset zielt. Diese fünf decken nahezu alles ab, und einer davon wird zum Arbeitspferd.

SelektorGeschrieben alsTrifft aufBeispiel
Elementbloßer Namejedes Element dieser Arth1 { color: #8a5a2e; }
Klasseführender Punktjedes Element, das diese Klasse trägt.tagline { color: #6b6257; }
IDführende Rautedas eine Element mit dieser ID (pro Seite eindeutig)#site-logo { ... }
Nachfahrezwei Selektoren, ein Leerzeichen dazwischenElemente innerhalb eines anderen Elementsnav a { ... } (Links innerhalb der nav)
Pseudo-KlasseDoppelpunkt + Zustandein Element in einem bestimmten Zustanda:hover { color: #8a5a2e; }

Die Klasse ist das Arbeitspferd. Beliebig viele Elemente können sich eine Klasse teilen, und ein Element kann mehrere tragen. Ich entscheide genau, welche Elemente zu einer Gestaltungsgruppe gehören, welcher Art sie auch sein mögen. Eine id visiert für immer genau ein Element an - das seltene, spezifische Werkzeug, falsch für alles, was jemals ein Geschwister haben könnte.

Zwei Kombinationstricks verdienen sich ihren Platz:

  • Gruppieren mit Kommas wendet einen Block auf mehrere Selektoren an - h1, h2 { color: #8a5a2e; } liest sich „für jedes h1 und jedes h2“.
  • Nachfahre (ein Leerzeichen) greift nach innen - nav a gestaltet nur Links innerhalb der nav und lässt einen Link in einem Absatz unberührt.

CSS akzeptiert eine Farbe in mehreren Schreibweisen. Drei sind jetzt wichtig, eine wird kurz erwähnt:

SchreibweiseSieht aus wieHinweis
Benanntgreen, white~140 Namen; praktisch beim Experimentieren, zu grob für echte Paletten
Hex#faf5eeDas Arbeitspferd. #RRGGBB - je zwei Hex-Ziffern für Rot, Grün, Blau, 00-FF. Jede Markenpalette kommt so an
rgb()rgb(6, 48, 42)dieselben drei Kanäle in Dezimal
hsl()hsl(174, 78%, 11%)Farbton, Sättigung, Helligkeit; Designer mögen es zum Nachdenken über Farbe - erkennen

Zwei Eigenschaften erledigen das Einfärben: color setzt die Textfarbe, background-color setzt die Füllung hinter einem Element. Setze beide auf body, und die Textfarbe vererbt sich hinab auf jeden Absatz, jede Liste und jede Überschrift, bis eine spezifischere Regel sie überschreibt.

body {
background-color: #faf5ee; /* warmes Creme */
color: #2f2a25; /* dunkles, warmes Braun, überall vererbt */
}

Untersuchen & experimentieren Weil CSS still versagt, ist der Inspektor des Browsers der beste Freund eines Anfängers, kein Werkzeug nur für Experten. Rechtsklick auf ein beliebiges Element auf einer beliebigen Seite und Untersuchen wählen. Chrome öffnet die DevTools mit dem Elemente-Panel (dem lebenden Elementbaum) und dem Styles-Bereich daneben - der jedes zutreffende Ruleset zeigt, aus welcher Datei es stammt und seine Zeilennummer.

Was es mir gibt:

  • Die Kaskade lesen - Regeln werden am spezifischsten zuerst aufgelistet; durchgestrichene Deklarationen haben die Kaskade verloren, sodass „warum greift mein Style nicht?“ zu einer Leseübung statt zu einem Rätsel wird.
  • Live-Bearbeitung - klicke auf einen beliebigen Wert und tippe einen neuen; die Seite aktualisiert sich sofort. Klicke auf ein Farbfeld, und die Farbauswahl zeigt sogar das Kontrastverhältnis gegen den Hintergrund, mit markierter 4,5:1-Linie.
  • Drei Diagnosen in einem Bereich - eine völlig ungestaltete Seite bedeutet, dass das Stylesheet nicht verlinkt ist (meist ein Tippfehler im href); ein Ruleset, das nie erscheint, bedeutet, dass der Selektor auf nichts passt (ein Klassen-Tippfehler); ein Warnsymbol markiert eine Deklaration, die ein fehlendes Semikolon verschluckt hat.

Der Großteil des Webs ist Text, was Typografie hier zur Designfähigkeit mit der höchsten Hebelwirkung macht. Es beginnt mit zwei Wörtern, die Laien verwischen und Profis nicht:

  • Eine Schriftart (typeface) ist der Entwurf - die ganze Familie von Buchstabenformen mit einem Namen (Playfair Display, Lato).
  • Ein Font ist ein konkreter Schnitt dieser Schriftart - ein Gewicht, eine Haltung (Playfair Display Bold; Lato Regular Italic).

Die Schriftart ist die Familie; jeder Font ist ein Mitglied. CSS stimmt zu - die Eigenschaft ist font-family: Ich benenne die Familie, der Browser wählt das Mitglied, das jede Situation braucht.

Zwei Regeln bringen mich weit: Lesbarkeit zuerst für den Fließtext (er muss im mühelosen Lesen verschwinden), Charakter für die Überschriften und die Marke (in einzelnen Zeilen gelesen, dürfen sie sich eine unverwechselbare Stimme leisten); und höchstens zwei Schriftarten - eine mit Charakter für die Auszeichnung, eine ruhige Arbeitskraft für alles andere. Mehr als zwei liest sich als Chaos.

Besucher haben meine gewählte Schriftart nicht installiert, und sie müssen es auch nicht - die Seite kann ihre eigenen Web-Fonts mitbringen. Dieser Kurs lädt sie von Google Fonts (kostenlos, offene Lizenz, Copy-and-paste-Integration; erwähnenswerte Alternativen existieren - Adobe Fonts oder das Selbst-Hosten der Dateien). Wähle die Schriftart, wähle die benötigten Gewichte (z. B. 400 regular und 700 bold) und füge die link-Elemente in den Head jeder Seite ein, oberhalb des Links zu meinem eigenen Stylesheet:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">

Dann benenne die Familie in CSS, immer mit einer generischen Familie als Sicherheitsnetz am Ende:

body {
font-family: "Lato", sans-serif; /* mehrwortige Namen in Anführungszeichen; ende mit serif / sans-serif / monospace */
}

Lesbare Seiten sind kein Glück - sie sind eine Hierarchie: Größen, Gewichte und Abstände so gewählt, dass ein Blick schon sagt, was ein Titel, ein Abschnitt und einfacher Text ist. Fünf Eigenschaften bauen eine:

EigenschaftSetztGute Praxis
font-sizewie groß Text gerendert wirdwähle aus einer kleinen Skala (z. B. body 1.6rem, h2 2.4rem, h1 3.6rem), keine willkürlichen Werte
font-weightStrichstärke400 (normal) und 700 (bold) - passend zu den von Google Fonts geladenen Gewichten
font-styleaufrecht oder italicdie „Kostüm“-Seite der Betonung - nur Aussehen, keine Bedeutung
line-heightAbstand zwischen Zeilenschreibe ihn einheitslos (1.6), damit er mit jeder Schriftgröße mitskaliert; 1,5-1,6 für Fließtext
text-alignleft · center · rightlanger Text bleibt links; center nur für kurze Auszeichnungszeilen

Die Einheit, die ich für Text wähle, ist im Stillen eine Entscheidung über Barrierefreiheit.

EinheitTypRelativ zuGreif danach, wenn
pxabsolutnichts - festRahmen, winzige feste Details; für Textgröße meiden
remrelativder Wurzel-Schriftgröße (html)der Standard für Text & Abstände - kein Aufsummieren, skaliert mit der Einstellung des Besuchers
emrelativder Schriftgröße des aktuellen Elementsselten - es summiert sich auf und wird schwer kontrollierbar
%relativdem Wert des Elternelementsfluide Breiten und der 62,5%-Wurzeltrick
vw / vhrelativ1% der Viewport-Breite / -Höhevollflächige Heroes, viewport-große Blöcke

Warum rem die barrierefreie Wahl ist: Jeder Browser lässt den Nutzer eine bevorzugte Standard-Schriftgröße einstellen - ein sehbeeinträchtigter Besucher stellt vielleicht 20px ein. Größen in rem skalieren mit dieser Wurzel, sodass die ganze Website die Wahl respektiert. Größen in px ignorieren sie schlicht.


Jedes Element, das der Browser rendert, ist ein Rechteck aus vier Schichten, von innen nach außen. Das ist das mit Abstand wichtigste Denkmodell, um irgendetwas mit Abständen zu versehen.

contentder Text oder das Bild selbst
→
paddingRaum innen, vor dem Rahmen
→
borderdie gezeichnete Kante
→
marginRaum außen, zur nächsten Box
Content → padding → border → margin, von innen nach außen. Jedes Element trägt alle vier.
.card {
padding: 1.6rem; /* Raum innen in der Box */
border: 1px solid #e3d9c9; /* die gezeichnete Kante */
margin: 2rem; /* Raum außen, zwischen Nachbarn */
}

Ein Wert setzt alle vier Seiten; zwei Werte setzen vertikal dann horizontal (padding: 1.2rem 2rem; = oben/unten dann links/rechts).

Bevor ich eine einzige width schreibe, braucht eine Frage eine feste Antwort: Wenn ich width: 300px sage, was genau ist 300px breit?

  • content-box (der Browser-Standard) - die Breite misst nur den Content. Padding und border werden obendrauf addiert, sodass eine 300px-Karte mit 20px padding und einem 2px border tatsächlich 344px breit rendert. Jede Padding-Änderung ändert die Größe des Elements, und Layouts brauchen für immer Rechnerei.
  • border-box - die Breite misst die sichtbare Box (content + padding + border zusammen). Dieselbe Karte rendert exakt 300px; der Content schrumpft, um innen Platz zu machen. Was ich sage, ist, was ich bekomme.

Die professionelle Lösung, eine Regel ganz oben im Stylesheet mit * (dem Universalselektor, der auf jedes Element passt):

* {
box-sizing: border-box; /* width bedeutet jetzt die sichtbare Box, überall - keine Rechnerei */
}

Größen-Begleiter: width setzt sie, max-width deckelt sie (die Box bleibt fluide, wächst aber nie über den Deckel hinaus - das Arbeitspferd), und height bleibt bei Text meist ungesetzt, weil der Content über seine eigene Höhe entscheiden soll. Der klassische zentrierte Container:

.container {
max-width: 96rem; /* die Zeilenlänge auf ein lesbares Maß deckeln */
margin: 0 auto; /* auto links+rechts teilt den Restraum gleich auf = zentriert */
padding: 0 2rem; /* Content bei schmalen Fenstern von den Bildschirmkanten fernhalten */
}

display legt fest, welches Layout-Verhalten eine Box verwendet. Die Standards, die ich bereits kenne, sind ihre Werte:

WertVerhalten
blockeigene Zeile, volle verfügbare Breite - Überschriften, Absätze, Listen, div
inlinefließt innerhalb von Text, nimmt nur seinen eigenen Platz, ignoriert width/height und vertikales padding - ein span kann nicht wie eine Box dimensioniert werden
inline-blockder Mittelweg - fließt in einer Zeile und akzeptiert width, height, padding
nonevollständig von der Seite entfernt - nimmt gar keinen Platz ein
flexmacht das Element zu einem Flex-Container - die Tür zum Layout

Flexbox ordnet Boxen entlang einer Linie an. Setze display: flex auf einen Container, und seine direkten Kinder werden zu Flex-Items, die gehorchen. Items reihen sich entlang der Hauptachse (main axis) auf; die sie kreuzende Richtung ist die Querachse (cross axis). Fast alles wird auf dem Container gesetzt - die Items folgen einfach.

  1. Erstelle den Container. display: flex auf dem Elternelement. Seine direkten Kinder sind nun Flex-Items.

  2. Setze die Hauptachse mit flex-direction - row (Standard, horizontal) oder column (vertikal). Jede andere Eigenschaft folgt dieser Wahl.

  3. Platziere entlang der Hauptachse mit justify-content - flex-start (Standard), center oder space-between (erstes Item an einem Ende, letztes am anderen).

  4. Richte auf der Querachse aus mit align-items - center (der ständige Griff), flex-start oder stretch (Standard, gleiche Höhen).

  5. Abstand und Umbruch mit gap (fester Raum zwischen Items - keine margin-Tricks) und flex-wrap: wrap (lässt eine überfüllte Zeile auf eine zweite umbrechen).

Hier ein vollständiges, direkt einfügbares Beispiel - eine Kopfleiste (Marke nach links geschoben, Links nach rechts geschoben) plus eine umbrechende Reihe von Karten:

<header class="header-bar">
<span class="brand">Café Aroma</span>
<nav>
<a href="#">Menu</a>
<a href="#">About</a>
<a href="#">Visit</a>
</nav>
</header>
<section class="card-row">
<article class="card">
<h3>Morning Bun</h3>
<p class="price">3.50</p>
</article>
<article class="card">
<h3>Rye Loaf</h3>
<p class="price">4.20</p>
</article>
<article class="card">
<h3>Almond Tart</h3>
<p class="price">3.90</p>
</article>
</section>
* { box-sizing: border-box; }
/* header: zwei Enden auseinandergeschoben, alles auf einer Mittellinie */
.header-bar {
display: flex;
justify-content: space-between; /* Marke links, nav rechts */
align-items: center; /* gleiche visuelle Mittellinie */
padding: 1.2rem 2rem;
background-color: #2f2a25;
color: #faf5ee;
}
/* die nav ist ihr eigener Flex-Container für gleichmäßig verteilte Links */
nav {
display: flex;
gap: 2.4rem;
}
nav a { color: #faf5ee; text-decoration: none; }
/* Kartenreihe: bricht auf eine neue Zeile um, wenn der Platz ausgeht */
.card-row {
display: flex;
flex-wrap: wrap;
gap: 2.4rem;
}
.card {
background-color: #ffffff;
border: 1px solid #e3d9c9;
padding: 1.6rem;
max-width: 28rem;
}

KernpunktKurz gemerkt
CSSCascading Style Sheets - beschreibt, wie HTML aussieht; keine Programmiersprache
Drei Wege zum Einbindeninline, intern, extern - extern gewinnt (eine Datei, sauberer Inhalt, gecacht)
Rulesetselector { property: value; } - ein fehlendes ; oder } versagt still
Selektorenelement / class (Arbeitspferd) / id / Nachfahre (Leerzeichen) / Pseudo-Klasse; Klassen nach Rolle benennen
Farbehex #RRGGBB ist das Arbeitspferd; color + background-color; jede Paarung ≥ 4,5:1 Kontrast
Schriftart vs. FontSchriftart = die Familie; Font = ein Gewicht/Stil davon → font-family, endend mit einer generischen Familie
Web-Fontsvon Google Fonts in den Head jeder Seite laden; die Fallback-Liste ist das Sicherheitsnetz
SchrifthierarchieGrößen aus einer Skala wählen; einheitslose line-height ~1,6; langer Text bleibt linksbündig
Einheitenrem für Text/Abstände (barrierefrei, skaliert); px fest; der 62,5%-Wurzeltrick macht 1rem = 10px
Box-Modellcontent → padding → border → margin; Hintergrund hört am border auf, margin ist transparent
box-sizing* { box-sizing: border-box; } ganz oben, damit width = die sichtbare Box
displayblock / inline / inline-block / none / flex (regiert die Kinder)
Flexboxdisplay:flex auf dem Container; flex-direction · justify-content · align-items · gap · flex-wrap
DevToolsRechtsklick → Untersuchen; die Kaskade lesen, live experimentieren, dann Gewinner ins Stylesheet kopieren