Scrollen einer Flexbox mit überfülltem Inhalt


214

Geben Sie hier die Bildbeschreibung ein

Hier ist der Code, mit dem ich das obige Layout erreiche:

.header {
  height: 50px;
}

.body {
  position: absolute;
  top: 50px;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
}

.sidebar {
  width: 140px;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  display: flex;
}

.column {
  padding: 20px;
  border-right: 1px solid #999;
}
<div class="header">Main header</div>
<div class="body">
  <div class="sidebar">Sidebar</div>

  <div class="main">
    <div class="page-header">Page Header. Content columns are below.</div>
    <div class="content">
      <div class="column">Column 1</div>
      <div class="column">Column 1</div>
      <div class="column">Column 1</div>
    </div>
  </div>
</div>

Ich habe den für das Styling verwendeten Code weggelassen. Sie können alles im Stift sehen .


Das Obige funktioniert, aber wenn der contentInhalt des Bereichs überläuft, wird die gesamte Seite gescrollt. Ich möchte nur, dass der Inhaltsbereich selbst gescrollt wird, also habe ich overflow: autodem contentdiv hinzugefügt .

Das Problem dabei ist nun, dass die Spalten selbst nicht über die Höhe ihrer Eltern hinausragen, sodass auch dort die Ränder abgeschnitten werden.

Hier ist der Stift, der das Bildlaufproblem zeigt .

Wie kann ich festlegen, dass der contentBereich unabhängig gescrollt wird, während die untergeordneten Elemente weiterhin über die contentHöhe der Box hinausragen ?

Antworten:


263

Ich habe mit Tab Atkins (Autor der Flexbox-Spezifikation) darüber gesprochen, und das haben wir uns ausgedacht:

HTML:

<div class="content">
    <div class="box">
        <div class="column">Column 1</div>
        <div class="column">Column 2</div>
        <div class="column">Column 3</div>
    </div>
</div>

CSS:

.content {
    flex: 1;
    display: flex;
    overflow: auto;
}

.box {
    display: flex;
    min-height: min-content; /* needs vendor prefixes */
}

Hier sind die Stifte:

  1. Kurze Säulen werden gedehnt .
  2. Längere Spalten laufen über und scrollen .

Der Grund dafür ist, dass align-items: stretchdie Elemente nicht verkleinert werden, wenn sie eine intrinsische Höhe haben, was hier durch erreicht wird min-content.


3
Sie funktionieren, wenn die Größe der Eltern im Allgemeinen nicht von ihren Kindern abhängt, was hier der Fall ist. Min-Höhe: 100% behebt in der Tat das Problem der Dehnung, auch wenn Spalten in Firefox kurz sind (allerdings nicht in Chrome). Ich bin mir nicht sicher, ob es sich um einen Chrome-Fehler oder einen Firefox-Fehler handelt.
Dholbert

1
@dholbert - Tab Atkins hat mir dabei geholfen. Ich habe meine Antwort aktualisiert.
Joseph Silber

3
Beachten Sie, dass Firefox derzeit nur "Min-Content" für Breitenwerte und nicht für Höhenwerte unterstützt. Dies funktioniert in Firefox also nicht, wenn dies für Sie von Bedeutung ist. (Siehe zB bugzilla.mozilla.org/show_bug.cgi?id=852367 )
dholbert

2
@dholbert - Das Problem mit diesen Stiften ist, dass sie öffentlich waren, so dass jeder sie ändern konnte. Ich habe sie in Besitz genommen, also los geht's: codepen.io/JosephSilber/pen/pmyHh
Joseph Silber

5
Ja, dies ist in IE11
Steve

119

Ich habe dieses Problem gerade nach vielen Versuchen und Irrtümern sehr elegant gelöst.

Schauen Sie sich meinen Blog-Beitrag an: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

Im Grunde genommen , um eine Flexbox Zelle scrollbaren zu machen, müssen Sie all seinen machen Eltern overflow: hidden; , oder es wird nur Ihre Überlauf - Einstellungen ignorieren und die Eltern statt größer.


11
Das hat auch in meinem Fall funktioniert, aber wow, ich würde wirklich gerne eine Erklärung sehen, warum es funktioniert. Meistens finde ich die CSS-Spezifikationen für solche Dinge völlig unergründlich.
Markrian

2
Von Ihrem Blog - Eintrag: „Ich habe keine Ahnung , warum das funktioniert, und die Spezifikationen nichts sagen entweder“ . Also suche ich nach einer Erklärung, warum es funktioniert. Ich habe die Spezifikationen überflogen, aber wie Sie sagten, springt da draußen nichts heraus.
Markrian

3
Nachdem ich noch etwas darüber nachgedacht habe, denke ich, dass es Sinn macht. Das Standardverhalten ist, dass jedes Div so erweitert wird, dass es alle untergeordneten Elemente enthält, sodass an den Blattknoten kein Überlauf zu verbergen ist. Sie müssen einen Überlauf erzwingen: Wird ganz oben im DOM ausgeblendet, sodass kein Elternteil die Möglichkeit hat, seine untergeordneten Elemente aufzunehmen, bis Sie zu dem Knoten gelangen, den Sie überlaufen und scrollen möchten.
Geon

3
Ich bin mir nicht sicher, ob das das wirklich erklärt. Wenn Sie den Überlauf für ein Element auf "Ausgeblendet" setzen, wird es nicht daran gehindert, alle untergeordneten Elemente, AFAIK, zu erweitern. Laut MDN: "Die Überlaufeigenschaft gibt an, ob Inhalte abgeschnitten, Bildlaufleisten gerendert oder nur Inhalte angezeigt werden sollen, wenn der Container auf Blockebene überläuft." Wenn Sie den Überlauf auf etwas anderes als Sichtbares setzen, wird außerdem ein neuer Blockformatierungskontext erstellt. Dies kann jedoch nicht relevant sein, da Flex-Container bereits einen eigenen Blockformatierungskontext erstellen: developer.mozilla.org/en-US/docs/Web/Guide / CSS /… .
Markrian

1
Ich sollte hinzufügen, dass ich damit einverstanden bin, dass Ihre Erklärung intuitiv sinnvoll ist, aber ich denke nicht, dass es eine genaue technische Erklärung ist, was ich will. Nur wenn ich den Grund wirklich verstehe, kann ich mich in Zukunft an die Lösung erinnern!
Markrian

55

Arbeiten mit position:absolute;zusammen mit flex:

Positionieren Sie das Flex-Element mit position: relative. Fügen Sie dann ein weiteres <div>Element hinzu mit:

position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;

Dadurch wird das Element bis an die Grenzen seines relativ positionierten übergeordneten Elements erweitert, es kann jedoch nicht erweitert werden. Innen overflow: auto;funktioniert dann wie erwartet.

  • das in der Antwort enthaltene Code-Snippet - Klicken Sie auf Geben Sie hier die Bildbeschreibung einund dann auf, Volle Seitenachdem Sie das Snippet ausgeführt haben ODER
  • Klicken Sie hier für den CODEPEN
  • Das Ergebnis: Geben Sie hier die Bildbeschreibung ein

.all-0 {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
p {
  text-align: justify;
}
.bottom-0 {
  bottom: 0;
}
.overflow-auto {
  overflow: auto;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>


<div class="p-5 w-100">
  <div class="row bg-dark m-0">
    <div class="col-sm-9 p-0 d-flex flex-wrap">
      <!-- LEFT-SIDE - ROW-1 -->
      <div class="row m-0 p-0">
        <!-- CARD 1 -->
        <div class="col-md-8 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/700x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 2 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
      </div>
      <div class="row m-0">
        <!-- CARD 3 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 4 -->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
        <!-- CARD 5-->
        <div class="col-md-4 p-0 d-flex">
          <div class="my-card-content bg-white p-2 m-2 d-flex flex-column">
            <img class="img img-fluid" src="https://via.placeholder.com/400x250">
            <h4>Heading 1</h4>
            <p>
              Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old...
          </div>
        </div>
      </div>
    </div>
    <div class="col-sm-3 p-0">
      <div class="bg-white m-2 p-2 position-absolute all-0 d-flex flex-column">
        <h4>Social Sidebar...</h4>
        <hr />
        <div class="d-flex overflow-auto">
          <p>
            Topping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            opping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            opping candy tiramisu soufflé fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva fruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart.
            Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream
            chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halvafruitcake ice cream chocolate
            bar. Bear claw ice cream chocolate bar donut sweet tart. Pudding cupcake danish apple pie apple pie. Halva
        </div>
      </div>
    </div>
  </div>

Viel Glück...


2
Diese Lösung ist besonders nützlich, wenn für die Komponente im Inneren eine Polsterung festgelegt ist, da sie überall dort gut einrastet, wo Sie möchten. Es ist viel einfacher. (Ja, Sie könnten box-sizing: border-boxstattdessen festlegen, aber das kann für bestimmte Steuerelemente von Drittanbietern komplexer sein.)
Simon_Weaver

2
Du hast meine Nacht gerettet!
Botea Florin

2
Danke dir. Irgendwie bin ich enttäuscht, dass dies notwendig ist, aber ich bin dankbar für den Rat!
Mathias

9

Ein bisschen spät, aber das könnte helfen: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

Grundsätzlich müssen Sie setzen html, bodyzu height: 100%; und wickeln Sie alle Ihre Inhalte in ein<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

.wrap {
  height: 100vh;
  display: flex;
}

Hat für mich gearbeitet. Ich hoffe es hilft


Sie sollten sehr vorsichtig sein, wenn Sie "height: 100vh" verwenden, da es in iOS Safari anders als in Android misst. Einer berücksichtigt die Höhe der URL-Leiste und der andere nicht.
Sean Anderson

7

Füge das hinzu:

align-items: flex-start;

zur Regel für .content {}. Das behebt es zumindest für mich in Ihrem Stift (sowohl in Firefox als auch in Chrome).

Standardmäßig hat .contenthas align-items: stretch, wodurch alle untergeordneten Elemente mit automatischer Höhe entsprechend ihrer eigenen Größe gemäß http://dev.w3.org/csswg/css-flexbox/#algo-stretch angepasst werden . Im Gegensatz dazu flex-startkönnen die Kinder mit dem Wert ihre eigenen Höhen berechnen und sich an der Startkante ausrichten (und überlaufen und eine Bildlaufleiste auslösen).



Außerdem sind die Säulen nicht mehr gleich hoch, was eine der Hauptattraktionen von Flexbox ist.
Joseph Silber

OK. Mir war nicht klar, dass dies eine Designbeschränkung war - sorry.
Dholbert

Toller Vorschlag
Vlad

1

Ein Problem, auf das ich gestoßen bin, ist, dass für eine Bildlaufleiste für ein Element eine Höhe angegeben werden muss (und nicht als%).

Der Trick besteht darin, einen weiteren Satz von Divs in jeder Spalte zu verschachteln und die Anzeige der übergeordneten Spalte so einzustellen, dass sie mit der Flex-Richtung: Spalte gebogen wird.

    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }

    body {
        overflow-y: hidden;
        overflow-x: hidden;
        color: white;
    }

    .base-container {
        display: flex;
        flex: 1;
        flex-direction: column;
        width: 100%;
        height: 100%;
        overflow-y: hidden;
        align-items: stretch;
    }

    .title {
        flex: 0 0 50px;
        color: black;
    }

    .container {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
    }

        .container .header {
            flex: 0 0 50px;
            background-color: red;
        }

        .container .body {
            flex: 1 1 auto;
            display: flex;
            flex-direction: row;
        }

            .container .body .left {
                display: flex;
                flex-direction: column;
                flex: 0 0 80px;
                background-color: blue;
            }
                .container .body .left .content,
                .container .body .main .content,
                .container .body .right .content {
                    flex: 1 1 auto;
                    overflow-y: auto;
                    height: 100px;
                }
                .container .body .main .content.noscrollbar {
                    overflow-y: hidden;
                }

            .container .body .main {
                display: flex;
                flex-direction: column;
                flex: 1 1 auto;
                background-color: green;
            }

            .container .body .right {
                display: flex;
                flex-direction: column;
                flex: 0 0 300px;
                background-color: yellow;
                color: black;
            }

    .test {
        margin: 5px 5px;
        border: 1px solid white;
        height: calc(100% - 10px);
    }
</style>

Und hier ist das HTML:

<div class="base-container">
    <div class="title">
        Title
    </div>
    <div class="container">
        <div class="header">
            Header
        </div>
        <div class="body">
            <div class="left">
                <div class="content">
                    <ul>
                        <li>1</li>
                        <li>2</li>
                        <li>3</li>
                        <li>4</li>
                        <li>5</li>
                        <li>6</li>
                        <li>7</li>
                        <li>8</li>
                        <li>9</li>
                        <li>10</li>
                        <li>12</li>
                        <li>13</li>
                        <li>14</li>
                        <li>15</li>
                        <li>16</li>
                        <li>17</li>
                        <li>18</li>
                        <li>19</li>
                        <li>20</li>
                        <li>21</li>
                        <li>22</li>
                        <li>23</li>
                        <li>24</li>
                    </ul>
                </div>
            </div>
            <div class="main">
                <div class="content noscrollbar">
                    <div class="test">Test</div>
                </div>
            </div>
            <div class="right">
                <div class="content">
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>Right</div>
                    <div>End</div>
                </div>
            </div>
        </div>
    </div>
</div>

https://jsfiddle.net/LiamFlavelle/czpjdfr4/


0

Die Lösung für dieses Problem besteht overflow: auto;darin, den Inhalt hinzuzufügen , um den Inhalts-Wrapper scrollbar zu machen.

Darüber hinaus treten Umstände zusammen mit dem Flexbox-Wrapper und overflowedscrollbaren Inhalten wie diesem Codepen auf .

Die Lösung besteht darin overflow: hidden (or auto);, dem übergeordneten Element des Wrappers (festgelegt mit Überlauf: auto;) große Inhalte hinzuzufügen .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.