Im zweiten Teil des Artikels geht es um die Verfeinerung des designerischen Anteils eines HTML-Prototypen mittels CSS. Zur Erinnerung kann man hier den ersten Teil nachlesen.

Zusätzlich zum Verständnis von HTML und CSS aus Teil 1, setze ich nun leichtes Vorwissen im Präprozessor Sass/ SCSS vorraus.

Verfeinerung

Wir haben bisher eine solide HTML-Struktur und ein grundlegendes Layout des Card-Elements, nun nähern wir uns nach und nach, soweit es geht den Designanforderungen an.

Hierbei spielt in Zeiten von Responsive Design, die in den vergangenen Jahrzehnten oftmals geforderte Pixelperfektion keine Rolle mehr, denn Browser und Geräte mit ihren verschiedenen Renderengines der Browser sorgen für eine immer leicht verschiedene Interpretation der CSS-Anweisungen.
Je nach Umfang der implementierten Features, werden moderne CSS-Anweisungen ignoriert oder wie z.B. im Falle des Internet Explorers, auf eine dem Standard abweichende Weise interpretiert.

Unterschiedliche Größen und Dimensionen von Geräten erfordern einen responsiven Ansatz, ohne allzu fixe Größen, damit das Design sich adaptiv an den zur Verfügung stehenden Platz anpassen kann. Kurzum: Webseiten müssen (= können) nicht in jedem Browser gleich aussehen.

Texte

Im Design wird die Font "Proxima Soft" vorgegeben. Wir laden diese asynchron vom Anbieter Adobe Fonts (vormals Typekit) als Webfont. Die Anweisung für den Font-Stack beinhaltet noch ein Fallback für eine serifenlose Schrift, für den Fall wenn die Schrift einmal nicht geliefert wird.

.pt-moderncard {
  ...
  font-family: "proxima-soft", sans-serif;
  box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  border-radius: 4px;
}

Damit das Card-Element noch besser seiner Metapher einer (Spiel-) Karte entspricht, wird hier mit einem Schatten per box-shadow und abgerundeten Ecken per border-radius gearbeitet.

Als nächstes erhalten die Überschriften (.pt-moderncard__headline und .pt-moderncard__subhead) jeweils passende Schriftgrößen, Zeilenhöhen und Abstände.

Hierbei verwende ich ausschließlich Außenabstände nach unten (margin-bottom), da ich dadurch keine größeren Additionen von Innen- und Außenabständen zwischen einem und dem nachfolgenden Element bedenken muss. Dadurch ist das Box-Modell bei Untersuchung eines Elements direkter erkennbar, wie der folgende Screenshot der Firefox-Devtools zeigt:

Screenshot: Box-Modell Abstände der Überschrift

Zeilenbegrenzung

Beim Text .pt-moderncard__excerpt handelt es sich um die Beschreibung der Veranstaltung, die auch mal lang werden kann. Um nur einen Auszug daraus darzustellen und damit sicherzustellen, dass kein Text aus der Karte herausläuft, soll die Zeilenanzahl auf fünf begrenzt werden.

Um nicht aufwändig per JavaScript Zeichen zu zählen und dann abzuschneiden, habe ich stattdessen einen reinen (S)CSS Ansatz gewählt.
Mittels der Schriftgröße, der Zeilenhöhe, multipliziert mit der gewünschten/vorgegebenen Zeilenanzahl, kann ich die maximale Höhe des Paragraphen errechnen:

.pt-moderncard__excerpt {
  ...
  $paragraph-font-size: 14px;
  $paragraph-line-height: 1.22;
  $paragraph-lines: 5;
  $paragraph-height: $paragraph-font-size * $paragraph-line-height * $paragraph-lines;

  font-size: $paragraph-font-size;
  line-height: $paragraph-line-height;
  max-height: $paragraph-height;
  overflow: hidden;
}

Wichtig ist hierbei noch overflow: hidden, um alles was über die berechnete maximale Höhe hinausgeht, auch zu verstecken.

Animation

Der Designer/Konzepter hatte eine klare Vorstellung davon, wie sich das Element bei Hover verhalten sollte.
Das Verhältnis der Breite vom linken zum rechten Bereich (.pt-moderncard__meta und .pt-moderncard__main) soll sich von 50:50 auf 30:70 verändern.
Gleichzeitig kann durch den im Textbereich gewonnenen Raum, der eben abgekürzte Text auf sieben Zeilen verlängert werden, damit mehr Inhalt lesbar wird.

Die Breitenaufteilung wird durch Veränderung der jeweiligen flex-basis Werte erreicht. Zur Anpassung der maximalen Höhe des Textes bei hover, wird eine neue Konstante mit höherem Multiplikator für die Zeilen verwendet.

.pt-moderncard__main {
  flex-basis: 50%;
  transition: all 0.1s linear 0.1s;
  ...

  .pt-moderncard:hover & {
    flex-basis: 70%;
  }
}

.pt-moderncard__meta {
  flex-basis: 50%;
  transition: all 0.1s linear 0.1s;
  ...

  .pt-moderncard:hover & {
    flex-basis: 30%
  }
}

.pt-moderncard__excerpt {
  ...
  $paragraph-lines-hover: 7;
  $paragraph-height-hover: 
    $paragraph-font-size * $paragraph-line-height * $paragraph-lines-hover;

  .pt-moderncard:hover & {
    max-height: $paragraph-height-hover;
  }
}

Ich nutze hier den von Sass bereitgestellten Parentselector, um je die Unterelemente bei :Hover über das Elternelement zu verändern.
Es wird außerdem eine Übergangsanimation (transition) genutzt, die nicht zu abgehackt hart aussieht.

Um den Verkleinerungs/Verbreiterungseffekt schöner zu gestalten, erhält das Bild noch folgende Regel, damit der Bildausschnitt bei Verkleinerung des linken Containers links ausgerichtet bleibt:

.pt-moderncard__image {
  ...
  object-position: left;
}

Moderne Variante mit CSS-Variablen

Ein relativ neues Feature sind CSS-Variablen, ähnlich wie bei Präprozessoren hat man darüber die Möglichkeit der Verwendung von Variablen, jedoch direkt im CSS, im Browser.
Der große Unterschied gegenüber Präprozessor-Variablen ist deshalb die Veränderbarkeit des Variablenwertes zur Laufzeit.
Sie sind bereits von allen modernen Browsern (das heißt: nicht dem IE) implementiert.

Da deshalb ein Großteil der Browser unserer Nutzer das noch nicht können, ist es für uns leider nicht produktiv einsetzbar. Als kurzes Experiment habe ich das aber einmal ausprobiert Hier zur genauen Ansicht der zugehörige Codepen.

Zunächst werden "globale Variablen" über einen :root-Selector definiert. Darüber sind sie im gesamten Dokumentenscope nutzbar.
Der Text erhält dann eine Variable, die per CSS Berechnung calc() diese Werte multipliziert, welche dann als Wert für die max-height verwendet wird.

:root {
  --paragraph-font-size: 14px;
  --paragraph-line-height: 1.22;
  --paragraph-lines: 5;
}

.pt-moderncard__excerpt {
  ...

  --paragraph-height: 
    calc(var(--paragraph-font-size) * var(--paragraph-line-height) * var(--paragraph-lines));
  max-height: var(--paragraph-height);
}

.pt-moderncard:hover {
  --paragraph-lines: 7;
}

Für den :hover-Style der umfassenden .pt-moderncard muss jetzt nur noch der Wert der Variablen auf der Anzahl der gewünschten Zeilen verändert werden. Kurz, übersichtlich und elegant! 😍

Man sieht, dass dieser Ansatz viel mehr dem Prinzip von Variablen aus Programmiersprachen gleicht, während im Präprozessor eher mit mehreren "Konstanten" gearbeitet wird, wo also je Modifikation eine eigene Konstante geschrieben werden muss.

Accessibility: Reduced Motion

Epilepsiewarnungen vor Videos gibt es schon seit Jahrzehnten, doch auch Betriebssysteme bieten heutzutage die Möglichkeit eine Einstellung zu aktivieren um weniger bzw. reduzierte Animationen dargestellt zu bekommen.

Screenshot: Youtube Video Seizure Warning

Eine solche Wahl zu treffen kann verschiedene Gründe haben.
Eine Vielzahl von Menschen haben Gleichgewichtsstörungen oder empfinden Schwindel, was durch die Betrachtung von sich bewegenden Bildschirminhalten verschlechtert werden oder Symptome hervorrufen kann.

Ein anderer Grund eine solche Einstellung zu wählen ist, dass automatisch ablaufende Animationen auf Webseiten Ressourcenintensiv und damit Batterieziehend sind, was bei Smartphones wichtig sein kann.

In Mac OSX (und auch iOS) findet man diese Einstellung in den Systemeinstellungen unter "Bedienungshilfen" > "Anzeige" > "Bewegung reduzieren".
In Mac OSX wird bei Wechsel zwischen Desktops zum Beispiel dann statt eines "Schwenks" eine angenehmere Überblendung genutzt.

Screenshot: Mac OSX Bedienungshilfen

In (manchen) Browsern können wir Webentwickler diese Informationen nun als neuen Media-Query prefers-reduced-motion abfragen.

Für unser hier vorliegendes Beispiel der :hover-Übergangsanimation, habe ich das so verwendet:

.pt-moderncard__main {
  ...
  flex-basis: 50%;

  .pt-moderncard:hover & {
    flex-basis: 70%;
  }

  @media screen and (prefers-reduced-motion: reduce) {
    .pt-moderncard:hover & {
      flex-basis: 50%;
    }
  }
}

.pt-moderncard__meta {
  ...
  flex-basis: 50%;

  .pt-moderncard:hover & {
    flex-basis: 30%
  }
  @media screen and (prefers-reduced-motion: reduce) {
    .pt-moderncard:hover & {
      flex-basis: 50%;
    }
  }
}

.pt-moderncard__excerpt {
  ...
  max-height: $paragraph-height;

  .pt-moderncard:hover & {
    max-height: $paragraph-height-hover;
  }
  @media screen and (prefers-reduced-motion: reduce) {
    .pt-moderncard:hover & {
      max-height: $paragraph-height;
    }
  }
}

Alle :hover-Regeln für .pt-moderncard werden also im Falle von bevorzugter reduzierter Bewegung wieder auf den Ausgangswert umgeschrieben.

In meinen Tests respektierten bereits der Safari (10) und der Firefox (66) den Media-Query prefers-reduced-motion, die Browseradaption ist noch nicht allzu weit fortgeschritten, da es sich noch in der Entwurfsphase beim W3C befindet (kommende Blink-basierte Browser (Chrome, Edge, Opera) werden es auch schon können).
Somit ist die Verwendung der Regel ein gutes progressives Enhancement, User mit Browsern, die darauf Wert legen, werden nicht von Animationen belästigt, andere Browser ignorieren es einfach.

Ende

Und damit bin ich auch schon am Ziel. Der HTML-Prototyp wurde in designerischer Hinsicht verfeinert und der Anforderung angeglichen.
Animationen wurden eingebaut, die bei Interesse mehr Inhalt zu Tage fördern, mit der Option für reduzierte Bewegung.

Hier das Resultat (der Variante ohne CSS-Variablen):