Scorrimento di una flexbox con contenuti straripanti


214

inserisci qui la descrizione dell'immagine

Ecco il codice che sto usando per ottenere il layout sopra:

.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>

Ho omesso il codice utilizzato per lo styling. Puoi vederlo tutto dentro penna .


Quanto sopra funziona, ma quando il contentcontenuto dell'area trabocca, fa scorrere l'intera pagina. Voglio solo scorrere l'area stessa del contenuto, quindi ho aggiuntooverflow: auto al contentdiv .

Il problema con questo ora è che le colonne stesse non si estendono oltre l'altezza dei loro genitori, quindi anche i bordi vengono tagliati lì.

Ecco la penna che mostra il problema di scorrimento .

Come posso impostare l' contentarea per scorrere in modo indipendente, pur avendo i suoi figli estendersi oltre l' contentaltezza della casella?

Risposte:


264

Ne ho parlato con Tab Atkins (autore delle specifiche della flexbox), e questo è ciò che abbiamo inventato:

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 */
}

Ecco le penne:

  1. Colonne corte allungate .
  2. Colonne più lunghe traboccanti e scorrevoli .

Il motivo per cui funziona è perché align-items: stretchnon riduce i suoi oggetti se hanno un'altezza intrinseca, che viene eseguita qui da min-content.


3
Funzionano quando l'altezza del genitore non dipende dai suoi figli, generalmente, come è il caso qui. min-height: il 100% risolve davvero il tuo problema di allungamento delle colonne anche in Firefox (sebbene non in Chrome). Non sono sicuro se si tratta di un bug di Chrome o di Firefox.
dholbert,

1
@dholbert - Tab Atkins mi ha aiutato in questo. Ho aggiornato la mia risposta.
Joseph Silber,

3
Nota che Firefox attualmente supporta solo "min-content" per i valori di larghezza, non per quelli di altezza - quindi non funzionerà in Firefox, se questo è importante per te. (Vedi ad esempio bugzilla.mozilla.org/show_bug.cgi?id=852367 )
dholbert,

2
@dholbert - Il problema con queste penne è che erano pubbliche, quindi chiunque poteva cambiarle. Ne ho preso la proprietà, quindi eccoti
Joseph Silber,

5
Sì, questo è rotto in IE11
Steve

119

Ho appena risolto questo problema in modo molto elegante dopo molte prove ed errori.

Dai un'occhiata al mio post sul blog: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

Fondamentalmente, per rendere scorrevole una cella flexbox, devi rendere tutti i suoi genitori overflow: hidden; , o semplicemente ignorerà le tue impostazioni di overflow e ingrandirà invece il genitore.


11
Questo ha funzionato anche nel mio caso, ma wow, mi piacerebbe davvero vedere una spiegazione del perché funzioni. Il più delle volte, trovo che le specifiche CSS siano totalmente imperscrutabili per questo tipo di cose.
Markrian,

2
Dal tuo post sul blog: "Non ho idea del perché funzioni e le specifiche non dicono nulla" . Quindi, sto cercando una spiegazione del perché funziona. Ho sfogliato le specifiche, ma come hai detto, niente salta là fuori.
Markrian,

3
Dopo averci pensato un po 'di più, penso che abbia senso. Il comportamento predefinito è che ogni div si espanda per contenere tutti i suoi figli, quindi non ci sarà alcun overflow da nascondere ai nodi foglia. È necessario forzare l'overflow: nascosto completamente dalla parte superiore del DOM, quindi nessun genitore ha la possibilità di ospitare i propri figli fino a quando non si scende al nodo che si desidera overflow e scorrimento.
geon,

3
Non sono sicuro che questo lo spieghi davvero. L'impostazione di overflow su nascosto su un elemento non impedisce che si espanda per contenere tutti i suoi figli, AFAIK. Secondo MDN: "La proprietà di overflow specifica se tagliare il contenuto, renderizzare le barre di scorrimento o semplicemente visualizzare il contenuto quando trabocca il suo contenitore a livello di blocco." Inoltre, l'impostazione di overflow su qualcosa di diverso da visibile crea un nuovo contesto di formattazione dei blocchi, ma ciò non può essere rilevante, poiché i contenitori flessibili già creano il proprio contesto di formattazione dei blocchi: developer.mozilla.org/en-US/docs/Web/Guide / CSS /… .
Markrian,

1
Devo aggiungere che sono d'accordo sul fatto che la tua spiegazione abbia un senso intuitivo , ma non penso che sia una spiegazione tecnica accurata , che è quello che voglio. Solo comprendendo veramente la ragione sarò in grado di ricordare la soluzione in futuro!
Markrian,

55

Lavorare position:absolute;insieme a flex:

Posizionare l'elemento flessibile con position: relative. Quindi al suo interno, aggiungi un altro <div>elemento con:

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

Questo estende l'elemento ai limiti del suo genitore posizionato in modo relativo, ma non consente di estenderlo. All'interno, overflow: auto;funzionerà quindi come previsto.

  • lo snippet di codice incluso nella risposta. Fai clic su, inserisci qui la descrizione dell'immaginequindi fai clic su Pagina interadopo aver eseguito lo snippet OPPURE
  • Clicca qui per il CODEPEN
  • Il risultato: inserisci qui la descrizione dell'immagine

.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>

In bocca al lupo...


2
Questa soluzione è particolarmente utile se il componente interno ha un'imbottitura perché lo bloccherà perfettamente in posizione dove vuoi. È molto più semplice. (Sì, è possibile impostare box-sizing: border-boxinvece, ma può essere più complesso per alcuni controlli di terze parti).
Simon_Weaver,

2
mi hai salvato la notte!
Botea Florin,

2
Grazie. In qualche modo sono deluso dal fatto che ciò sia necessario, ma sono grato per il consiglio!
Mathias,

9

Un po 'in ritardo ma questo potrebbe aiutare: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

Fondamentalmente è necessario mettere html, bodyper height: 100%; e avvolgere tutti i tuoi contenuti in un<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

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

Ha funzionato per me. Spero che sia d'aiuto


Dovresti stare molto attento quando usi "height: 100vh" poiché misura diversamente in iOS Safari vs Android. Uno tiene conto dell'altezza della barra degli URL e l'altro no.
Sean Anderson,

7

Aggiungi questo:

align-items: flex-start;

alla regola di .content {} . Questo lo risolve nella penna per me, almeno (sia in Firefox che in Chrome).

Per impostazione predefinita, .contenthas align-items: stretch, che consente di ridimensionare tutti i propri figli di altezza automatica in modo che corrispondano alla propria altezza, per http://dev.w3.org/csswg/css-flexbox/#algo-stretch . Al contrario, il valore flex-startconsente ai bambini di calcolare le proprie altezze e di allinearsi sul bordo iniziale (e traboccare e attivare una barra di scorrimento).



Inoltre, le colonne non avranno più la stessa altezza, che è una delle principali attrazioni di flexbox.
Joseph Silber,

OK. Non mi era chiaro che quello era un vincolo di progettazione: scusate.
dholbert,

Ottimo consiglio
Vlad

1

Un problema che ho riscontrato è che per avere una barra di scorrimento è necessario specificare un elemento in altezza (e non in%).

Il trucco è annidare un altro set di div all'interno di ciascuna colonna e impostare la visualizzazione del genitore della colonna in modo che si fletta con la direzione flessibile: colonna.

    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>

Ed ecco l'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

La soluzione a questo problema è solo aggiungere overflow: auto;al contenuto .cont per rendere scorrevole il wrapper di contenuto.

Inoltre, si verificano circostanze insieme al wrapper Flexbox e al overflowedcontenuto scorrevole come questo codice .

La soluzione è aggiungere overflow: hidden (or auto);al genitore del wrapper (impostato con overflow: auto;) attorno a contenuti di grandi dimensioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.