it-swarm.com.de

Chrome/Safari füllt nicht 100% Höhe des Flex-Elternteils

Ich möchte ein vertikales Menü mit einer bestimmten Höhe haben.

Jedes untergeordnete Element muss die Höhe des übergeordneten Elements ausfüllen und einen Text in der Mitte haben.

Die Anzahl der Kinder ist zufällig, also muss ich mit dynamischen Werten arbeiten.

Div .container enthält eine zufällige Anzahl von untergeordneten Elementen (.item), die immer die Höhe des übergeordneten Elements ausfüllen müssen. Dafür habe ich Flexbox verwendet. 

Um Links mit mittig ausgerichtetem Text zu erstellen, verwende ich die display: table-cell-Technik. Die Verwendung von Tischanzeigen erfordert jedoch eine Höhe von 100%.

Mein Problem ist, dass .item-inner { height: 100% } nicht im Webkit (Chrome) funktioniert. 

  1. Gibt es eine Lösung für dieses Problem? 
  2. Oder gibt es eine andere Technik, um alle .item die Höhe des übergeordneten Elements mit vertikal zur Mitte ausgerichtetem Text ausfüllen zu lassen?

Beispiel hier jsFiddle, sollte in Firefox und Chrome angezeigt werden

.container {
  height: 20em;
  display: flex;
  flex-direction: column;
  border: 5px solid black
}
.item {
  flex: 1;
  border-bottom: 1px solid white;
}
.item-inner {
  height: 100%;
  width: 100%;
  display: table;
}
a {
  background: orange;
  display: table-cell;
  vertical-align: middle;
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

164

Lösung

Verwenden Sie verschachtelte Flex-Container.

Prozenthöhen loswerden. Befreien Sie sich von Tabelleneigenschaften. Werde vertical-align Los. Vermeiden Sie eine absolute Positionierung. Bleib einfach ganz bei flexbox durch.

Wenden Sie display: flex Auf das Flex-Objekt an (.item), Um es zu einem Flex-Container zu machen. Dies setzt automatisch align-items: stretch, Wodurch das Kind (.item-inner) Angewiesen wird, die volle Höhe des Elternteils zu erweitern.

Wichtig: Entfernen Sie die angegebenen Höhen von Flex-Elementen, damit diese Methode funktioniert. Wenn für ein Kind eine Größe angegeben wurde (z. B. height: 100%), Wird der align-items: stretch vom Elternteil kommen. Damit die Standardeinstellung stretch funktioniert, muss die Größe des Kindes mit auto(vollständige Erläuterung ) berechnet werden.

Versuchen Sie dies (keine Änderungen an HTML):

.container {
    display: flex;
    flex-direction: column;
    height: 20em;
    border: 5px solid black
}

.item {
    display: flex;                      /* new; nested flex container */
    flex: 1;
    border-bottom: 1px solid white;
}

.item-inner {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */

    /* height: 100%;                    <-- remove; unnecessary */
    /* width: 100%;                     <-- remove; unnecessary */
    /* display: table;                  <-- remove; unnecessary */  
}

a {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */
    align-items: center;                /* new; vertically center text */
    background: orange;

    /* display: table-cell;             <-- remove; unnecessary */
    /* vertical-align: middle;          <-- remove; unnecessary */
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

jsFiddle-Demo


Erläuterung

Mein Problem ist, dass .item-inner { height: 100% } Im Webkit (Chrome) nicht funktioniert.

Es funktioniert nicht, weil Sie die prozentuale Höhe auf eine Weise verwenden, die nicht der herkömmlichen Implementierung der Spezifikation entspricht.

10.5 Höhe des Inhalts: die Eigenschaft height

Prozentsatz
Gibt eine prozentuale Höhe an. Der Prozentsatz wird in Bezug auf die Höhe des Blocks berechnet, der die generierte Box enthält. Wenn die Höhe des enthaltenen Blocks nicht explizit angegeben wird und dieses Element nicht absolut positioniert ist, wird der Wert zu auto berechnet.

auto
Die Höhe hängt von den Werten anderer Eigenschaften ab.

Mit anderen Worten, damit die prozentuale Höhe für ein eingehendes untergeordnetes Element verwendet werden kann, muss das übergeordnete Element muss eine festgelegte Höhe haben.

In Ihrem Code hat der Container der obersten Ebene eine definierte Höhe: .container { height: 20em; }

Der Container der dritten Ebene hat eine definierte Höhe: .item-inner { height: 100%; }

Dazwischen hat der Container der zweiten Ebene - .item - nicht eine definierte Höhe. Webkit sieht das als fehlendes Glied.

.item-inner Sagt Chrome: gib mir height: 100%. Chrome schaut nach dem übergeordneten Element (.item) Und antwortet: 100% von was? Ich sehe nichts (ignoriert das flex: 1 Regel, die es gibt). Als Ergebnis gilt height: auto (Inhaltshöhe) gemäß der Spezifikation.

Firefox hingegen akzeptiert jetzt die Flex-Größe eines Elternteils als Referenz für die prozentuale Größe des Kindes. IE11 und Edge akzeptieren auch Flexhöhen.

Chrome akzeptiert flex-grow Als adäquaten übergeordneten Verweis in Verbindung mit flex-basis (jeder numerische Wert funktioniert ( auto nicht), einschließlich flex-basis: 0). Zum jetzigen Zeitpunkt schlägt diese Lösung jedoch in Safari fehl.

#outer {
  display: flex;
  flex-direction: column;
  height: 300px;
  background-color: white;
  border: 1px solid red;
}
#middle {
  flex-grow: 1;
  flex-basis: 1px;
  background-color: yellow;
}
#inner {
  height: 100%;
  background-color: lightgreen;
}
<div id="outer">
  <div id="middle">
    <div id="inner">
      INNER
    </div>
  </div>
</div>

Vier Lösungen

1. Geben Sie eine Höhe für alle übergeordneten Elemente an

Eine zuverlässige browserübergreifende Lösung besteht darin, für alle übergeordneten Elemente eine Höhe anzugeben. Dies verhindert, dass Links fehlen, die von Webkit-basierten Browsern als Verstoß gegen die Spezifikation eingestuft werden.

Beachten Sie, dass min-height Und max-height Nicht zulässig sind. Es muss die Eigenschaft height sein.

Weitere Details hier: Arbeiten mit der CSS-Eigenschaft height und Prozentwerten

2. CSS Relative & Absolute Positionierung

Wenden Sie position: relative Auf das übergeordnete Element und position: absolute Auf das untergeordnete Element an.

Passen Sie die Größe des Kindes mit height: 100% Und width: 100% An, oder verwenden Sie die Offset-Eigenschaften: top: 0, right: 0, bottom: 0, left: 0.

Bei der absoluten Positionierung funktioniert die prozentuale Höhe ohne eine angegebene Höhe für das übergeordnete Element.

3. Entfernen Sie unnötige HTML-Container (empfohlen)

Benötigen Sie zwei Container um button? Warum nicht .item Oder .item-inner Oder beides entfernen? Obwohl button Elemente manchmal als flexible Container versagen , können sie flexible Elemente sein. Erwägen Sie, button zu einem untergeordneten Element von .container Oder .item Zu machen und unbegründete Markierungen zu entfernen.

Hier ist ein Beispiel:

.container {
    height: 20em;
    display: flex;
    flex-direction: column;
    border: 5px solid black
}

a {
    flex: 1;
    background: orange;
    border-bottom: 1px solid white;
    display: flex;                   /* nested flex container (for aligning text) */
    align-items: center;             /* center text vertically */
    justify-content: center;         /* center text horizontally */
}
<div class="container">
    <a>Button</a>
    <a>Button</a>
    <a>Button</a>
</div>

4. Geschachtelte Flex-Container (empfohlen)

Prozenthöhen loswerden. Befreien Sie sich von Tabelleneigenschaften. Werde vertical-align Los. Vermeiden Sie eine absolute Positionierung. Bleib einfach ganz bei flexbox durch.

Wenden Sie display: flex Auf das Flex-Objekt an (.item), Um es zu einem Flex-Container zu machen. Dadurch wird automatisch align-items: stretch Festgelegt, wodurch das untergeordnete Element (.item-inner) Angewiesen wird, die volle Höhe des übergeordneten Elements zu erweitern.

Wichtig: Entfernen Sie die angegebenen Höhen von Flex-Elementen, damit diese Methode funktioniert. Wenn für ein Kind eine Größe angegeben wurde (z. B. height: 100%), Wird der align-items: stretch vom Elternteil kommen. Damit die Standardeinstellung stretch funktioniert, muss die Größe des Kindes mit auto(vollständige Erläuterung ) berechnet werden.

Versuchen Sie dies (keine Änderungen an HTML):

.container {
    display: flex;
    flex-direction: column;
    height: 20em;
    border: 5px solid black
}

.item {
    display: flex;                      /* new; nested flex container */
    flex: 1;
    border-bottom: 1px solid white;
}

.item-inner {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */

    /* height: 100%;                    <-- remove; unnecessary */
    /* width: 100%;                     <-- remove; unnecessary */
    /* display: table;                  <-- remove; unnecessary */  
}

a {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */
    align-items: center;                /* new; vertically center text */
    background: orange;

    /* display: table-cell;             <-- remove; unnecessary */
    /* vertical-align: middle;          <-- remove; unnecessary */
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

jsFiddle

334
Michael_B

Lösung: Entfernen Sie height: 100% in .item-inner und fügen Sie display: flex in .item hinzu.

Demo: https://codepen.io/tronghiep92/pen/NvzVoo

4
nghiepit

Ich hatte ein ähnliches Problem in iOS 8, 9 und 10, und die obigen Informationen konnten das Problem nicht beheben. Nach einem Tag Arbeit fand ich jedoch eine Lösung. Zugegeben, es funktioniert nicht für alle, aber in meinem Fall waren meine Artikel in einer Spalte gestapelt und hatten 0 Höhe, wenn sie die Inhaltshöhe hätte haben sollen. Durch das Wechseln der CSS-Datei in Zeile und Wrap wurde das Problem behoben. Dies funktioniert nur, wenn Sie ein einzelnes Objekt haben und sie gestapelt sind. Da ich jedoch einen Tag gebraucht habe, um das herauszufinden, dachte ich, ich sollte mein Update teilen!

.wrapper {
    flex-direction: column; // <-- Remove this line
    flex-direction: row; // <-- replace it with
    flex-wrap: wrap; // <-- Add wrapping
}

.item {
    width: 100%;
}
0
Designer023

Für Mobile Safari gibt es einen Browser-Fix. Sie müssen -webkit-box für iOS-Geräte hinzufügen.

Ex.

display: flex;
display: -webkit-box;
flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
align-items: stretch;

wenn Sie die align-items: stretch;-Eigenschaft für das übergeordnete Element verwenden, entfernen Sie height : 100% aus dem untergeordneten Element.

0
Narasinghe