Flexbox Navigationsleiste mit festen, variablen und den Rest einnehmenden Elementen

Avatar of Chris Coyier
Chris Coyier am

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

Izak Filmalter schrieb mir

Auf der Website, an der ich arbeite, gibt es eine Navigationsleiste mit einigen Elementen: ein Suchfeld, der vollständige Name des Benutzers und einige Symbole. Die Symbole haben eine feste Breite, der Name des Benutzers variiert und das Suchfeld soll den Rest des nutzbaren Platzes einnehmen.

Egal, was ich versuche, ich schaffe es nicht, dass das Suchfeld den gesamten verfügbaren Platz und nicht mehr nutzt, wenn die Länge des Benutzernamens dynamisch ist.

Ich habe Izak bereits eine Antwort gesendet, aber ich werde diese Lösung hier teilen. Flexbox! Ich bin mir sicher, dass es keine Überraschung ist, dass Flexbox ein wunderbares Werkzeug für Layouts ist. Ich habe hier einen Leitfaden zu Flexbox, der als gute Referenz dient.

Die gute Nachricht ist, dass dies mit Flexbox-Layout eine ziemlich einfache Sache ist. Wir werden detaillierter darauf eingehen, aber diese wenigen Codezeilen erledigen im Grunde die Arbeit.

.bar {
  display: flex;
}
.search {
  flex: 1;
} 

Schritt für Schritt

Nehmen wir Markup wie dieses an. Nichts Überraschendes hier wirklich. Ich habe das Suchfeld in ein <div> eingeschlossen, hauptsächlich weil ich mich vor einem Eingabefeld, das zu einem Flex-Element wird, unwohl fühle. Aber man möchte wahrscheinlich sowieso ein umschließendes Element (wie ein <form>), da man wahrscheinlich ein <label> und so weiter hätte.

<div class="bar">
  <div class="icon icon-1"></div>
  <div class="icon icon-2"></div>
  <div class="icon icon-3"></div>
  <div class="username">
    Emily Blunt
  </div>
  <div class="search">
    <input type="search" placeholder="search..." />
  </div>
</div>
Ohne CSS

Um sie horizontal auszurichten und zu zentrieren

.bar {
  display: flex;
  align-items: center;
}

Stellen wir sicher, dass die Leiste so breit wie das Browserfenster ist. Das können wir leicht mit 100% Breite einstellen. Aber jedes Mal, wenn ich das tue, erinnere ich mich, dass wir box-sizing: border-box; verwenden sollten – sonst wäre bei jedem Padding oder jeder Border auf diesem Container die Breite größer als 100% und das ist das Schlimmste.

*, *:before, *:after {
  box-sizing: inherit;
}
html {
  box-sizing: border-box;
}
.bar {
  display: flex;
  align-items: center;
  width: 100%;
  background: #eee;
  padding: 20px;
}

Für den letzten Trick

.search {
  /* take up the rest of the remaining space */
  flex: 1;
}
.search input {
  width: 100%;
}

Es funktioniert dann so

Jetzt, wo wir im Flexbox-Land sind, können wir sogar die Reihenfolge der Elemente beliebig tauschen und die gleiche gute Abstandsaktion erzielen. Die `order`-Eigenschaft ist standardmäßig 0, sodass jeder positive Wert dieses Flex-Element am Ende platziert und jeder negative Wert am Anfang. Und dann in der Reihenfolge, genau wie `z-index`.

.bar-2 .username {
  order: 2;
}
.bar-2 .icon-3 {
  order: 3;
}

.bar-3 .search {
  order: -1;
}
.bar-3 .username {
  order: 1;
}

Bonus RWD!

Flexbox ist super freundlich zu responsivem Design, da wir die Reihenfolge und Größe und sogar das Umbrechen wirklich einfach ändern können. Machen wir unsere Demo umbrechend und geben wir der Suche und dem Benutzernamen volle Breite.

@media (max-width: 650px) {
  .bar {
    flex-wrap: wrap;
  }
  .icon {
    order: 0 !important;
  }
  .username {
    order: 1 !important;
    width: 100%;
    margin: 15px;
  }
  .search {
    order: 2 !important;
    width: 100%;
  }
}

Demo

Hier geht's los

Siehe den Stift Flexbox reordering von Chris Coyier (@chriscoyier) auf CodePen.

Browser-Unterstützung

Man kann heutzutage nicht über Flexbox reden, ohne etwas Gerede über Browserunterstützung. Wie immer können Sie Can I Use konsultieren. IE 9 ist die große Einschränkung, die noch übrig ist. Wenn Sie das unterstützen müssen, müssen Sie einen anderen Weg finden. Ansonsten, zwischen alten / neuen / mittleren Synthesen, werden Sie gut zurechtkommen. Wir verwenden hier nichts Seltsames.

Der Trick besteht einfach darin, Autoprefixer zu verwenden, das Flexbox wunderbar handhabt. Wenn Sie das verwenden, werden die Flexbox-Eigenschaften/Werte in dieser Demo zu

.bar {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}

.search {
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
.bar-2 .username {
  -webkit-order: 2;
  -ms-flex-order: 2;
  order: 2;
}

Aber ich brauche einen besseren Fallback!

Eine Möglichkeit ist die Verwendung von Modernizr, um die Flexbox-Unterstützung zu erkennen. Es fügt dem html-Element eine Klassenbezeichnung hinzu, wie z.B.

<html class="no-flexbox">

Sie können das verwenden, um eine andere Layout-Technik zu verwenden

.no-flexbox .bar {
  display: table;
  border-spacing: 15px;
  padding: 0;
}
.no-flexbox .bar > * {
  display: table-cell;
  vertical-align: middle;
  white-space: nowrap;
}
.no-flexbox .username {
  width: 1px;
}

Funktioniert ziemlich gut

Es ist nicht der einzige mögliche Weg. Man könnte mit `inline-block` oder `float` experimentieren und Dinge mit JavaScript messen. Oder man könnte eine tatsächliche Tabelle verwenden. Das Web, yo, es gibt immer einen Weg.