Ich möchte hiermit Einblicke in meine Denk- und Arbeitsweise beim "Übersetzen" einer Designvorgabe in einen HTML-Prototypen geben.
Ich setze mittlere Vorkenntnisse in HTML und CSS voraus.

Ich spiele das Ganze an einem neu entwickelten UI-Element durch, das Kurzinformationen zu einer Veranstaltung anzeigt. Hier die Designvorgabe:

Screenshot der Designvorgabe: Kartenelement mit Bild und Text

Das Ziel der Umsetzung ist also eine Art Karte mit Bild, Texten und zusätzlichen Informationen über Ort und Datum.

In diesem Artikel werde ich mich zunächst einmal grob dem Layout der Vorgabe annähern, also Aufteilung, Größen und Platzierung von Boxen und mich später um die visuelle Verfeinerung kümmern.

Semantisches HTML

Ein sinngemäß aus dem Gedächtnisprotokoll wiedergegebenes Zitat eines unbekannten Internet-Users ist: "HTML is the bones, CSS the skin [and backend and JS the muscles]".
Zuerst muss also ein robustes Skelett vorhanden sein, damit eine Website solide stehen kann.

Als erstes denke ich über die Strukturierung nach. Ich versuche zunächst einmal semantisch sinnhaftes HTML zu schreiben. Gute Semantik hat viele Vorteile gegenüber der sogenannten div-Suppe.

Ich beginne mit der Auswahl eines HTML-Elements der umfassenden Box.
Mit HTML5 wurden die Sectioning-Elemente zur Strukturierung eines Dokuments geschaffen.
Das Kartenelement wird also ein article sein, da es eine in sich abgeschlossene Einheit ist.

Überschrift

Es geht jetzt darum, Gruppierungen von Elementen zu finden. Beispielsweise werden Überschrift h1 und Sub-Überschrift p in der Regel gemeinsam auftreten und werden hier zum header. Ein Header ist nicht nur ausschließlich für den oberen Berech der ganzen Seite reserviert, sondern darf je article genutzt werden.

Jedes in sich geschlossene Sectioning-Element trägt zur Dokumentenstruktur bei und darf deshalb auch eine eigene Überschrift erster Ordnung haben. Diese bezieht sich dann auf diesen kleinen Bereich.

Boxen

Bei der Betrachtung eines Layout-Mockups fallen mir direkt zusammenhängende Bereiche auf, die zu Boxen zusammengefasst in HTML übertragen werden können.

Meme aus dem Film "The Sixth Sense" mit Text "I see dead boxes"

Ich lasse nun also erste Verfeinerungen der Struktur einfließen, die aus Layoutgründen nötig werden können.

Die Erfahrung sagt mir, dass es sinnvoll sein kann, die beiden visuellen Spalten (Bild links und Text rechts), als zusammengefasste Gruppen zu betrachten.
Hier nehme ich sections, da sie abgeschlossene Bereiche innerhalb des Artikels darstellen. Später kann hierüber auch einfacher gelayoutet werden (siehe dazu den Abschnitt CSS).

Grafische Darstellung der HTML Bereiche am Design

Ebenso bezeichne ich den Bereich, der visuell am unteren Ende der Karte angesiedelt ist, und eher zweitrangigere Informationen enthält, als footer. Auch das Footer-Element darf je Sektionselement genutzt werden und nicht nur für die gesamte Seite.

Weitere Elemente

Für die Auflistung der Fakten bietet sich hier die unordered list ul mit ihren Einträgen li an.
Für die Icons werden SVGs genutzt, da es sich um grafisch einfach aufgebaute Piktogramme handelt.

SVG ist hier aufgrund seiner Bytegröße einer Pixelgrafik zu bevorzugen, um Ladeperformance zu verbessern.
Diverse Gründe sprechen auch für die Nutzung von SVGs gegenüber Iconfonts.

Das Bild auf der linken Seite ist natürlich ein img-Tag, erhält damit auch ein alt-Attribut zur Beschreibung des visuellen Inhalts, im Falle einer ungültigen URL und natürlich für Accessibility-Technologie wie Screenreader.

Klassen

Als Frontend-Entwickler trägt man die Verantwortung, dass Regeln für eine neue Komponente, keine Störungen bestehender Elemente hervorruft. Dazu ist wichtig, dass die CSS-Regeln eine gewisse Spezifität haben.

Unsere Code Conventions sehen daher einen gekapselten Ansatz vor, der über möglichst alleinstehende Klassen erreicht wird.
Gemeinsamkeiten wollen wir nicht über Verwendung mehrere "single-purpose Klassen" am Element, sondern über das inkludieren von Gemeinsamkeiten CSS-seitig, erreichen.

Das klingt erstmal umständlich, bedeutet im wesentlich aber nur, dass jede neue Komponente, eine eigene CSS-Datei erhält, in der mit eigenen neuen Klassen je Unterelement gestartet wird und so kaskadierende (sprich = beeinflußende, fremde) Regeln beschränkt.

Wir befolgen das BEM-Prinzip und fügen ein Präfix hinzu, dass anzeigt in welchem Bereich das Element genutzt wird. Das ist hier pt- weil es im Portal genutzt wird, was codeseitig Synonym für unser Cockpit ist.

Naming things is hard, wie immer. Ich habe mich für .pt-moderncard als Bezeichnung für den Block entschieden.

Die weiter oben beschriebene, geschaffene Unterteilung der Spalten in zwei sections, erhält nun beschreibende Namen nach dem BEM-Prinzip.

Hier wählte ich .pt-moderncard__meta für das linke Element welches das Bild beinhaltet, was eher Metainformationen ist und .pt-moderncard__main für den rechten Block mit den Hauptinformationen.

Dann fasse ich aus Layoutgründen noch den Headerbereich und den kurzen Beschreibungstext zu .pt-moderncard__body zusammen. Das ist wieder eine Vorbereitung für spätere Flexboxen.

Bei weiteren Elementen setzt sich die Benamung nach BEM fort.
Ich versuche dabei darauf zu achten, dass ich keine zu langen Ketten bilde oder tiefe Hierarchien im Namen festmache. Das würde Flexibilität beim Refactoring und Wiederverwendbarkeit in anderen Kontexten verringern.

So bekommt .pt-moderncard__headline eine "flache" Bezeichnung für den "Element"-Teil, nämlich nur __headline, anstatt die Einordnung innerhalb __body und __head zu berücksichtigen. Damit ist flexibler möglich die Headline an anderer Stelle innerhalb des Card-Elements zu platzieren, ohne den Container im Namen beachten und umschreiben zu müssen.

Grafische Darstellung der genutzen Klassen am Design

CSS

Unsere .pt-moderncard hat nun eine erste grobe sematische HTML-Struktur und spezifische Klassen-Bezeichnungen. Anpassungen daran werden im Laufe der Entwicklung natürlich immer mal nötig, das ist ein iterativer Prozeß.

Nun geht es darum, es visuell dem Entwurf anzunähern.

Layout mit Flex

Als erstes Werkzeug zum layouten greife ich zu Flexbox. Die Browseradaption ist weltweit bei 94% und sogar in 99% der Browser unserer User vorhanden.

Die oben beschriebene Teilung in .pt-moderncard__main und .pt-moderncard__meta ermöglicht jetzt die Teilung in die zwei visuellen Spalten mittels:

.pt-moderncard {
    display: flex;
}

Die Eigenschaft align-items hat defaultmäßig den Wert stretch, und die flex-direction hat den Standardwert row.

Wir bekommen also zwei nebeneinander platzierte Kindelemente, die ihre Höhe einander anpassen. Außerdem erhalten diese beiden jeweils flex-basis: 50%, damit sie sich den Bereich 1:1 in der Breite teilen.

Als nächstes wird .pt-moderncard__main auch zur Flexbox, mit Ausrichtung als Spalte, um dann mittels justify-content: space-between; den Abstand zwischen .pt-moderncard__body und .pt-moderncard__footer zu erreichen.

.pt-moderncard__main {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

Skalierung des Bildes

Die Card-Elemente werden sich responsiv verhalten, das heißt: die Breite ist nicht fest, sondern werden vom nächsthöheren Element, das eine Breite vorgibt, skaliert.

Das kann die gesamte zur Verfügung stehende Browserbreite sein (mobile), oder auch ein Grid-System, das mehrere Cards wie Kacheln platziert.

Deshalb sind auch die exakten Maße des Bildes unbekannt, diese kann und sollte man CSS seitig also nicht angeben.

Es ist damit zu rechnen, dass ein Content-Redakteur zu schmale, sehr hohe oder sehr breite, flache Bilder hochladen kann (und wird).
Um den Look solcher potenziell unterschiedlich skalierter Bilder zu vereinheitlichen, muss ich also sichergehen, dass das Bild immer die Hälfte der Breite einnimmt, und nirgendwo übersteht oder Freiraum drumherum entsteht.

Die Breite wurde bereits durch .pt-moderncard__meta (50% der Kartenbreite) vorgegeben, also soll das Bild selbst, 100% dessen einnehmen.
Außerdem soll es immer die gesamte Höhe einnehmen.

Angenommen es würde sich um ein zu schmales Bild handeln, dass man auf die volle Breite forciert, würde es dem Standardverhalten des Browsers nach in der Breite gestreckt und damit visuell verzerrt werden. Ein zu breites oder zu hohes Bild würde geschrumpft.

Um dem vorzubeugen, bietet CSS3 die Methode object-fit.
Der Wert cover dafür sorgt, dass beim Skalieren des Bild das Größenverhältnis beibehalten wird, und dann noch überstehende Teile, an den Grenzen der Box enden.

Zusammen ergibt das also folgendes Ruleset:

.pt-moderncard__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Abschließende Maßnahmen

Um das wesentliche Layout abszuschließen, muss noch die Liste der Informationen im Footer etwas angepasst werden. Die Browserdefault-Style der Liste erhalten ein "Reset", das heißt Abstände und Bullets werden entfernt.

Außerdem wird das SVG auf die passende Größe zum Text skaliert.

.pt-moderncard__list {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

.pt-moderncard__icon {
  width: 20px;
  height: 13px;
}

Das Resultat sieht dann bis hierher so aus:

Card Element

Die Struktur, die durch die Vorlage gefordert ist, ist bereits klar erkennbar, und das in jeweils effektiv 40 Zeilen HTML und CSS. 😎

Der "Design"-Part, also Schriften, Farben, Animation, usw. ist ein umfangreicherer Teil für sich, der bald in einem gesonderten Artikel behandelt wird.