Wie man eine responsive Card Komponente ohne Media Queries erstellt 

Avatar of Geoffrey Crofte
Geoffrey Crofte am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Spaßfakt: Es ist möglich, responsive Komponenten komplett ohne Media Queries zu erstellen. Sicherlich wären Container Queries sehr nützlich für Responsive Design auf Komponentenebene. Aber die haben wir nicht. Dennoch können wir, ob mit oder ohne Container Queries, Dinge tun, um unsere Komponenten überraschend responsiv zu gestalten. Wir werden Konzepte aus Intrinsic Web Design verwenden, präsentiert von Jen Simmons.

Tauchen wir gemeinsam in den unten beschriebenen Anwendungsfall ein, die Lösungen im Hinblick auf den aktuellen Stand von CSS und einige weitere Tricks, die ich Ihnen geben werde.

Eine responsive „Kochrezept“-Karte

Ich habe kürzlich ein Video und einen Pen von einer responsiven Card-Demo getwittert, die ich am Beispiel eines Pizzarezepts erstellt habe. (Für die Technologie hier nicht wichtig, aber ich habe das Rezept am Ende abgeladen, weil es köstlich und glutenfrei ist.)

Die Demo hier war ein erster Versuch, basierend auf einem Konzept aus einem der Vorträge von Stéphanie Walter. Hier ist ein Video, das Ihnen zeigt, wie die Karte funktionieren wird

Und wenn Sie jetzt damit spielen möchten, hier ist der Pen.

Lassen Sie uns das responsive Layout definieren

Ein Schlüssel zur Planung ist das Wissen um die tatsächlichen Inhalte, mit denen Sie arbeiten, und die Bedeutung dieser Details. Nicht, dass wir Inhalte zu irgendeinem Zeitpunkt verstecken sollten, aber aus Layout- und Designgründen ist es gut zu wissen, was zuerst kommuniziert werden muss und so weiter. Wir werden dieselben Inhalte unabhängig von der Größe oder Form des Layouts anzeigen.

Stellen wir uns die Inhalte mit einer Mobile-First-Mentalität vor, um uns auf das Wichtigste zu konzentrieren. Wenn der Bildschirm dann größer wird, wie auf einem Desktop, können wir den zusätzlichen Platz für Dinge wie * gloriosen * Weißraum und größere Typografie nutzen. Normalerweise reicht eine solche Priorisierung aus, um sicherzustellen, welche Inhalte für die Karten bei allen und jedem Viewport-Größen benötigt werden.

Nehmen wir das Beispiel eines Kochrezept-Teasers

In ihrem Vortrag hatte Stéphanie die Arbeit bereits erledigt und die Inhalte priorisiert für unsere Karten. Hier ist, was sie in der Reihenfolge der Wichtigkeit skizziert hat:

  1. Bild: Weil es ein Rezept ist, isst man mit den Augen!
  2. Titel: Um sicherzugehen, was Sie kochen werden.
  3. Schlüsselwörter: Um wichtige Informationen auf den ersten Blick zu erfassen.
  4. Bewertungsinformationen: Für sozialen Beweis.
  5. Kurze Beschreibung: Für die Leute, die lesen.
  6. Call to Action: Was Sie erwarten, dass der Benutzer mit dieser Karte macht.

Das mag nach viel klingen, aber wir können all das in ein einziges intelligentes Kartenlayout packen!

Nicht skalierbare Typografie

Eine der Einschränkungen der Technik, die ich Ihnen zeigen werde, ist, dass Sie keine skalierbare Typografie basierend auf der Containerbreite erhalten. Skalierbare Typografie (z. B. „fluid type“) wird üblicherweise mit der Viewport-Breite (vw) Einheit gemacht, die auf dem Viewport basiert, nicht auf dem Elternelement.

Während wir also versucht sein könnten, Fluid-Typografie als nicht-media-query-basierte Lösung für den Inhalt unserer Karten zu verwenden, können wir Fluid-Typografie leider nicht auf Basis eines Prozentsatzes der Containerbreite oder der Elementbreite selbst verwenden. Das wird uns jedoch nicht von unserem Ziel abhalten!

Ein kurzer Hinweis zur „Pixelgenauigkeit“

Sprechen wir beide Seiten an…

Designer: Pixelgenauigkeit ist super ideal, und wir können sicherlich auf Komponentenebene präzise sein. Aber auf Layout-Ebene muss es einen Kompromiss geben. Das bedeutet, Sie müssen einige Variationen bereitstellen, aber die Zwischenzustände flexibel lassen. Dinge verschieben sich in responsiven Layouts und Präzision bei jeder möglichen Bildschirmbreite ist eine schwierige Anforderung. Wir können aber trotzdem dafür sorgen, dass die Dinge in jeder Skalierung gut aussehen!

Entwickler: Sie müssen in der Lage sein, die Lücken zwischen den Layouts zu füllen, für die vorgegebene Designs existieren, damit die Inhalte zwischen diesen Zuständen lesbar und konsistent sind. Als gute Praxis empfehle ich auch, so viel wie möglich einen natürlichen Fluss beizubehalten.

Sie können auch den hervorragenden Artikel von Ahmad über den Zustand der Pixelgenauigkeit lesen.

Ein Rezept für null Media Queries

Denken Sie daran, dass wir nicht nur eine responsive Karte anstreben, sondern eine, die keine Media Queries benötigt. Es ist nicht so, dass Media Queries vermieden werden sollten; es geht vielmehr darum, dass CSS mächtig und flexibel genug ist, um uns auch andere Optionen zur Verfügung zu stellen.

Um unsere responsive Karte zu erstellen, fragte ich mich, ob Flexbox ausreichen würde oder ob ich es stattdessen mit CSS Grid machen müsste. Es stellt sich heraus, dass Flexbox diesmal tatsächlich ausreicht, indem wir das Verhalten und die Magie der Eigenschaften flex-wrap und flex-basis in CSS nutzen.

Der Kern von flex-wrap ist, dass es Elementen erlaubt, auf eine neue Zeile zu springen, wenn der Platz für Inhalte zu knapp wird. Sie können den Unterschied zwischen Flex ohne Zeilenumbruch und mit Zeilenumbruch in dieser Demo sehen.

Der flex-basis-Wert von 200px ist mehr eine Anweisung als ein Vorschlag für den Browser, aber wenn der Container nicht genug Platz dafür bietet, rutschen die Elemente nach unten in eine neue Zeile. Der Abstand zwischen den Spalten erzwingt sogar den anfänglichen Zeilenumbruch.

Ich habe diese Umbruchlogik verwendet, um die Basis meiner Karte zu erstellen. Adam Argyle hat sie auch in der folgenden Demo verwendet, die vier Formularlayouts mit nur 10 Zeilen CSS zeigt.

In seinem Beispiel verwendet Adam flex-basis und flex-grow (gemeinsam in der Kurzform flex-Eigenschaft) ), um dem E-Mail-Eingabefeld zu erlauben, dreimal so viel Platz einzunehmen wie das Namensfeld oder der Button. Wenn der Browser abschätzt, dass nicht genug Platz vorhanden ist, um alles in derselben Zeile anzuzeigen, bricht das Layout von selbst in mehrere Zeilen um, ohne dass wir die Änderungen mit Media Queries verwalten müssen.

Ich habe auch die clamp() Funktion verwendet, um noch mehr Flexibilität hinzuzufügen. Diese Funktion ist sozusagen magisch. Sie erlaubt uns, eine min()- und eine max()-Berechnung in einer einzigen Funktion zu lösen. Die Syntax lautet:

clamp(MIN, VALUE, MAX)

Es ist, als würde man eine Kombination aus den Funktionen max() und min() lösen.

max(MIN, min(VAL, MAX))

Sie können sie für alle Arten von Eigenschaften verwenden, die Folgendes abdecken:  <length>, <frequency>, <angle>, <time>, <percentage>, <number> oder <integer>.

Die „No-Media Query Responsive Card“-Demo

Mit all diesen neuartigen CSS-Kräften habe ich eine flexible responsive Karte ohne Media Queries erstellt. Es ist vielleicht am besten, diese Demo in einem neuen Tab anzuzeigen oder mit einer 0,5-fachen Option in der eingebetteten Version unten.

Etwas, das Sie sofort bemerken möchten, ist, dass der HTML-Code für die 2 Karten genau derselbe ist; der einzige Unterschied ist, dass die erste Karte in einem 65 % breiten Container und die zweite in einem 35 % breiten Container liegt. Sie können auch die Abmessungen Ihres Fensters anpassen, um die Responsivität zu testen.

Der wichtige Teil des Codes in dieser Demo befindet sich bei diesen Selektoren

  • .recipe ist der übergeordnete Flex-Container.
  • .pizza-box ist ein Flex-Item, das der Container für das Kartenbild ist.
  • .recipe-content ist ein zweites Flex-Item und der Container für den Karteninhalt. 

Jetzt, da wir wissen, wie flex-wrap funktioniert und wie flex-basis und flex-grow die Elementgröße beeinflussen, müssen wir nur noch kurz die clamp()-Funktion erklären, da ich sie für die responsive Schriftgrößenanpassung anstelle von Fluid-Typografie verwendet habe.

Ich wollte calc() und benutzerdefinierte Eigenschaften verwenden, um Schriftgrößen basierend auf der Breite des übergeordneten Containers zu berechnen, aber ich konnte keinen Weg finden, da ein 100%-Wert je nach Kontext unterschiedlich interpretiert wird. Ich habe ihn für den mittleren Wert meiner clamp()-Funktion beibehalten, aber das Endergebnis war überdimensioniert und funktionierte nicht wie erhofft oder erwartet.

/* No need, really */
font-size: clamp(1.4em, calc(.5em * 2.1vw), 2.1em);

Hier bin ich stattdessen gelandet

font-size: clamp(1.4em, 2.1vw, 2.1em);

Das habe ich getan, um die Größe des Kartentitels an die Bildschirmgröße anzupassen, aber wie wir bereits weiter oben beim Thema Fluid-Typografie besprochen haben, werden wir den Text nicht nach der Breite des übergeordneten Containers skalieren können.

Stattdessen sagen wir mit dieser einen Zeile CSS im Grunde genommen:

Ich möchte, dass die font-size 2,1vw (2,1% der Viewport-Breite) entspricht, aber bitte lassen Sie sie nicht unter 1,4em oder über 2,1em gehen.

Dies bewahrt die priorisierte Bedeutung des Titels, indem er größer als der Rest des Inhalts bleibt, aber dennoch lesbar ist. Und er wächst und schrumpft mit der Bildschirmgröße!

Und vergessen wir nicht die responsiven Bilder. Die Inhaltsanforderungen besagen, dass das Bild das wichtigste Element ist, also müssen wir es definitiv berücksichtigen und sicherstellen, dass es in allen Bildschirmgrößen gut aussieht. Nun, Sie möchten vielleicht so etwas tun und es dabei belassen.

max-width: 100%;
height: auto;

Aber das führt nicht immer zur besten Darstellung eines Bildes. Stattdessen haben wir die object-fit-Eigenschaft, die nicht nur auf die Höhe und Breite der Content-Box des Bildes reagiert, sondern es uns auch erlaubt, das Bild zuzuschneiden und zu steuern, wie es in der Box gestreckt wird, wenn es mit der object-position-Eigenschaft verwendet wird.

img {
  max-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  object-fit: cover;
  object-position: 50% 50%;
}

Wie Sie sehen, ist das eine Menge von Eigenschaften aufzulisten. Dies ist zwingend erforderlich wegen der expliziten Breiten- und Höhenangaben im HTML-<img>-Code. Wenn Sie den HTML-Teil entfernen (was ich aus Performance-Gründen nicht empfehle), können Sie die object-*-Eigenschaften in CSS belassen und die anderen entfernen.

Ein alternatives Rezept für keine Media Queries

Eine weitere Technik ist die Verwendung von flex-grow als einheitlichen Wachstumsfaktor mit einem absurd riesigen Wert für flex-basis. Die Idee ist direkt aus Heydon Pickerings großartiger „Holy Albatross“-Demo gestohlen.

Der interessante Teil des Codes ist dieser:

/* Container */
.recipe {
  --modifier: calc(70ch - 100%);


  display: flex;
  flex-wrap: wrap;
}


/* Image dimension */
.pizza-box {
  flex-grow: 3;
  flex-shrink: 1;
  flex-basis: calc(var(--modifier) * 999);
}


/* Text content dimension */
.recipe-content {
  flex-grow: 4;
  flex-shrink: 1;
  flex-basis: calc(var(--modifier) * 999);
}

Proportionale Abmessungen werden durch flex-grow erzeugt, während die flex-basis-Abmessung entweder ungültig oder extrem hoch sein kann. Der Wert wird extrem hoch, wenn calc(70ch - 100%), der Wert von  --modifier, einen positiven Wert erreicht. Wenn die Werte extrem hoch sind, füllt jeder von ihnen den Raum und erzeugt ein Spaltenlayout; wenn die Werte ungültig sind, ordnen sie sich inline an.

Der Wert von 70ch wirkt wie der *Breakpoint* im Rezept-Komponente (fast wie eine Container Query). Ändern Sie ihn je nach Bedarf.

Zerlegen wir die Zutaten noch einmal

Hier sind die CSS-Zutaten, die wir für eine kartenlose Komponentenkomponente verwendet haben:

  • Die clamp()-Funktion hilft bei der Auflösung eines „bevorzugten“ im Gegensatz zu einem „minimalen“ oder „maximalen“ Wert.
  • Die Eigenschaft flex-basis mit einem negativen Wert bestimmt, wann das Layout in mehrere Zeilen umbricht.
  • Die Eigenschaft flex-grow wird als Einheitswert für proportionale Wachstumswerte verwendet.
  • Die vw-Einheit hilft bei responsiver Typografie.
  • Die  object-fit-Eigenschaft bietet feinere Responsivität für das Kartenbild, da sie es uns ermöglicht, die Abmessungen des Bildes zu ändern, ohne es zu verzerren.

Weiter geht's mit Mengenabfragen

Ich habe noch einen weiteren Trick für Sie: Wir können das Layout je nach *Anzahl* der Elemente im Container anpassen. Das ist keine echte Responsivität, die durch die Dimension eines Containers entsteht, sondern eher durch den Kontext, in dem der Inhalt liegt.

Es gibt keine *echte* Media Query für die Anzahl der Elemente. Es ist ein kleiner CSS-Trick, um die Anzahl der Elemente rückwärts zu zählen und Stiländerungen entsprechend anzuwenden.

Die Demo verwendet den folgenden Selektor

.container > :nth-last-child(n+3),
.container > :nth-last-child(n+3) ~ * {
  flex-direction: column;
}

Sieht schwierig aus, oder? Dieser Selektor erlaubt uns, Stile *vom* letzten Kind und all seinen Geschwistern aus anzuwenden. Nett! 

Una Kravets erklärt dieses Konzept sehr gut. Wir können diesen speziellen Anwendungsfall wie folgt übersetzen:

  • .container > :nth-last-child(n+3): Das dritte oder größere .container-Element *vom Ende* der .container-Gruppe.
  • .container > :nth-last-child(n+3) ~ *: Genau das Gleiche, aber wählt jedes .container-Element *nach* dem letzten aus. Dies hilft, andere Karten, die wir hinzufügen, zu berücksichtigen.

Kitty Giraudels „Selectors Explained“-Tool hilft wirklich, komplexe Selektoren in einfacher Sprache zu übersetzen, falls Sie eine weitere Übersetzung wünschen, wie diese Selektoren funktionieren.

Eine weitere Möglichkeit, „Mengen“-Container in CSS zu erhalten, ist die Verwendung von binären Bedingungen. Aber die Syntax ist nicht einfach und scheint etwas hacky. Sie können mich auf Twitter erreichen, wenn Sie über diese – oder andere Tricks und Tipps zu CSS oder Design – sprechen möchten. pastedGraphic.png

Ist das zukunftssicher?

Alle Techniken, die ich Ihnen hier vorgestellt habe, können heute in einer Produktionsumgebung eingesetzt werden. Sie werden gut unterstützt und bieten Möglichkeiten für graceful degradation.

Im schlimmsten Fall? Ein Browser, der etwas nicht unterstützt, wie z. B. Internet Explorer 9, wird das Layout nicht gemäß den von uns angegebenen Bedingungen ändern, aber der Inhalt wird trotzdem lesbar sein. Es ist also unterstützt, aber vielleicht nicht für das ideale Erlebnis „optimiert“.

Vielleicht werden wir eines Tages endlich den Heiligen Gral der Container Queries in Aktion erleben. Hoffentlich resonierten die Intrinsic Web Design-Muster, die wir hier verwendet haben, mit Ihnen und helfen Ihnen in der Zwischenzeit, flexible und „intrinsisch-responsive“ Komponenten zu bauen.

Kommen wir zum „wirklichen“ Grund für diesen Beitrag … der Pizza! 🍕


Glutenfreies Pfannenpizza-Rezept

Sie können die Beläge wählen. Das Wichtigste ist der Teig, und hier ist er:

Zutaten

  • 3¼ Tassen (455g) glutenfreies Mehl
  • 1 Esslöffel plus 1 Teelöffel (29g) brauner Zucker
  • 2 Teelöffel koscheres Salz
  • ½ Würfel Hefe
  • 2½ Tassen (400 ml) Vollmilch
  • 4 Esslöffel geschmolzene Margarine
  • 1 Esslöffel Maisstärke

Anleitung

  1. Alle trockenen Zutaten vermischen.
  2. Flüssigkeiten hinzufügen.
  3. 2 Stunden gehen lassen, bis sich die Masse verdoppelt hat. Ich empfehle, ein feuchtes Geschirrtuch über Ihre Schüssel mit dem Teig zu legen und die Schüssel in die Nähe eines heißen Bereichs zu stellen (aber nicht zu heiß, da wir ihn nicht sofort backen wollen).
  4. In die Pfanne mit Öl geben. Ca. 1 Stunde gehen lassen, bis sich die Masse verdoppelt hat.
  5. Im Ofen bei 250 Grad 20 Minuten backen.

Danke Stéphanie für das Rezept 😁