Elemente ohne Semantik

Notwendig aufgrund von Layoutvorgaben
Sollten nur eingesetzt werden, wenn keine passende semantische Alternative existiert
Werden in der Regel mit Attributen kombiniert
Keinerlei eigene Aussagekraft
Attribut class wird für optische Anpassungen genutzt
Werden wir heute noch drüber reden
Attribut id wird zur eindeutigen Identifizierung benutzt
Fragmente in der URL #ziel navigieren zu IDs

block- und inline-Elemente

Wesentliche Unterschiede
  • block-Elemente beginnen im Layout auf einer neuen Zeile und nehmen die ganze Seitenbreite ein
  • inline-Elemente betten sich in den Textfluss ein um so wenig Platz wie möglich zu beanspruchen
Die meisten Elemente fallen in eine dieser beiden Kategorien
Wesentliche Ausnahmen sind Elemente im Zusammenhang mit Tabellen und Flexboxen

Allgemeine block-Elemente mit div

  • intro_html/div.html | Validieren
    <div class="game-card artifact" id="black-lotus">
      <h1>Black Lotus</h1>
      <img src="/assets/photos/black-lotus.jpg"
           alt="black-lotus">
      <p class="rules">
        Adds 3 mana of any single colour of your choice
        to your mana pool, then is discarded. Tapping
        this artifact can be played as an interrupt.
      </p>
    </div>
    
    <div class="game-card black" id="thoughtseize">
      <h1>Thoughtseize</h1>
      <img src="/assets/photos/thoughtseize.jpg"
           alt="thoughtseize">
      <p class="rules">
        Target player reveals his or her hand. You choose
        a nonland card from it. That player discards that
        card. You lose 2 life.
      </p>
    
      <p class="flavour">
        Any dream is a robust harvest. Still, I prefer the
        timeworn dreams, heavy with import, that haunt the
        obsessive mind.
      </p>
    </div>
    

Allgemeine inline-Elemente mit span

  • intro_html/span.html | Validieren
    <div class="game-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>
    

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

Das class-Attribut und der .-Selektor

Kurzschreibweise: .<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: nth-child zur “Abwechslung”

Mit nth-child lassen sich Selektoren auf nur jedes n-te Kind der Trefferliste eingrenzen
Typische Verwendung: Spezielle Konstanten für gerade (even) und ungerade (odd)

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

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.

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;
    }
    

Auswahl von Styling-Eigenschaften

Texteigenschaften

font-size: Größe des Textes
Beliebige Längenangabe
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;
    }
    
    

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>
    

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

Zeitabhängige Animation mit CSS

Ziel: Graduelle Veränderung von numerischen Werten ohne JavaScript
Technik dahinter ist allerdings noch nicht vollständig standarisiert
Nicht alle Eigenschaften lassen sich animieren, numerische Werte aber meistens schon
Genaue Auflistung zum Beispiel im MDN

Transitionen

Funktionsweise: Neue CSS-Eigenschaften werden nicht unmittelbar angewendet, sondern zeitabhängig verändert
Angegeben wird immer der gewünschte Zielzustand, die Zwischenwerte berechnet der Browser
Zwischenwerte werden über eine mathematische Funktion berechnet
Standardwert ist eine “Ease”-Funktion, andere Berechnungen ebenfalls möglich
Syntax: Liste von animierten Eigenschaften mit Dauer und Funktion
  • Animation aller Eigenschaften mit all möglich
  • Explizite Angabe der Animationsfunktion mit transition-timing-function

Beispiel: Veränderung einer Eigenschaft

Beispiel: Veränderung zweier Eigenschaften

Beispiel: Veränderung aller Eigenschaften

  • animate/transition-all.html | Validieren
    {% for i in (1..5) %}
      <div class="bar">
        Bar {{ i }}
      </div>
    {% endfor %}
    
  • animate/transition-all.css
    .bar {
        width: 20%;
        background-color: red;
        border: 2px solid red;
        text-align: right;
        transition: all 2s;
    }
    
    .bar:hover {
        width: 90%;
        background-color: green;
        margin-left: 10%;
        border: 2px solid yellow;
    }
    

Stetige Übergangsfunktionen

Intern: Verarbeitung von kubischen Bézier-Kurven
Irrelevantes Implementierungsdetail für nicht MInf und nicht CGT

Unstetige Übergangsfunktionen

Angabe von Schritten mit steps(number, direction)
  • number Ganzzahl für die Anzahl der Schritte
  • direction ist start oder end und bestimmt ob am Anfang oder am Ende keine Zeit vergehen soll
Bald: Angabe von Schritten mit frames(number)

Beispiele für Übergangsfunktionen

  • animate/transition-func.html | Validieren
    <div class="parent">
      {% for func in page.transitions %}
        <div class="bar"
             style="transition-timing-function: {{ func }};">
          <code>{{ func }}</code>
        </div>
      {% endfor %}
    </div>
    
  • animate/transition-func.css
    .bar {
        width: 25%;
        background-color: rgba(255, 0, 0, 0.2);
        border: 1px solid black;
        margin: 2px;
        text-align: right;
        transition: width 3s;
    }
    
    .parent:hover .bar {
        width: 100%;
    }
    

Animationen mit Keyframes

Funktionsweise: Neue CSS-Eigenschaften durchlaufen eine Liste von Zuständen (“Keyframe”)
Letzter Keyframe steht für den endgültigen Zustand
Umfangreiche Spezifikation aus acht Werten
  • animation-name für die zu verwendende Keyframe-Liste
  • animation-duration für die Dauer der Animation
  • animation-iteration-count für die Anzahl der Wiederholungen

Beispiel für endlos laufende Animation

  • animate/animate-color.html | Validieren
    <div class="rainbow">
      Rainbow
    </div>
    
  • animate/animate-color.css
    @keyframes colorRotate {
        from  { color: rgb(255,   0,   0); }
        16.6% { color: rgb(255,   0, 255); }
        33.3% { color: rgb(  0,   0, 255); }
        50%   { color: rgb(  0, 255, 255); }
        66.6% { color: rgb(  0, 255,   0); }
        83.3% { color: rgb(255, 255,   0); }
        to    { color: rgb(255,   0,   0); }
    }
    
    .rainbow {
        font-size: 15vw;
        font-family: monospace;
        text-align: center;
        animation: colorRotate 3s linear 0s infinite;
    }
    
    

Umfrage zur SchülerUni