Balancieren auf einem Drehpunkt mit Flexbox

Avatar of Julian Merkenich
Julian Merkenich am

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

Ich zeige Ihnen eine Methode, die ich kürzlich entdeckt habe, um eine Reihe von Elementen um etwas zu zentrieren, das ich **den Drehpunkt** nenne. Ich verspreche Ihnen, dass seltsames HTML ausgeschlossen ist und Sie keine CSS-Kenntnisse auf dem neuesten Stand benötigen, um die Aufgabe zu erledigen.

Ich liebe Wortspiele, also habe ich kürzlich das Hauptmenü meiner Website als Anspielung auf Kreuzworträtsel neu gestaltet, mit meinem Namen als vertikalem Wort und den Hauptbereichen meiner Website als horizontale Wörter.

So sieht das Design mit den Namen einiger Farben statt der Wörter aus

Und hier ist ein Beispiel für das HTML, das dieses Rätsel antreibt

<div class="puzzle">
  <div class="word">
    <span class="letter">i</span>
    <span class="letter">n</span>
    <span class="letter">d</span>
    <span class="letter">i</span>
    <span class="letter pivot">g</span>
    <span class="letter">o</span>
  </div>
  <!-- MORE WORDS -->
</div>

In diesem Beispiel ist der Buchstabe g der Drehpunkt. Sehen Sie, dass er nicht in der Mitte ist? Das ist die Schönheit dieser Herausforderung.

Wir könnten jedem Wort einen Versatz mit hartcodiertem CSS oder Inline-Custom-Properties zuweisen und uns zurücklehnen. Es wäre sicherlich der offensichtlichste Weg, das Problem zu lösen, aber es gibt einen Nachteil – zusätzlich zur .pivot-Klasse müssten wir für jedes Wort einen Versatz angeben. Die Stimme in meinem Kopf sagt mir, dass dies unnötige Redundanz darstellt, weniger flexibel ist und zusätzlichen Ballast erfordert, den wir jedes Mal brauchen, wenn wir ein Wort hinzufügen oder ändern.

Lassen Sie uns stattdessen einen Schritt zurücktreten und sehen, wie das Rätsel ohne jegliches Ausbalancieren aussieht

Stellen Sie sich für einen Moment vor, wir verwenden display: none, um alle Buchstaben vor dem Drehpunkt auszublenden. Jetzt sehen wir nur noch die Drehpunkte und alles danach.

Ohne weitere Änderungen wären unsere Drehpunkte bereits ausgerichtet. Aber wir haben den Anfang unserer Wörter verloren, und wenn wir die ausgeblendeten Teile wieder einblenden, werden die Wörter nach rechts verschoben und alles ist wieder durcheinander.

Wenn wir stattdessen die nachfolgenden Buchstaben ausblenden würden, wären wir immer noch mit falsch ausgerichteten Drehpunkten konfrontiert.

All dieses Hin und Her scheint ein wenig sinnlos, aber es offenbart eine Symmetrie meines Problems. Wenn wir ein Rechts-nach-links (RTL)-Leseschema verwenden würden, hätten wir das entgegengesetzte Problem – wir könnten die rechte Seite lösen, aber die linke wäre völlig falsch.

Wäre es nicht großartig, wenn es eine Möglichkeit gäbe, beide Seiten gleichzeitig auszurichten?

Tatsächlich gibt es die.

Da wir bereits eine halbe Lösung haben, leihen wir uns ein Konzept aus der Algorithmik namens *Divide and Conquer* (Teile und Herrsche). Die allgemeine Idee ist, dass wir ein Problem in Teile zerlegen können und dass wir durch das Finden einer Lösung für die Teile eine Lösung für das Ganze finden.

In diesem Fall zerlegen wir unser Problem in die Positionierung von zwei Teilen. Erstens der "Kopf" oder alles vor dem Drehpunkt.

Als nächstes der "Schwanz", der den Drehpunkt plus alles danach umfasst.

Der flex-Display-Typ wird uns hier helfen. Wenn Sie damit nicht vertraut sind, ist flex ein Framework zur Positionierung von Elementen in einer Dimension. Der Trick hierbei ist, die linken und rechten Enden unseres Containers zur Ausrichtung zu nutzen. Um dies zu erreichen, vertauschen wir Kopf und Schwanz, indem wir einen kleineren order-Eigenschaftswert für den Schwanz als für den Kopf verwenden. Die order-Eigenschaft wird von Flex verwendet, um die Reihenfolge der Elemente in einem flexiblen Layout zu bestimmen. Kleinere Zahlen werden früher im Fluss platziert.

Um Kopf- und Schwanz-Elemente ohne zusätzliches HTML zu unterscheiden, können wir den Kopf-Teil auf *alle* Buchstaben anwenden und dann die kaskadierende Natur von CSS nutzen, um den Drehpunkt und alles danach mit dem nachfolgenden Geschwister-Selektor .pivot ~ .letter zu überschreiben.

So sehen die Dinge jetzt aus

Okay, jetzt sitzt der Kopf bündig am Ende des Schwanzes. Moment mal, reg dich nicht auf! Wir können das beheben, indem wir margin: auto auf der rechten Seite des letzten Elements im Schwanz anwenden. Das ist zufällig auch der letzte Buchstabe des Wortes, der jetzt irgendwo in der Mitte sitzt. Die Hinzufügung eines automatischen Rands dient dazu, den Kopf vom Schwanz wegzudrücken und ganz an die rechte Seite unseres Containers zu schieben.

Jetzt haben wir etwas, das so aussieht

Das Einzige, was noch zu tun ist, ist, unsere Teile wieder in der richtigen Reihenfolge zusammenzufügen. Das ist einfach genug, wenn wir position: relative auf alle unsere Buchstaben anwenden und dann ein left: 50% auf den Schwanz und ein right: 50% auf unsere Kopfelemente werfen.

Hier ist eine verallgemeinerte Version des gerade verwendeten Codes. Wie Sie sehen, sind es nur 15 Zeilen einfaches CSS.

.container {
  display: flex;
}
.item:last-child {
  margin-right: auto;
}
.item {
  order: 2;
  position: relative;
  right: 50%;
}
.pivot, .pivot ~ .item {
  order: 1;
  left: 50%;
}

Es ist auch möglich, diesen Ansatz für vertikale Layouts zu verwenden, indem flex-direction auf einen column-Wert gesetzt wird. Es sei auch gesagt, dass dasselbe erreicht werden kann, indem Kopf- und Schwanz-Elemente in eigene Wrapper gesteckt werden – aber das würde mehr Markup und einen umständlicheren CSS-Code erfordern und wäre viel weniger flexibel. Was ist zum Beispiel, wenn unser Backend bereits eine ungepackte Liste von Elementen mit dynamisch generierten Klassen erzeugt?

Zufälligerweise spielt diese Lösung auch gut mit Screenreadern zusammen. Obwohl wir die beiden Abschnitte rückwärts ordnen, verschieben wir sie dann durch relative Positionierung wieder an ihren Platz, sodass die endgültige Reihenfolge der Elemente mit unserem Markup übereinstimmt, wenn auch schön zentriert.

Screenreader behalten die Elementreihenfolge gemäß dem ursprünglichen Markup bei.

Hier ist das endgültige Beispiel auf CodePen

Fazit

Entwickler sind besser im Balancieren als Akrobaten. Glauben Sie mir nicht? Denken Sie darüber nach: Viele der üblichen Herausforderungen, denen wir uns stellen, erfordern die Suche nach einem Mittelweg zwischen konkurrierenden Anforderungen, die von Leistung und Lesbarkeit über Stil und Funktion bis hin zu Skalierbarkeit und Einfachheit reichen. Ein Balanceakt, zweifellos.

Aber der Punkt, an dem wir das Gleichgewicht finden, ist nicht immer die Mitte zwischen dem einen und dem anderen. Gleichgewicht wird oft an einem unerklärlichen Punkt dazwischen gefunden; oder, wie wir gerade gesehen haben, um ein beliebiges HTML-Element herum.

Da haben Sie es! Gehen Sie und erzählen Sie Ihren Freunden, dass Sie der größte Akrobat der Welt sind.