Nächste Generation CSS: @container

Avatar of Una Kravets
von Una Kravets am

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

Chrome experimentiert mit @container, einer Eigenschaft innerhalb der Containment Level 3 Spezifikation der CSS Working Group, die von Miriam Suzanne von Oddbird und einer Gruppe von Ingenieuren der gesamten Web-Plattform vorangetrieben wird. @container gibt uns die Fähigkeit, Elemente basierend auf der Größe ihres Elternelements zu stylen.

Die @container API ist nicht stabil und kann sich in der Syntax ändern. Wenn Sie sie selbst ausprobieren, können Sie auf einige Fehler stoßen. Bitte melden Sie diese Fehler an die entsprechende Browser-Engine!

Fehler: Chrome | Firefox | Safari

Sie können sich diese wie eine Media Query (@media) vorstellen, aber anstatt sich auf das Viewport zu verlassen, um Styles anzupassen, kann das Elternelement des von Ihnen angesprochenen Elements diese Styles anpassen.

Container Queries werden die größte Veränderung im Web-Styling seit CSS3 sein und unsere Perspektive auf „Responsive Design“ verändern.

Der Viewport und der User-Agent werden nicht mehr die einzigen Ziele sein, auf die wir uns verlassen können, um Responsive Layout- und UI-Styles zu erstellen. Mit Container Queries können Elemente ihre eigenen Eltern ansprechen und ihre eigenen Styles entsprechend anwenden. Das bedeutet, dass dasselbe Element, das sich in der Seitenleiste, im Hauptteil oder im Hero-Bereich befindet, je nach verfügbarer Größe und Dynamik völlig unterschiedlich aussehen kann.

@container in Aktion

In diesem Beispiel verwende ich zwei Karten innerhalb eines Elternelements mit folgendem Markup

<div class="card-container">
  <div class="card">
    <figure> ... </figure>
    <div>
      <div class="meta">
        <h2>...</h2>
        <span class="time">...</span>
      </div>
      <div class="notes">
        <p class="desc">...</p>
        <div class="links">...</div>
      </div>
      <button>...</button>
    </div>
  </div>
</div>

Anschließend setze ich die Containment (die container-type Eigenschaft) für das Elternelement, auf dem ich die Container-Styles abfragen werde (.card-container). Ich setze auch ein relatives Grid-Layout auf das Elternelement von .card-container, sodass sich dessen inline-size basierend auf diesem Grid ändert. Dies frage ich mit @container ab.

.card-container {
  container-type: inline-size;
  width: 100%;
}

Jetzt kann ich Container-Styles abfragen, um Styles anzupassen! Dies ist sehr ähnlich dazu, wie Sie Styles mit breitenbasierten Media Queries einstellen würden, wobei max-width verwendet wird, um Styles festzulegen, wenn ein Element kleiner als eine bestimmte Größe ist, und min-width, wenn es größer ist.

/* when the parent container is smaller than 850px, 
remove the .links div and decrease the font size on 
the episode time marker */

@container (max-width: 850px) {
  .links {
    display: none;
  }

  .time {
    font-size: 1.25rem;
  }

  /* ... */
}

/* when the parent container is smaller than 650px, 
decrease the .card element's grid gap to 1rem */

@container (max-width: 650px) {
  .card {
    gap: 1rem;
  }

  /* ... */
}

Container Queries + Media Queries

Eines der besten Features von Container Queries ist die Möglichkeit, Mikrolayouts von Makrolayouts zu trennen. Sie können einzelne Elemente mit Container Queries stylen und so nuancierte Mikrolayouts erstellen, und ganze Seitenlayouts mit Media Queries stylen, dem Makrolayout. Dies schafft eine neue Ebene der Kontrolle, die noch responsivere Interfaces ermöglicht.

Hier ist ein weiteres Beispiel, das die Stärke der Verwendung von Media Queries für Makrolayouts (d.h. der Kalender geht von Einzelpanel zu Mehrpanel) und Mikrolayouts (d.h. das Layout/die Größe des Datums und die Ränder/die Größe des Events verschieben sich) zeigt, um ein wunderschönes Zusammenspiel von Queries zu schaffen.

Container Queries + CSS Grid

Eine meiner persönlichen Lieblingsmethoden, um die Auswirkungen von Container Queries zu sehen, ist zu beobachten, wie sie innerhalb eines Grids funktionieren. Betrachten Sie das folgende Beispiel einer Pflanzenhandels-UI

Auf dieser Website werden überhaupt keine Media Queries verwendet. Stattdessen verwenden wir nur Container Queries zusammen mit CSS Grid, um die Shopping-Card-Komponente in verschiedenen Ansichten anzuzeigen.

Im Produkt-Grid wird das Layout mit grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); erstellt. Dies erzeugt ein Layout, das den Karten sagt, dass sie den verfügbaren Bruchteil der Fläche einnehmen sollen, bis sie eine Größe von 230px erreichen, und dann zur nächsten Zeile fließen sollen. Schauen Sie sich weitere Grid-Tricks auf 1linelayouts.com an.

Dann haben wir eine Container Query, die die Karten so stylt, dass sie ein vertikales Blocklayout annehmen, wenn sie weniger als 350px breit sind, und zu einem horizontalen Inline-Layout wechseln, indem sie display: flex anwenden (was standardmäßig einen Inline-Flow hat).

@container (min-width: 350px) {
  .product-container {
    padding: 0.5rem 0 0;
    display: flex;
  }

  /* ... */
}

Das bedeutet, dass jede Karte ihr eigenes responsives Styling besitzt. Dies ist ein weiteres Beispiel dafür, wie Sie ein Makrolayout mit dem Produkt-Grid und ein Mikrolayout mit den Produktkarten erstellen können. Ziemlich cool!

Verwendung

Um @container verwenden zu können, müssen Sie zuerst ein Elternelement erstellen, das Containment hat. Dazu müssen Sie contain: layout inline-size auf dem Elternelement setzen. Sie können inline-size verwenden, da wir Container Queries derzeit nur auf der Inline-Achse anwenden können. Dies verhindert, dass Ihr Layout in Blockrichtung bricht.

Das Setzen von contain: layout inline-size erstellt einen neuen Containing Block und einen neuen Block Formatting Context, wodurch der Browser ihn vom Rest des Layouts trennt. Jetzt können wir abfragen!

Einschränkungen

Derzeit können Sie keine höhenbasierten Container Queries verwenden, nur die Blockachse. Damit Grid-Kinder mit @container funktionieren, müssen Sie ein Wrapper-Element hinzufügen. Trotzdem können Sie mit dem Hinzufügen eines Wrappers die gewünschten Effekte erzielen.

Probieren Sie es aus

Sie können heute mit der @container Eigenschaft in Chromium experimentieren, indem Sie in Chrome Canary zu: chrome://flags navigieren und das Flag #experimental-container-queries aktivieren.