Trennung von Darstellung und Inhalt

Anliegen
Abweichung / Unabhängigkeit von der “gewöhnlichen” Darstellung im Browser
  • Position
  • Ausrichtung
  • Umrahmung
  • Farbe
Probleme
  • Konsistenz der Darstellungsweise für viele HTML-Dateien eines Web-Auftritts
  • Faustregel: Je besser das Dokument semantisch ausgezeichnet ist, desto einfacher ist die konsistente optische Anpassung
  • Flexible, konsistente Veränderung der Darstellungsweise bei überschaubarem Aufwand auch für größere Seitenanzahl
Lösung
Separate Stylesheets zur Beschreibung der Darstellung
Sehr andere Anforderungen als Print-Medien
Unterschiedlichste Auflösungen, Seitenverhältnisse, …

Der Vollständigkeit halber: Optische Anpassungen ohne Stylesheets

  • intro_css/style.html | Validieren
    <html>
      <head>
        <title>Eingebettetes Stylesheet</title>
      </head>
      <body>
        <h1 style="color: red;">Hello direct Style</h1>
      </body>
    </html>
    

Stylesheets

Einbettung von Stylesheets im Dokument

  • intro_css/embed.html | Validieren
    <html>
      <head>
        <title>Eingebettetes Stylesheet</title>
        <style type="text/css">
         h1 {
             color: red;
         }
        </style>
      </head>
      <body>
        <h1>Hello embedded Style</h1>
      </body>
    </html>
    

Verweis auf Stylesheets im Dokument

Bevorzugt: Verweise auf Stylesheets

Erlaubt die Verwendung der gleichen CSS-Anweisungen in verschiedenen Dokumenten
Klare Trennung von Darstellung und Inhalt auch auf Datei-Ebene
Viele unterschiedliche Möglichkeiten zur Steuerung der Einbindung
Einbindung immer im <head>, aber auf Basis welcher Daten?
Statisch: Einfache Angabe eines <link>-Elements im Wurzel-Template
Nicht sehr flexibel
Daten: Angabe von zu verwendenden Stylesheets als JSON-Liste
In der globalen Konfiguration oder dem Template-Frontmatter
Mehrstufig: Zusätzliche Angabe von Stylesheets für bestimmte Seiten
Aufteilung in eine Menge von “Grundregeln” und zusätzliche spezifische Regeln (basierend auf dem Typ der Seite)

Cascading Stylesheets (CSS)

Aufbau eines CSS-Dokuments
Menge von Darstellungsregeln
Definition einer Regel
  • Besteht aus Selektor und Deklaration
  • Der Selektor bestimmt den Wirkungsbereich der Deklaration
  • Die Deklaration ordnet Eigenschaften spezifische Werte zu
Vereinfachter Aufbau
<ruleset>     ::= { <rule> }
<rule>        ::= <selector> '{' { <declaration> } '}'
<declaration> ::= <property> ':' <expr>;

Selektorarten

Universeller Selektor (*)
Selektiert jedes verfügbare Element
Typ-Selektoren
Selektiert alle Elemente eines bestimmten Typs
Nachfahren-, Kind- und Nachbar-Selektoren
Selektiert anhand der Position im DOM-Baum
Attribut-Selektoren
Selektiert Elemente mit bestimmten Attributen
ID-Selektoren
Selektiert anhand einer eindeutigen ID
Externe Selektoren (Pseudo-Klassen und Pseudo-Elemente)
Schränkt die Selektion aufgrund von Zuständen ein, die möglicherweise nichts mit dem DOM zu tun haben

Universeller Selektor

  • Selektor: *
    %3 node_0 body node_1 p node_0->node_1 node_2 ul node_0->node_2 node_3 li node_2->node_3 node_5 li node_2->node_5 node_4 p node_3->node_4

Typ-Selektoren

Direkte Angabe
Das zu formatierende HTML-Element wird unmittelbar angegeben
  • Selektor: p
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 time node_2->node_3 node_4 em node_2->node_4

Nachfahren-Selektoren

Pfadangabe mit Leerzeichen
Jeweils links stehende Selektoren beschreiben den Kontext, in dem rechts stehende Selektoren auftreten müssen, damit die Regel anwendbar ist
  • Selektor: ul li
    %3 node_0 body node_1 ul node_0->node_1 node_4 ol node_0->node_4 node_2 li node_1->node_2 node_3 li node_1->node_3 node_5 li node_4->node_5 node_6 li node_4->node_6

Kind-Selektoren

Pfadangabe mit >
Selektion von Elementen, die unmittelbar auf der nächsten Baumebene enthalten sind
  • Selektor: body > p
    %3 node_0 body node_1 p node_0->node_1 node_2 ul node_0->node_2 node_3 li node_2->node_3 node_5 li node_2->node_5 node_4 p node_3->node_4

Nachfahren-Selektor und Kind-Selektor im Vergleich

Typisches Problem: Selektion von allgemeinen Elementen weiter unten im Baum
Je allgemeiner das zu selektierende Kind-Element, desto wahrscheinlicher ist eine spätere Kollision
  • Selektor: ul li
    %3 node_0 body node_1 ul node_0->node_1 node_2 li node_1->node_2 node_3 li node_1->node_3 node_4 ol node_3->node_4 node_5 li node_4->node_5 node_6 li node_4->node_6
  • Selektor: ul > li
    %3 node_0 body node_1 ul node_0->node_1 node_2 li node_1->node_2 node_3 li node_1->node_3 node_4 ol node_3->node_4 node_5 li node_4->node_5 node_6 li node_4->node_6

Direkter Geschwisterselektor

Pfadangabe mit +
Selektion von einem Element, das unmittelbar auf das vorherige Element folgt
  • Selektor: dt + *
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6

Allgemeiner Geschwisterselektor

Pfadangabe mit ~
Selektion von allen Elementen, die unmittelbar auf das vorherige Element folgen
  • Selektor: dt ~ *
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6

Geschwisterselektoren im Vergleich

  • Selektor: h1 + dl
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6
  • Selektor: h1 ~ dl
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6
  • Selektor: dt + dd
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6
  • Selektor: dt ~ dd
    %3 node_0 body node_1 h1 node_0->node_1 node_2 p node_0->node_2 node_3 dl node_0->node_3 node_4 dt node_3->node_4 node_5 dd node_3->node_5 node_6 dd node_3->node_6

Attribut-Selektoren

Angabe von Schlüssel-Wert-Paaren mit [name="wert"]
Erlauben Selektion von Elementen in Abhängigkeit von Attributwerten
[name]
Selektiert Elemente, für die ein beliebiger Wert im Attribut name angegeben ist
[name="wert"]
Selektiert Elemente, für die ein exakt passender wert angegeben ist
[name~="wert"]
Selektiert Elemente, bei denen in der Leerzeichen-separierten Liste an Attributwerten exakt wert vorkommt.
[name^="wert"] oder [name$="wert"]
Selektiert Elemente, bei denen wert entweder ein Präfix (^) oder ein Suffix ($) des konkreten Attributes ist.
  • intro_css/attribute-selector.html | Validieren
    <ul>
      <li><a href="http://www.fh-wedel.de">Ein Link zur FH Wedel</a></li>
      <li><a href="https://www.tuhh.de/">Kein Link zur FH Wedel</a></li>
      <li>Eine wichtige Abkürzung: <abbr title="Wichtig">DVA</abbr></li>
    </ul>
    
  • intro_css/attribute-selector.css
    a { color: red; }
    [href="http://www.fh-wedel.de"] { color: green; }
    [title="Wichtig"]               { color: blue; }
    

Das class-Attribut und der .-Selektor

.<klassenname> statt [class~="<klassenname>"]
Abkürzung für den Zugriff auf darstellungsbezogene Klassen
Wird häufig direkt zusammmen mit dem Element notiert: <element>.<klassenname>
Vorsicht, wenn ein Leerzeichen dazwischen rutscht ändert sich die Bedeutung
  • intro_css/class-selector.html | Validieren
    <div class="card artifact" id="black-lotus">
      <h1>Black Lotus <span class="mana">0</span></h1>
      <img src="/assets/photos/black-lotus.jpg"
           alt="black-lotus">
      <p class="rules">
        Adds <span class="mana">3</span> mana of any
        single colour of your choice to your mana pool,
        then is discarded. <span class="tap">Tapping</span>
        this artifact can be played as an
        <span class="interrupt">interrupt</span>.
      </p>
    </div>
    
  • intro_css/class-selector.css
    .card {
        background-color: lightgray;
    }
    
    .card .tap, .card .interrupt {
        background-color: yellow;
    }
    
    .card .tap       { color: red; }
    .card .mana      { color: blue; }
    .card .interrupt { color: green; }
    
Frage:

Was ändert sich, wenn in dem Beispiel statt des Nachfahren-Selektors ein Kind-Selektor verwendet wird?

Antwort:

Da zwischen .card und den jeweiligen anderen Klassen noch p- bzw. h1-Elemente im Weg sind, werden nun keine Elemente mehr selektiert.

ID-Attribut und der #-Selektor

Selektion von einzigartigen Elementen mit #id
Bezeichner id muss einzigartig sein

Pseudo-Klassen

Erlauben Einschränkungen auf Basis von Nicht-Attribut-Eigenschaften
Entsprechende Merkmale finden sich nicht unmittelbar im Quelltext
Syntax: :<pseudoklasse>, typischerweise in Kombination mit einem weiteren Selektor
Schränkt den vorherigen Selektor weiter ein

Beispiel: hover

Selektiert alle Elemente, über denen sich die Maus befindet
Gilt auch für Elternelemente, hover gilt ausgehend vom speziellsten Kind bis zur Wurzel

Beispiel: visited

Selektiert Links, sofern Sie schon vom Anwender besucht worden sind
Erlaubt aus Datenschutzgründen nur farbliche Anpassungen

Beispiel: target

Selektiert Elemente, deren id zum aktuellen Fragment der Browser-URL passt
Erlaubt Interaktion mit Links ohne JavaScript
  • intro_css/pseudo-class-target.css
    p:target {
        background-color: yellow;
    }
    
  • intro_css/pseudo-class-target.html | Validieren
    <ul>
      <li><a href="#blue">Blue</a></li>
      <li><a href="#red">Red</a></li>
      <li><a href="#indigo">Indigo</a></li>
      <li><a href="#gold">Gold</a></li>
      <li><a href="#silver">Silver</a></li>
      <li><a href="#pink">Pink</a></li>
    </ul>
    
    <p id="blue">
      Blue Tide - the Tide linked to reason, wisdom, enlightenment, and
      mysticism. People influenced by this tide seek to expand their
      consciousness and spirit forces, acquire great knowledge, and have
      an in-depth insight about the world around them.
    </p>
    
    <p id="red">
      Red Tide - represents passion, emotion, action, pathos, and zeal.
      It's a path for people who want to live their life to the fullest,
      and base their worldview on their own feelings. Such characters
      always strive to be free, and follow the voice of their hearts. 
    </p>
    
    {{ page.remaining_tides }}
    

Pseudo-Klassen zur DOM-Navigation

Sinnvoll benannte Klassen zur Navigation im DOM, teilweise parametrisiert
  • first-child, last-child bzw nth-child(x) um nur einen bestimmten Kind-Treffer zu selektieren
  • first-of-type, last-of-type bzw nth-of-type(x) um nur bestimmte Kind-Treffer eines bestimmten Selektors zu selektieren
Zählung von Treffern beginnt mit dem Index 1!

Pseudo-Elemente

::first-letter und ::first-line: Schränken den Treffer gemäß dem Textfluss ein
Je nach Zeichensatz können hier eine Vielzahl spezifischer Regeln zum Einsatz kommen
  • Interpunktion und kombinierte Glyphen werden typischerweise nicht gezählt
::before und ::after: Ergänzen den DOM-Baum um weitere Elemente
Typischerweise in Verbindung mit dem content-Wert um einen Text anzugeben

Auflösung von in Konflikt stehenden Selektoren

Problematisch: Unterschiedliche Wertzuweisungen für die gleichen Schlüssel
Unproblematisch: Zuweisungen für unterschiedliche Schlüssel, auch über mehrere Regeln hinweg.

Verfahren: Bestimmung der Spezifität

Grundgedanke: Die speziellste Nennung gewinnt
Jeder zutreffenden Zuweisung wird ein Punktwert gemäß des Selektors zugeordnet
Bewertung einzelner Selektortypen
  1. Typ-Selektoren (p) oder Pseudo-Elemente (::before)
  2. Klassenselektoren (.beispiel), Attribut-Selektoren ([href="/"]) und Pseudo-Klassen (:hover)
  3. ID-Selektoren (#beispiel)
Algorithmus zur Bestimmung des spezifischsten Selektors
  1. Jeden vorkommenden Selektor gemäß seiner Bewertung zählen
  2. Die Regel mit der höchsten gefüllten Kategorie gewinnt
  3. Bei Gleichstand: Vergleich der geringeren Kategorien
  4. Bei Gleichstand: Zuletzt genannte Regel gewinnt

Beispiel zur Spezifität

  • intro_css/specifity.html | Validieren
    <dl class="desc">
      <dt class="term">Muggel</dt>
      <dd class="definition">
        <p class="text" id="no-wizard">Ein Muggel ist ein Mensch ohne magische Begabung,
          der nicht in der Welt der Zauberer und Hexen geboren wurde.</p>
      </dd>
    </dl>
    
  • intro_css/specifity.css
    dl dd p                 { color: red; }
    .desc .definition .text { color: yellow; }
    #no-wizard              { color: blue; }
    dl #no-wizard           { color: green; }
    .definition #no-wizard  { color: fuchsia; }
    
Regel 1 2 3
dl dd p 3 0 0
.desc .definition .text 0 3 0
#no-wizard 0 0 1
dl #no-wizard 1 0 1
.definition #no-wizard 0 1 1

Typisches Problem: Selektion spezifischer Tiefen

Lässt sich nicht mit Angabe eines “Tiefenselektors” o.ä. lösen
Abhilfe durch Schachtelung von Kind-Selektoren
  • Selektor: ul > li
    %3 node_0 body node_1 ul node_0->node_1 node_2 li node_1->node_2 node_3 ul node_2->node_3 node_4 li node_3->node_4
  • Selektor: ul > li > ul > li
    %3 node_0 body node_1 ul node_0->node_1 node_2 li node_1->node_2 node_3 ul node_2->node_3 node_4 li node_3->node_4

Styling-Angaben

Bis hier: Welche Elemente sollen optisch angepasst werden
Beispielhafte Änderungen von Farben
Ab hier: Wie sollen diese Elemente optisch angepasst werden
Farbe, Layout, Textstil, …
Häufig verwendete Werte
  • Farben
  • Längen
  • Häufig ebenfalls möglich: Prozentangaben, deren Bedeutung ergibt sich aus dem Kontext
  • Unterschiedlichste Aufzählungen
    • Textstile
    • Positionsangaben

Farbangaben

Typische Eigenschaften:
  • color für die Farbe des Vordergrunds
  • background-color für die Farbe des Hintergrunds
Schlüsselwörter
Angabe eines Wertes aus einer Farbaufzählung: black, blue, yellow, …
RGB-Farbmodell
Angabe der Farbkanäle rot, grün und blau. Die folgenden Anweisungen kodieren alle die gleich Farbe:
  • Sechs hexadezimale Ziffern: #FF0033 oder #ff0033
  • Funktionale Schreibweise mit Dezimalzahlen: rgb(255, 0, 51)
  • Funktionale Schreibweise mit Prozentwerten: rgb(100%, 0%, 20%)
HSL-Farbmodell
Angabe von hue (Farbwinkel), saturation (Farbsättigung) und lightness (Helligkeit).
  • Funktionale Schreibweise: hsl(0, 100%, 50%)
Farben werden nicht im Quelltext aufeinander abgestimmt! Nutzen Sie online existierende "Colour Picker" oder Tools für Farbpaletten (wie paletton.com).

Längenangaben

Schema: Zahl mit Einheit
Standardmaß sind Pixel

Absolute Längenangaben

Pixel (px)
  • Näherung: Die kleinste darstellbare Einheit eines Monitors.
  • Realität: Ein Winkelmaß (mehr dazu im Teil “Responsive Design”)
Millimeter (mm), Zentimeter (cm), Zoll (in)
“Typische” Längenangaben mit den bekannten Einheiten.
Skalierung
Die Pixeldichte hängt vom ausgebenden Endgerät ab. Auf Geräten mit hoher Pixeldichte (Smartphones, Drucker, UHD-Monitore) werden die Angaben so skaliert, dass etwa 96 DPI dabei herauskommen.

Relative Längenangaben

Grundidee: Größe eines Pixels (oder einer anderen absoluten Angabe) eignet sich nicht gut zur relativen Skalierung
Viele explizite Angaben notwendig um Angaben wie “doppelt so groß” umzusetzen.
Daher: Kein expliziter Bezug zu absoluten Angaben, sondern zur Schriftgröße
Erlaubt wesentlich bessere Skalierung als bei der Verwendung von Pixelangaben.
em & ex: Größenangaben die sich auf die aktuell genutzten Font beziehen
  • Ursprüngliche Bedeutung: Breite des Buchstabens “m” bzw. Höhe des Buchstabens “x”
  • Heute: Abstraktere Definition, nicht jedes Alphabet kennt ein “m” oder “x”
em
Relativ zur font-size des Elementes. Falls ein em-Wert zur Angabe des font-size-Attributes genutzt werden soll, wird der ererbte Wert modifiziert.
rem
Relativ zur font-size des Wurzelements. Wenn dieses Attribut an der Wurzel (<html>) genutzt wird, wird damit der Wert festgelegt.
  • intro_css/lengths-rel.html | Validieren
    <h1>Primal</h1>
    <h2>Druid</h2>
    <h3>Circle of the Moon</h3>
    <h3>Circle of the Unspeakable</h3>
    <h2>Barbarian</h2>
    <h3>Path of the Colossus</h3>
    <h3>Path of the Wolfsblood</h3>
    
  • intro_css/lengths-rel.css
    html { font-size: 12px; }
    h1   { font-size: 3rem; }
    h2   { font-size: 2rem; }
    h3   { font-size: 1rem; }
    

Viewport-Längenangaben

vh und vw
Höhe und Breite bezogen auf die Größe des “Fensters”

Texteigenschaften

text-align: Ausrichtung des Textes
left, right, center, justify (Blocksatz)
hyphens: Automatische Silbentrennung
  • none (Standard) oder auto
  • Außerdem notwending: Angabe einer Sprache mit dem Attribut lang
text-transform: Beinflussung der Groß- und Kleinschreibung
  • capitalize: Erster Buchstabe eines Wortes groß
  • uppercase: Alle Buchstaben groß
  • lowercase: Alle Buchstaben klein
  • intro_css/text.html | Validieren
    <p lang="de">
      Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte,
      fand er sich in seinem Bett zu einem ungeheueren Ungeziefer
      verwandelt. Er lag auf seinem panzerartig harten Rücken und
      sah, wenn er den Kopf ein wenig hob, seinen gewölbten, braunen,
      von bogenförmigen Versteifungen geteilten Bauch, auf dessen Höhe
      sich die Bettdecke, zum gänzlichen Niedergleiten bereit, kaum
      noch erhalten konnte. Seine vielen, im Vergleich zu seinem
      sonstigen Umfang kläglich dünnen Beine flimmerten ihm hilflos
      vor den Augen.
    </p>
  • intro_css/text.css
    p {
        text-align: justify;
        hyphens: auto;
    }
    
    

CSS Box Model

Grundsätzlich: Aufteilung inline- und block-Elemente
Definiert grundlegende Maße, Abstände und Regeln zur Anordnung
Block-Elemente sind Rechtecke (div, p, ul, h1, …)
Position mit (x,y)-Koordinaten sowie Breite und Höhe
Inline-Elemente sind z.B. Textflüsse (span, em, q, …)
Beginnen an einer Position, sind möglicherweise aber konkav

Größe und Abstände

Quelle: Dudley Storey, thenewcode.com
Zulässiger Wertebereich:
  • Längen
  • Prozentwerte
  • auto is replaced by some suitable value, e.g. it can be used for centering of blocks.” (s. MDN).
Endgültige im Layout verwendete Größe ergibt sich aus der Summe aller Werte auf einer Achse
Tatsächliche Layout-Berechnung erfolgt immer in Pixeln
Prozentangaben bei width-Angaben: Unproblematisch
Bezieht sich dann auf die berechnete Breite des Elternelements
Prozentangaben bei height-Angaben: Problematisch
  • Grund”problem”: Browser geht davon aus, dass der Inhalt vertikal gescrollt werden muss
  • Funktioniert nur erwartungskonform bei Elementen deren Eltern eine absolute Höhe haben
    • Beliebter Fehler: Das body-Element hat keine absolute Höhe
    • Häufige Lösung: Nutzung der absoluten vh-Angabe

Beispiele für Auswirkung von padding und margin

  • intro_css/box-margin.html | Validieren
    <div class="first">First</div>
    <div class="second">Second</div>
    <div class="third">Third</div>
    
  • intro_css/box-margin.css
    .first {
        margin: 2em;
        background-color: red;
    }
    .second {
        margin: 1em;
        padding: 1em;
        background-color: blue;
    }
    .third {
        padding: 2em;
        background-color: green;
    }
    

Assymetrische Werte padding und margin

Notation von Abständen

Notation der einzelnen Abstände
  • Individuelle Angabe der Seite mit left, right, top und bottom
  • Kurzschreibweise, Belegung abhängig von der Anzahl der Werte:
    1. margin-or-padding: <x> Identischer Wert für alle Seiten
    2. margin-or-padding: <vert>, <horz> Vertikaler Abstand, dann horizontaler Abstand
    3. margin-or-padding: <up>, <horz>, <down>
    4. margin-or-padding: <up>, <right>, <down>, <left>

Beispiele für horizontale Zentrierung mit Abständen

Zentrierung von Elementen fester Breite mit margin: auto;
Ohne die Angabe einer Breite errechnet auto den Wert 0.
Dieser Ansatz funktioniert nur für die horizontale Zentrierung! Verwenden Sie für zentrierte Layouts im allgemeinen Fall lieber die später vorgestellten Flexboxen.

Box-Modell und benötigter Platz im Layout

Beanspruchte Länge oder Breite ist die Summe der Werte der jeweiligen Achse
Angaben müssen ggfs. mit 2 multipliziert werden, wenn sie auf beiden Seiten genutzt werden.
Wenn keine explizite Breite oder Höhe angegeben ist: Kind-Elemente bestimmen Dimensionen
Jedes Element wird so klein wie nur irgend möglich gezeichnet
Wenn der Platz nicht ausreicht: Inhalt ragt aus dem Element hinaus
Passiert nur wenn Breite und Höhe fest definiert werden
  • intro_css/box-model-size-layout.html | Validieren
    <div id="ex1">
      width: 100px + 2 * 2px + 2 * 3px + 2 * 10px
    </div>
    
    <div id="ex2">
      width: 40px + 10px + 2px + 4px
    </div>
    
  • intro_css/box-model-size-layout.css
    div {
        background-color: yellow;
    }
    
    #ex1 {
        margin: 10px;
        padding: 2px;
        border: 3px solid black;
        width: 100px;
    }
    
    #ex2 {
        margin-left: 10px;
        padding-left: 2px;
        padding-right: 4px;
        width: 40px;
        height: 20px;
    }

Berechnungen mit calc()

Typische arithmetische Ausdrücke innerhalb von CSS
Müssen innerhalb eines calc()-Funktionsaufrufs notiert werden
Vorteil: Mischung von absoluten und relativen Angaben
“Höhe des gesamten Browserfensters abzüglich einer festen Breite für die Navigation”
Vorteil: Exakte Angabe von Brüchen
“Exakt ein Drittel” statt “ungefähr 33.33333333%”
  • intro_css/calc-intro.html | Validieren
    <h1>Test</h1>
    
    <div class="calc">1</div>
    <div class="calc">2</div>
    <div class="calc">3</div>
    
    <div class="abs">1</div>
    <div class="abs">2</div>
    <div class="abs">3</div>
    
  • intro_css/calc-intro.css
    h1 {
        width: calc(100% - 80px);
        text-align: center;
        background-color: green;
    }
    .calc {
        float: left;
        width: calc(100% / 3);
        background: red;
    }
    .abs {
        float: left;
        width: 33.3%;
        background: blue;
    }
    

Rahmen mit border

Gestaltung von Rahmen um Boxen
  1. Breite (Längenangabe)
  2. Stil (none, hidden, dotted, dashed, solid, double, …)
  3. Farbe

Rahmen mit runden “Ecken”

Angabe eines Radius für die Breite oder Höhe der “runden Ecke”
Zu große Werte werden auf die maximal mögliche Höhe und Breite limitiert
Radius für jede Ecke lässt sich einzeln angeben
  • border-radius als Kurzschreibweise für alle vier Werte
  • Spezifisch: border-top-left-radius, border-top-right-radius, border-bottom-right-radius & border-bottom-left-radius.
  • intro_css/border-radius.css
    .box {
        width: 100px;
        height: 100px;
    }
    #box1 {
        border: 1px dotted black;
        border-radius: 15px;
    }
    #box2 {
        border: 5px double fuchsia;
        border-radius: 10% 30% 10% 30%;
    }
    #box2:hover {
        border-radius: 10%;
    }
    #box3 {
        border: 2px solid green;
        border-radius: 200px;
    }
    
  • intro_css/border-radius.html | Validieren
    <div class="box" id="box1">#box1</div>
    <div class="box" id="box2">#box2</div>
    <div class="box" id="box3">#box3</div>
    

Hintergründe mit box-shadow

Erlaubt Angabe von “verschobenen” Hintergrundfarben die (unter Umständen) wie Schatten aussehen
Zeichenbereich des “Schattens” hat keinen Einfluss auf die Dimensionen des Elements
Notwendige Parameter: Verschiebung und Farbe
box-shadow: <Versatz X-Achse> <Versatz Y-Achse> <Farbe>
Optionale 3. & 4. Parameter: “Verschwommenenheit” und Größe
  • Farbe wird immer zuletzt genannt
  • “Verschwommenheit” (blur) ist die Distanz zu den Rändern an denen der Schatten “ausfasert”
  • Normalerweise hat der Schatten die Größe der Box, mit dem spread-radius
  • intro_css/box-shadow.css
    .box {
        width: 100px;
        height: 100px;
    }
    #box1 {
        border: 3px solid red;
        box-shadow: 25px 25px black;
    }
    #box1:hover {
        box-shadow: 25px 25px 10px black;
    }
    #box2 {
        border: 5px double fuchsia;
        border-radius: 10% 30% 10% 30%;
        box-shadow: 10px 10px blue;
    }
    #box2:hover {
        box-shadow: 10px 10px 0px 10px blue;
    }
    
  • intro_css/box-shadow.html | Validieren
    <div class="box" id="box1">
      #box1
    </div>
    <p>Ich bin ein Text zwischen den Boxen</p>
    <div class="box" id="box2">
      #box2
    </div>
    

Änderungen von Layout-Dimensionen und Benutzerinteraktion

Wie gesehen: Boxen können trivial mit z.B: :hover beinflusst werden
Gilt grundsätzlich für alle CSS-Eigenschaften
Vorsicht: Layout “zittert” möglicherweise (oder wird sogar instabil) wenn ungeschickte Änderungen zusammenfallen
  • Faustregel: Endgültige Positionsangaben so wenig wie irgend möglich verändern
  • Ausblick: Bessere Optionen (z.B. Skalierung) im Kapitel “Animation”
Sonderfall border: Eignet sich sehr gut zur Hervorhebung
Angabe eines transparenten Rahmens im “Normalzustand”
  • intro_css/changing-dimensions.css
    .box {
        width: 50vw;
        height: 20vh;
        background-color: LightGoldenRodYellow;
    }
    
    div.box:hover {
        border: 5px double black;
    }
    
    .box.smart {
        border: 5px solid transparent;
        width: calc(50vw - 10px);
    }
    
  • intro_css/changing-dimensions.html | Validieren
    <div class="box">
      Not Smart <!-- (Clever?) -->
    </div>
    
    <div class="box smart">
      .smart <!-- (Clever &amp; Smart?) -->
    </div>
    
    <div class="box">
      Not Smart <!-- (Clever?) -->
    </div>
    

Positionierung mit float

Löst einen Block aus dem normalen Fluss
Erlaubt text- und inline-Elementen um entsprechende Elemente herumzufließen
Kein Einfluß auf die Dimensionen der Elternelemente
Ein Element mit ausschließlich float-Kindern verschwindet möglicherweise
left oder right
Positionierung auf der linken oder rechten Seite
none
Verbietet jeglichen Umfluss

Beispiel mit Bildunterschriften

  • intro_css/float-intro.css
    figure {
        float: right;
        width: 100px;
        border: 1px solid black;
    }
    
  • intro_css/float-intro.html | Validieren
    <figure>
      <img src="/assets/photos/sherlock-holmes-portrait-paget.jpg">
      <figcaption>
        Sherlock Holmes,
        Urheber: <a rel="author"
                    href="https://de.wikipedia.org/wiki/Sidney_Paget">
        Signey Paget
        </a>
      </figcaption>
    </figure>
    
    {{ page.flavour_text }}
    

Vorgehen zur Positionierung

Positionierung in DOM-Reihenfolge
Treffen mehrere Floats aufeinander, so werden diese in der Reihenfolge, in der sie im Dokument vorkommen von links nach rechts angeordnet. Dabei dürfen sich die Margin-Boxen der Floats nicht überlappen (das gilt auch für Floats, die in unterschiedliche Richtungen floaten).
Verschiebung nach unten bei Überläufen
Ist die Breite von zwei nebeneinanderstehenden Floats größer als die Breite des Elternelements, wird das zweite floatende Element nach unten verschoben, sodass sich die obere Außenkante dieses Floats unter der unteren Außenkante des vorherigen Floats befindet. In diesem Fall darf der verschobene Float keine sich weiter oben befindende Position einnehmen.
Unvermeidbare Überläufe
Nur ein Float, der die linke Innenkante des Elternelements berührt, darf die rechte Innenkante des Elternelements überschreiten.
Anker ist “oben links”
Grundsätzlich werden Floats so weit oben und links wie möglich positioniert. Eine höhere Position wird dabei einer möglichen, sich weiter links befindenden Position bevorzugt. Ein Float darf nicht höher positioniert werden als andere Floats oder Elemente, die sich vor ihm im Elementfluss befinden.

Quelle: selfhtml-Wiki

Reihenfolge beeinflusst maßgeblich die Positionierung! Für später genannte Elemente steht immer weniger Platz zur Verfügung.

Beispiel 1

Theoretisch: Perfektes “Mosaik” aus verschiedenfarbigen Blöcken
Praktisch: Korrektur der margin des body-Elements nötig
  • intro_css/float-stacking-1.css
    div {
        width: calc(25vw - 2px);
        height: calc(10vh - 2px);
        font-size: 2rem;
        text-align: center;
        border: 1px solid black;
    }
    div.l {
        float: left;
        background-color: rgba(255, 0, 0, 0.5);
    }
    div.r {
        float: right;
        background-color: rgba(0, 0, 255, 0.5);
    }
    
  • intro_css/float-stacking-1.html | Validieren
    <div class="l">1</div>
    <div class="r">2</div>
    <div class="r">3</div>
    <div class="r">4</div>
    <div class="r">5</div>
    <div class="r">6</div>
    <div class="r">7</div>
    <div class="r">8</div>
    <div class="r">9</div>
    <div class="r">10</div>
    <div class="l">11</div>
    <div class="l">12</div>
    

Beispiel 2

  • intro_css/float-stacking-2.css
    div {
        width: 98px;
        height: 48px;
        font-size: 2rem;
        text-align: center;
        border: 1px solid black;
    }
    div.l {
        float: left;
        background-color: rgba(255, 0, 0, 0.5);
    }
    div.huge{
        font-size: 4rem;
        height: 80px;
    }
    div.r {
        float: right;
        background-color: rgba(0, 0, 255, 0.5);
    }
    
  • intro_css/float-stacking-2.html | Validieren
    <div class="l">1</div>
    <div class="l huge">2</div>
    <div class="r">3</div>
    <div class="l">4</div>
    <div class="l">5</div>
    <div class="r">6</div>
    <div class="l">7</div>
    <div class="l">8</div>
    <div class="r">9</div>
    <div class="l">10</div>
    <div class="l">11</div>
    

Beispiel für unerwünschten Fluss

Gewünscht: Footer ganz am Ende der eigentlichen Seite
Problem: Dimensionen des float-Bildes unberücksichtigt

Mögliche Lösung: Zeilen erzwingen mit clear

Problem: Elternelement

Zur Erinnerung: Wenn ein Elternelement ausschließlich float-Elemente enthält, ist die Höhe 0
Im Beispiel erkennbar an fehlender gelber Hintergrundfarbe

Lösung 1: Elternelement mit künstlichem letzten Element

Lösung 2: clear-fix

  • intro_css/float-parent-clear-solution-2.html | Validieren
    <div class="image-gallery clearfix">
      {% for i in (1..12) %}
        <img src="/assets/icons/squirrel.svg">
      {% endfor %}
    </div>
    
  • intro_css/float-parent-clear-solution-2.css
    .image-gallery {
        border: 1px solid red;
        background-color: yellow;
    }
    .clearfix::after {
        visibility: hidden; /* Versteckter Hack ... */
        height: 0;          /* ... der nichts vertikal verschiebt ... */
        content: " ";       /* ... technisch gesehen Inhalt hat */
        display: block;     /* ... immer ein Block ist ... */
        clear: both;        /* ... und clear erzwingt! */
    }
    .image-gallery img {
        float: left;
        width: calc(25% - 10px);
        margin: 5px;
    }
    

Lösung 3 (?): display: inline-block (ohne float)

inline-block erlaubt die Angabe von Dimensionen ohne Zeilenumbrüche zu erzwingen
Elemente werden, wie inline-Elemente, von links nach rechts positioniert

Lösung 3 (!): display: inline-block (ohne float)

Problem: Trennende Zeilenumbrüche und Leerzeichen zwischen den Bildern
  • Praktische Lösung: Häßlicher Quelltext (Zeile in einer Schleife)
  • Mögliche Lösung: font-size des Eltern-Containers auf 0 setzen
  • Mögliche Lösung: Zeilenumbrüche mit Kommentaren maskieren

Berechnung mit verschiedenen Box-Modellen

Bisher häufig zu sehen: calc-Ausdrücke um von der Breite die Innenabstände abzuziehen
Fehleranfällig und umständlich
Abhilfe: Angabe eines alternativen Berechnungsmodells für Breite und Höhe
  • box-sizing: content-box: “Klassisches” Modell, Breite und Höhe stehen für sich selbst
  • box-sizing: border-box: “Alternatives” Modell, Innenabstände und Rahmen werden von der Breite oder Höhe abgezogen
  • intro_css/box-sizing.css
    .parent {
        width: 400px;
        border: 10px solid SaddleBrown;
    }
    
    .parent > div {
        width: 100%;
    }
    
    #content-box {
        box-sizing: content-box; /* Redundant */
        border: 10px solid red;
    }
    
    #content-box-calc {
        box-sizing: content-box; /* Redundant */
        width: calc(100% - 20px);
        border: 10px solid green;
    }
    
    #border-box {
        box-sizing: border-box;
        border: 10px solid blue;
    }
  • intro_css/box-sizing.html | Validieren
    <div class="parent">
      <div id="content-box">#content-box</div>
      <div id="content-box-calc">#content-box-calc</div>
      <div id="border-box">#border-box</div>
    </div>
    
    

Frustriert? Sie sind nicht allein!

Layouts mit Flexbox

Spezieller Layout-Modus zur flexiblen Anordnung von Containern
Noch kein offizieller Standard, aber schon jetzt recht breite Unterstützung
Von Grund auf skalierbar
Unterschiedlichste Anpassungsmöglichkeiten für verschiedene Layouts
Richtungsunabhängig
Weder horizontale (inline-Elemente) noch vertikale (block-Elemente) Ausrichtungen werden bevorzugt
Grundsätzliche Unterscheidung: “container” und “items”
“items” sind Kind eines “containers”

Verbreitung

Can I Use flexbox? Data on support for the flexbox feature across the major browsers from caniuse.com.

Online-Ressourcen

Eigenschaften von Flex-Containern

Verhalten bei Überläufen
flex-wrap: nowrap | wrap | wrap-reverse;
Angabe der Flussrichtung
flex-direction: row | row-reverse | column | column-reverse;
Umgang mit Leerraum
justify-content: flex-start | flex-end | center | space-between | space-around;
  • intro_css/flex-display.html | Validieren
    <div class="image-gallery">
      {% for i in (1..24) %}
        <div>{{ i }}</div>
      {% endfor %}
    </div>
    
  • intro_css/flex-display.css
    .image-gallery {
        border: 1px solid red;
        background-color: yellow;
        display: flex;
    }
    
    .image-gallery div {
        border: 1px solid black;
        background-color: lime;
        
        width: 25px;
        margin: 5px;
    }
    
    

Größe von Flex-Items mit flex-grow

Standard: Jedes Element bekommt exakt die Breite die es benötigt
Eigenschaft flex-grow auf 0.
Relativ: Gewichtung des Wachstums mit flex-grow
  • Endgültige Breite ergibt sich aus dem frei verfügbaren Platz
  • Wert von flex-grow / Summe aller Verhältnisse ergibt Gewichtung
Absolut: Angabe einer festen Breite oder Höhe mit width und height
  • Elemente werden dann genau diese Breite oder Höhe bekommen
  • Alternativ spezifischere Angabe von flex-basis um allgemeinere width & height zu überschreiben
  • intro_css/flex-sizing.html | Validieren
    <div class="flex-parent">
      <p>Laaaaaang</p>
      <p>Kurz</p>
      <p>Laaaaaang</p>
    </div>
    
    <div class="flex-parent">
      <p style="flex-grow: 1">1</p>
      <p>Kurz</p>
      <p style="flex-grow: 1">1</p>
    </div>
    
    <div class="flex-parent">
      <p style="flex-grow: 3">3</p>
      <p style="flex-grow: 2">2</p>
      <p style="flex-grow: 1">1</p>
    </div>
    
    <div class="flex-parent">
      <p style="flex-grow: 3">3</p>
      <p style="width: 200px">200px</p>
      <p style="flex-grow: 2">2</p>
      <p style="flex-grow: 1">1</p>
    </div>
  • intro_css/flex-sizing.css
    .flex-parent {
        border: 1px solid red;
        background-color: yellow;
        display: flex;
        flex-wrap: wrap;
        flex-direction: row;
    }
    
    .flex-parent > * {
        border: 1px solid black;
        background-color: lime;
    }
    
    

Beispiel: Bildergallerie mit flex statt float

  • intro_css/flex-gallery.html | Validieren
    <div class="image-gallery">
      {% for i in (1..12) %}
        <img src="/assets/icons/squirrel.svg">
      {% endfor %}
    </div>
    
  • intro_css/flex-gallery.css
    .image-gallery {
        border: 1px solid red;
        background-color: yellow;
        display: flex;
        flex-wrap: wrap;
    }
    
    img {
        margin: 5px;
        width: calc(25% - 10px);
    }
    

Dreispaltige Layouts

“Heiliger Gral” der Layoutstrukturen
Eines der typischsten Layouts im Web

Dreispaltiges Layout

Nutzen Sie diese Beispiele nicht für tatsächliche Projekte! Die hier gezeigten Vorgehensweisen sind in dieser Form ausschließlich auf großen Bildschirmen sinnvoll nutzbar. Wie es besser geht klären wir im Kapitel "Responsive Design".

Die Ausgangslage

  • intro_css/three-column-initial.html | Validieren
    <header>
      Wenn ich groß bin, werde ich ein dreispaltiges Layout
    </header>
    
    <nav>nav</nav>
    <main>main</main>
    <aside>aside</aside>
    
    <footer>footer</footer>
    
  • intro_css/three-column-initial.css
    body {
        background-color: yellow;
    }
    
    header, nav, main, aside, footer {
        background: lightgray;
        border: 1px solid black;
        padding: 10px;
    }
    
    nav, main, aside {
        min-height: 100px;
    }
    

Mit float

Mit flex

Absolute Positionsangaben im Layout

Grundidee: Angabe von exakten Pixelpositionen (z.B. Bezogen auf den Bildschirm)
Elemente werden komplett aus dem normalen Layout herausgelöst
Einsatz von absoluten Angaben nur in Ausnahmefällen!
Skaliert besonders schlecht auf kleinen Bildschirme
Typischster Einsatzzweck: Bewusste Überlagerung von Elementen
Absolute Angaben dann relativ zum Elternelement oder zum Viewport
Angabe von absoluten Positionsangaben mit den Eigenschaften left, right, top und bottom
Werte sind Längenangaben, genaues Verhalten ist abhängig von der position-Eigenschaft

Zeichenreihenfolge anhand des z-index

Lösen von Elementen aus dem normalen Layoutfluss erlaubt Überlappungen
Absolut positionierte Elemente werden einfach verschoben, es finden keine Layout-Anpassungen statt
Standardverhalten: Tiefer geschachtelte Elemente liegen weiter “vorne”
Werden gewissermaßen “auf” ihre Eltern gezeichnet
CSS-Eigenschaft z-index erlaubt Eingriff in die Zeichenreihenfolge
Hauptsächlich für Elemente auf der gleichen Ebene relevant, “höher” ist “weiter vorne”

Verschiebung der eigenen Position mit position: relative

Element wird zunächst im normalen Fluss positioniert und dann verschoben
Anpassung ist absolute Positionierung, daher: Verschiebung hat keinen Einfluss auf das umliegende Layout
  • intro_css/position-relative.html | Validieren
    <div>Un</div>
    <div>ord</div>
    <div>nung</div>
    
  • intro_css/position-relative.css
    div {
        float: left;
        position: relative;
        border: 1px solid black;
        text-align: center;
        width: calc(33% - 2px);
        height: 40px;
    }
    
    div:nth-child(1) {
        top: 10px;
    }
    
    div:nth-child(2) {
        top: 25px;
        left: -20px;
    }
    
    div:nth-child(3) {
        top: 5px;
        right: 60px;
    }
    

Ausrichtung am Elternelement mit position: absolute

Element wird aus dem normalen Fluss gelöst und nimmt auch keinen Platz ein
Dimensionen haben also keinen Einfluss auf das Layout
Vorsicht: Ohne Angabe einer Position erfolgt die initiale Positionierung dennoch im Textfluss
Mindestens eine Angabe von left, right, top oder bottom sinnvoll
Positionierung erfolgt im Koordinatensystem des nächsten absolut positionierten Elternelements
Typischerweise wird dazu ein Element mit position: relative genutzt
  • intro_css/position-absolute.html | Validieren
    <div class="bureau-parent">
      <img src="/assets/photos/bureau.jpg" alt="Büro mri">
      <div class="bureau-box">
      </div>
    </div>
    
  • intro_css/position-absolute.css
    .bureau-parent {
        position: relative;    
    }
    
    img {
        width: 100%;
    }
    
    
    .bureau-box {
        position: absolute;
        border: 15px solid white;
        width: 20%;
        height: 12%;
        top: 48%;
        left: 30%;
    }
    

Ausrichtung am Viewport mit position: fixed

Positionierung im Bildschirm-Koordinatensystem
Element wird vollständig aus dem normalen Fluss herausgelöst
Typische Nutzung: Jederzeit erreichbare Bedienelemente
Navigation, Feedback, …
  • intro_css/position-fixed.html | Validieren
    <h1 id="top">Weise Worte</h1>
    <a class="back-to-top" href="#top">Zurück zum Start</a>
    {% for quote in page.quotes %}
      <div>
        <blockquote>{{ quote.text }}</blockquote>
        {{ quote.author }} &dash;
        <a href="{{ quote.url }}" rel="author">{{ quote.title}}</a>
      </div>
    {% endfor %}
    
    
  • intro_css/position-fixed.css
    .back-to-top {
        position: fixed;
        bottom: 0px;
        right: 0px;
        background-color: yellow;
    }
    

position: fixed und ungewollte Überdeckung

Problem: Am Bildschirm ausgerichtete Elemente schieben sich möglicherweise vor den Inhalt
Besondere Vorsicht bei am Viewport positionierten Inhalten notwendig
Mögliche Lösung: Angabe von Außenabständen
Überdeckter Bereich wird “freigehalten”

Gleitende Positionierung mit position: sticky

Zunächst: Berechnung anhand der normalen Positionierungsregeln
Normale Platzierung im Dokumentfluss
Danach: Versatz gemäß dem Abstand zum Eltern-Element
Versatz hat keinen Einfluß auf Positionierung anderer Elemente (wie bei relative)
  • intro_css/position-sticky.html | Validieren
    <dl>
      <dt>A</dt>
      <dd>Andrew W.K.</dd>
      <dd>Apparat</dd>
      <dd>Arcade Fire</dd>
      <dd>At The Drive-In</dd>
      <dd>Aziz Ansari</dd>
      <dt>C</dt>
      <dd>Chromeo</dd>
      <dd>Common</dd>
      <dd>Converge</dd>
      <dd>Crystal Castles</dd>
      <dd>Cursive</dd>
      <dt>E</dt>
      <dd>Explosions In The Sky</dd>
      <dt>T</dt>
      <dd>Ted Leo &amp; The Pharmacists</dd>
      <dd>T-Pain</dd>
      <dd>Thrice</dd>
      <dd>TV On The Radio</dd>
      <dd>Two Gallants</dd>
    </dl>
    

Beispiel: Stapeln von Elementen mit dem z-index