Bei unserem Lean Coffee zum Thema CSS blieben aus zeitlichen Gründen einige Fragen unbeantwortet. Wir haben sie für euch zusammengetragen und von unseren Expert:innen beantworten lassen.
Wie kann ich (Breakpoint-) Werte als Variablen sowohl für CSS als auch für JavaScript definieren?
In einem Projekt haben wir dafür einen Webpack-Loader geschrieben, der die Variablen aus einer Less-Datei extrahiert und in ein JavaScript-Modul konvertiert. Dieses Modul kann dann im JavaScript verwendet werden. Dieser Ansatz lohnt sich, wenn es häufig Änderungen an den Variablen gibt oder oft neue hinzukommen. Leider haben wir den Loader bisher nicht als npm-Paket veröffentlicht, im Prinzip besteht er aber nur aus ein paar Zeilen Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
const symbolsParser = require('less-symbols-parser'); module.exports = function lessToJSONLoader(source) { // this does all the magic const symbols = symbolsParser.parseSymbols(source); // remove the @ from the variable name const variables = symbols.variables.map(({ name, value }) => ({ name: name.substring(1), value })); return `export default ${JSON.stringify(variables)}`; }; |
In Sass gibt es die Möglichkeit, Variablen zu exportieren, die dann über einen Webpack-Loader im JavaScript-Code zur Verfügung gestellt werden. Ein Artikel bei CSS Tricks beschreibt, wie es geht. In diesem Artikel wird auch beschrieben, wie CSS-Variablen per JavaScript ausgelesen werden können.
Bei kleineren Projekten oder nur wenigen Variablen (und einem disziplinierten Team) ist ein einfacherer Weg möglich: Eine Less/Sass-Datei und eine JavaScript-Datei, in denen jeweils die Variablen (dupliziert) enthalten sind, mit jeweils einem Kommentar der Art:
1 2 3 |
// These variables are also used in variables.js. // Whenever you change a value here change it there as well. |
Wann setze ich Flex ein und wann Grid?
Wenn man noch den Internet Explorer voll unterstützen muss, dann Flex. Der IE unterstützt zwar eine alte Version von Grids, die aber so viel weniger kann als was moderne Browser können.
Ansonsten gibt es zwei wichtige Unterschiede zwischen Flex und Grid:
- Flex ist eindimensional, Grid zweidimensional. Gerade wenn es darum geht, Elemente über mehrere Spalten zu strecken, kommt man mit Flex nicht mehr aus.
- Flex ist content-first, Grid ist space-first. Bei Flex geht es darum, Elemente zu layouten und mit übrigem Raum umzugehen (z.B. Abstand zwischen den Elementen, manche Elemente wachsen lassen). Bei Grid geht es darum, den zur Verfügung stehenden Raum aufzuteilen und dann die Elemente darin zu platzieren.
Im Grunde sollte man beide Konzepte kennen und beherrschen, um dann anhand der Designvorgaben zu überlegen, welches Konzept sinnvoller ist. Zum Erlernen der Grundlagen empfehle ich Flexbox Froggy und CSS Grid Garden oder – weniger spielerisch – Grid by Example.
Ist eine Kombination aus Component-CSS-Module und globalem index.css sinnvoll?
Ich glaube, es geht gar nicht anders. Natürlich wollen wir CSS komponentenbasiert entwickeln, um die Wartbarkeit zu erhöhen, aber irgendwie müssen diese Komponenten ja zu einer Webseite zusammengesetzt werden. Und dafür brauchen wir globales CSS.
Aber in diesem globalen CSS sollen keine Dinge gestylt werden, die zu einer Komponente gehören. Was hinein kann sind Regeln wie * { box-sizing: border-box; } oder CSS-Resets oder auch Schriftartendefinitionen. Schriftarten sollten ja nur einmal pro Dokument definiert und geladen werden, die Komponenten können dann diese Werte erben.
Was macht position: absolute genau?
Spannende Frage. Kurze Antwort: Selbst nachlesen. Die lange Antwort ist einen eigenen Blog-Eintrag wert. Vielleicht schreibe ich den mal.
Wie ermittle ich, welche Browser von Nutzer:innen verwendet werden, um CanIUse nutzen zu können und unnötige Fallbacks zu vermeiden? (vielleicht off-topic?)
Ja, ist etwas off-topic. Can I Use gibt zu jedem Feature an, wie viel Prozent der verwendeten Browser dieses Feature unterstützen. Dabei werden die globalen Daten von StatCounter verwendet. Man kann über die Settings auch die Daten eines einzelnen Landes auswählen, zum Beispiel „Germany“.
Wenn diese Werte noch zu ungenau sind, sollten aus den eigenen Serverlogs die tatsächlichen Browser der eigenen Nutzer:innen ermittelt werden.
Brauche ich in Angular-Komponenten noch BEM?
BEM ist ein Konzept für die Benennung und Struktur von Klassen, um wartbares CSS zu schreiben. Als dieses Konzept vor ungefähr zehn Jahren Verbreitung gefunden hat, traf es einen Nerv, weil dadurch auf einen Schlag viele Probleme von CSS gelöst wurden, unter anderem die Selektorhölle, die Gefahr unerwarteter Nebeneffekte und die Spezifität.
Im Kontext von Komponenten sorgt die Anwendung von BEM dafür, dass nur die Elemente gestylt werden, die man stylen will – es gibt keine Auswirkungen auf Kindkomponenten und keine Auswirkungen von außen auf eine Komponente.
Genau dieses Scoping liefert Angular direkt mit. Auch dort wirkt sich das CSS einer Komponente nicht auf Kindkomponenten aus. Die Frage ist also, ob die Klassennamen innerhalb einer Angular-Komponente nach BEM-Schema benannt werden sollten. Ich tendiere dazu, es nicht zu tun. Statt button__icon als Klassennamen des Icons in der Button-Komponente kann ich in Angular den Klassennamen icon benutzen, ohne dass etwas verloren geht. Modifier-Klassennamen wie button--primary würde ich nicht einfach durch primary ersetzen, weil dann verloren geht, dass es sich hierbei um einen Modifier handelt und nicht um ein Element. Für Modifier würde ich ein has- oder is-Präfix wählen: is-primary .
Wenn eine Komponente so komplex ist, dass man darüber nachdenkt, ob sich innerhalb nicht doch BEM lohnt, ist das ein Indikator dafür, eine eigene Komponente zu extrahieren.
Welche CSS-Selektoren soll ich am besten verwenden (Prio)? Vielleicht im Zusammenhang mit Angular.
Nie auf IDs stylen: #content. Die Spezifität einer ID ist so hoch, dass es schwierig wird, diese Styles gegebenenfalls zu überschreiben. Im Zweifelsfall kann man dem Element einen Klassennamen mit der ID geben, über den man dann stylt: .content .
Auf Elementnamen nur für die nötigsten Dinge, z.B. html oder body . Die Gefahr, über Elementnamen Elemente zu stylen, bei denen man es doch nicht möchte, ist ziemlich groß.
Das Ideal ist also, auf Klassennamen zu stylen, weil dann der Klassenname ganz gezielt nur auf die Elemente gesetzt werden kann, die gestylt werden sollen. Wenn der Selektor so kurz wie möglich gehalten wird, besteht auch weniger die Gefahr, versehentlich Elemente in anderen Kontexten mitzustylen.
Manchmal möchte man auch auf Attribut-Selektoren stylen, z.B. [type="email"] . Das kann man machen, aber es besteht wieder die Gefahr, Elemente zu stylen, die man vielleicht nicht stylen wollte. Deswegen empfehle ich, Attribut-Selektoren immer in Kombination mit einem Klassennamen zu verwenden.
Im Kontext von Angular ist es durch das Scoping möglich, direkt auf Elementnamen zu stylen, aber nicht immer sinnvoll. Mir hat das vor kurzem Probleme bereitet, als ich in eine Angular-Komponente, in der ich das einzige SVG-Icon direkt über den Elementnamen gestylt hatte, zwei weitere Icons eingefügt habe, die andere Styles brauchten. Darum bin ich auch in Angular dazu übergegangen, alles über Klassennamen zu stylen.
Kann ich CSS-Variablen schon in der Praxis einsetzen? Gibt es Fallbacks für alte Browser?
Ja, man kann CSS-Variablen in der Praxis einsetzen – wenn man den Internet Explorer nicht voll unterstützen muss. Einen Fallback gibt es leider nicht. CSS-Variablen ermöglichen Dinge, die früher nicht gingen – auch nicht mit Less- oder Sass-Variablen. Man kann es auch nur in einfachen Fällen durch JavaScript nachbauen.
Wenn man CSS-Variablen verwenden möchte, muss man sich davon verabschieden, dass die Website in allen/alten Browsern gleich aussieht. Das sollte sie aber auch nicht müssen. Wichtig ist, dass die Nutzer:innen die Webseite grundlegend nutzen können – aber sie muss nicht überall gleich aussehen.
So sollte man mit semantischem HTML beginnen, dann mit CSS-Basis-Styles wie Typografie, Abstände und Farben ergänzen. Danach kann man dann anhand der Browserfähigkeiten mit weiterem CSS oder JavaScript die Seite verschönern oder nutzungsfreundlicher gestalten. Dieser Ansatz entspricht den Konzepten von Progressive Enhancement und Resilient Web Design. Zum Weiterlesen kann ich das Buch Resilient Web Design von Jeremy Keith sehr empfehlen.
Ich habe hier ein Design, wie setze ich das am besten um?
Ohne das konkrete Design kann es nur eine unkonkrete Antwort geben:
- Mit semantischem HTML beginnen. Welches Markup ist das richtige, wenn es kein CSS und kein JavaScript gäbe?
- Dann CSS ergänzen, und zwar Mobile first. Als erstes die Seite für z.B. eine Breite von 320 Pixeln umsetzen, dann für die nächstgrößere Breite usw.
- Zuletzt mit JavaScript die User-Experience verbessern.
Wenn man eine Single Page Application hat, die zum Beispiel mit Angular oder React im Browser gerendert wird, hat man natürlich von Anfang an JavaScript zur Verfügung und kann das auch nutzen. Trotzdem ist es richtig, mit semantischem HTML zu beginnen. Dadurch hat man die Grundlage für Accessibility geschaffen.
(Wie) kann man von außen Elemente in einem Shadow-DOM stylen?
Wenn die Web-Component das nicht ermöglicht: gar nicht – das ist ja das Konzept des Shadow-DOM: Eine Komponente zu haben, die abgekapselt vom Äußeren ist. Es gibt aber zwei Wege, wie die Web-Component ein Stylen von außen erlauben kann:
- Sie verwendet intern CSS-Variablen, die von außen gesetzt werden können.
- Sie gibt intern einzelne Elemente über das part-Attribut frei. Diese Elemente können dann über das ::part()-Pseudoelement gestylt werden. Mehr dazu bei MDN oder CSS Tricks.
Viele HTML-Element werden in Browsern über den Shadow-DOM abgebildet, zum Beispiel <meter> . Oft ermöglichen die Browser, die Elemente innerhalb des Shadow-DOMs über nicht-standardisierte Pseudoelemente zu stylen, z.B. ::-webkit-meter-bar.
Less oder Sass? Oder Styled-Components?
Less und Sass sind zwei Erweiterungen von CSS, mit denen man Dinge machen kann, die mit CSS nicht direkt möglich sind (oder waren): Modularität, Funktionen, Code-Generierung und mehr. Ob man Less oder Sass verwendet, ist Geschmackssache, beide haben einen ähnlichen Feature-Umfang. Sass scheint insgesamt beliebter zu sein, ich bevorzuge aber Less (nur deshalb, weil Less in JavaScript geschrieben wurde und ich im ersten Projekt, in dem Sass verwendet wurde, Kompilierfehler hatte – das hatte ich bei Less noch nie).
Styled-Components bieten eine Möglichkeit, in React CSS im JavaScript zu schreiben. In React/JSX wird ja eh Logik (JavaScript) und Markup (JSX) in einer Datei geschrieben, weshalb manche Entwickler:innen auch das Styling dort haben wollen.
Als ich vor drei Jahren Styled-Components evaluiert habe, war die Unterstützung in IDEs noch sehr schwach: fehlende Code Completion, fehlendes Syntax Highlighting, fehlendes Syntax Checking. Darum haben wir in dem Projekt Less verwendet. Inzwischen ist die IDE-Unterstützung wohl besser – aber in meinem aktuellen Projekt verwenden wir Angular, deswegen habe ich es noch nicht ausprobiert. Das Konzept von Angular, Logik, Markup und Styles in separaten Dateien zu haben, gefällt mir persönlich ziemlich gut – auch wenn JSX schon auch schick ist.
Wie geht Resize von SVG-Grafik in Flex-Grid?
So! Die Umsetzung entspricht nicht ganz dem, was gewünscht war, ist aber sehr nah dran. Ich habe drei Dinge geändert:
- Beim #graphics-Element habe ich overflow: hidden gesetzt. Dadurch wird die Höhe nicht mehr durch das SVG beeinflusst.
- Beim SVG habe ich height: 100%; width: 100%; gesetzt. Dadurch füllt das SVG-Element das #graphics-Element vollkommen aus (das ist der Punkt, in dem meine Lösung von der Anforderung abweicht).
- Dadurch entsteht aber das Problem, dass das Seitenverhältnis des SVG-Elements nicht mehr dem der Viewbox entspricht (außer zufällig). Um jetzt die Viewbox innerhalb des SVG-Elements zu platzieren, habe ich beim SVG das preserveAspectRatio-Attribut gesetzt. Mit dem Wert xMinYMin wird die Viewbox oben links ausgerichtet.
Eine Anforderung war, dass das SVG-Element selbst im richtigen Seitenverhältnis angezeigt wird und der dunkelgraue Hintergrund des #graphics-Elements sichtbar wird. Das ist leider nicht möglich – kann aber simuliert werden, indem im SVG ein rect-Element mit der Größe der Viewbox ergänzt wird und die Hintergrundfarbe aus dem CSS entfernt.
Es ist deswegen nicht möglich, weil man in CSS das Seitenverhältnis nicht direkt angeben kann. Man kann mit einem Hack die Höhe in Abhängigkeit der Breite setzen, aber nicht die Breite in Abhängigkeit der Höhe, was ja aber bei schmalen, hohen Bildschirmen deine Anforderung war.
Was ist dein Lieblings-CSS-Farbname? (Warum ist hotpink gerade so im Trend?)
Hotpink. Es gibt über 200 definierte Farbnamen in CSS, darunter sehr obskure (schnell: Welcher der folgenden Namen ist kein CSS-Farbname: goldenrod, peru, powderblue oder lavenderblush?). Ich verwende diese Farbnamen nie in Projekten, sondern nur in Code-Beispielen. Dafür habe ich mir ein paar Farbnamen gemerkt – vielmehr merken wollen. Bis auf Hotpink vergesse ich sie aber immer wieder. Meine Lieblingsfarbe ist übrigens #ffbb00, aber dafür gibt es keinen Farbnamen.
Wie stehst du dazu, ob man heute für jedes Layout immer flex verwenden sollte? Ich erlebe unterschiedliche Philosophien in meinem Team. Ich persönliche implementiere viele Spalten/Zeilen-Layouts noch mit display: block, width, position etc …
Mit Flexbox sind Dinge möglich, die man mit display: block nicht hinbekommt. Von daher sollte man schon Flexbox beherrschen. Das bedeutet aber nicht, dass man nun alles mit Flexbox umsetzen sollte. Letzte Woche habe ich ein Layout mit Floats umgesetzt, weil das einfacher war als mit Flexbox.
Übrigens muss man nicht bei Flexbox stehenbleiben. Mit Grids sind noch viel flexiblere Layouts möglich. Zum Erlernen der Grundlagen empfehle ich Flexbox Froggy und CSS Grid Garden oder – weniger spielerisch – Grid by Example.
Spitze
Danke dir, Thomas! Es freut uns, dass dir der Artikel gefällt.