Прокрутка флекси з переповненим вмістом


214

введіть тут опис зображення

Ось код, який я використовую для досягнення вищевказаного макета:

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

Я пропустив код, який використовується для стилізації. Ви можете побачити все це в ручці .


Вищезазначене працює, але коли contentвміст області переповнюється, це змушує прокручувати всю сторінку. Я хочу лише, щоб сама область вмісту прокручувалась, тому я додав overflow: autoу contentdiv .

Проблема в цьому зараз полягає в тому, що самі стовпчики не виходять за межі висоти батьків, тому межі також відрізані.

Ось ручка, що показує проблему прокрутки .

Як я можу встановити contentзону для прокрутки незалежно, поки її діти виходять за межі contentвисоти коробки?

Відповіді:


264

Я говорив з Табом Аткінсом (автором специфікації flexbox) про це, і ось що ми придумали:

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

Ось ручки:

  1. Короткі колони розтягуються .
  2. Більш довгі стовпці переповнюються та прокручуються .

Причина цього працює в тому, що align-items: stretchвін не стискає своїх елементів, якщо вони мають внутрішню висоту, що тут виконується min-content.


3
Вони працюють, коли зріст батька не залежить від його дітей, як правило, у цьому випадку. мінімальна висота: 100% дійсно виправляє ваші проблеми з розтягуванням, навіть коли коли стовпці, у Firefox (хоча не в Chrome). Не впевнений, чи це помилка Chrome чи помилка Firefox.
дхольберт

1
@dholbert - в цьому мені допоміг вкладку Аткінс. Я оновив свою відповідь.
Джозеф Сільбер

3
Зауважте, що в даний час Firefox підтримує лише "min-content" для значень ширини, а не для значень висоти, тому це не працюватиме у Firefox, якщо це має значення для вас. (Див., Наприклад, bugzilla.mozilla.org/show_bug.cgi?id=852367 )
dholbert

2
@dholbert - Проблема цих ручок у тому, що вони були загальнодоступними, тому кожен міг їх змінити. Я взяв на себе право власності на них, тож перейдіть: codepen.io/JosephSilber/pen/pmyHh
Джозеф

5
Так, це порушено в IE11
Стів

119

Я просто вирішив цю проблему дуже елегантно після багатьох спроб та помилок.

Перевірте мій пост у блозі: http://geon.github.io/programming/2016/02/24/flexbox-full-page-web-app-layout

В основному, щоб зробити клітинку флекси для прокрутки, ви повинні зробити всіх її батьків overflow: hidden; , інакше вона просто ігнорує ваші налаштування переповнення і замість цього зробить батьків більше.


11
Це працювало і в моєму випадку, але ось я дуже хотів би побачити пояснення, чому це працює. Здебільшого я вважаю, що специфікації CSS є абсолютно неприступними для подібних речей.
Маркріан

2
З вашого допису в блозі: "Я поняття не маю, чому це працює, і специфікації також нічого не говорять" . Отже, я шукаю пояснення, чому це працює. Я скуйовжував характеристики, але, як ви сказали, нічого з цього не вискакує.
Маркріан

3
Подумавши про це ще раз, я думаю, що це має сенс. Поведінка за замовчуванням розширюється, щоб кожен div розгортався, щоб містити всі його діти, тому не буде переповнення, щоб ховатися у вузлах листків. Вам потрібно примусити переповнення: приховано весь шлях від вершини DOM, тому жоден з батьків не має шансів розмістити своїх дітей, поки ви не спуститеся до вузла, який хочете переповнювати та прокручувати.
геон

3
Я не впевнений, що насправді це пояснює. Встановлення переповнення на прихований на елементі не зупиняє його розширення, щоб містити всіх його дітей, AFAIK. Згідно з MDN: "Властивість переповнення визначає, чи слід відсікати вміст, відображати смуги прокрутки або просто відображати вміст, коли він переповнює контейнер рівня блоку." Крім того, встановлення переповнення нічого іншого, окрім видимого, створює новий контекст форматування блоку - але це не може бути актуально, оскільки гнучкі контейнери вже створюють власний контекст форматування блоку: developer.mozilla.org/en-US/docs/Web/Guide / CSS /… .
Маркріан

1
Додам, що я погоджуюся, що ваше пояснення має інтуїтивне значення, але я не думаю, що це точне технічне пояснення, чого я хочу. Тільки зрозумівши причину, я зможу запам'ятати рішення в майбутньому!
Маркріан

55

Робота position:absolute;з flex:

Розмістіть гнучкий предмет за допомогою position: relative. Потім всередині нього додайте ще один <div>елемент із:

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

Це поширює елемент на межі його відносно розташованого батька, але не дозволяє розширити його. Всередині overflow: auto;буде працювати як слід.

  • фрагмент коду, включений у відповідь - Клацніть на введіть тут опис зображенняі натисніть на кнопку Повна сторінкапісля запуску фрагмента АБО
  • Клацніть тут для CODEPEN
  • Результат: введіть тут опис зображення

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

Щасти...


2
Це рішення особливо корисне, якщо компонент всередині має набір прокладки, тому що він добре зафіксує його в тому місці, де ви хочете. Це набагато простіше. (Так, ви можете встановити box-sizing: border-boxнатомість, але це може бути складніше для деяких сторонніх елементів управління).
Simon_Weaver

2
ти врятував мою ніч!
Botea Florin

2
Дякую. Я якось розчарований, що це потрібно, але я вдячний за пораду!
Матіас

9

Трохи пізно, але це може допомогти: http://webdesign.tutsplus.com/tutorials/how-to-make-responsive-scrollable-panels-with-flexbox--cms-23269

В основному потрібно поставити html, bodyщобheight: 100%; і обернути все своє вміст в<div class="wrap"> <!-- content --> </div>

CSS:

html, body {
  height: 100%;
}

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

Працювали для мене. Сподіваюся, це допомагає


Ви повинні бути дуже обережними при використанні "висота: 100 ВГт", оскільки вона по-різному вимірюється в iOS Safari проти Android. Один враховує висоту рядка URL, а інший - ні.
Шон Андерсон

7

Додати це:

align-items: flex-start;

до правила для .content {} . Принаймні, це фіксує це у вашій ручці як мінімум (як у Firefox, так і в Chrome).

За замовчуванням .contentмає align-items: stretchфункцію has , завдяки якій розмір усіх дітей, що працюють з автоматичним зростом, відповідає його власному зросту, за http://dev.w3.org/csswg/css-flexbox/#algo-stretch . Навпаки, значення flex-startдозволяє дітям обчислити власну висоту та вирівняти себе на її початковому краю (і перелити, і запустити смугу прокрутки).



Крім того, стовпчики вже не будуть однакової висоти, що є однією з головних визначних пам'яток флексбоксу.
Джозеф Сільбер

ГАРАЗД. Мені було не зрозуміло, що це обмеження дизайну - вибачте.
Дольберт

Відмінна пропозиція
Влад

1

Одне з питань, з яким я зіткнувся, полягає в тому, що для того, щоб мати смугу прокрутки, елементу потрібно вказати висоту (а не як%).

Трюк полягає в тому, щоб вкласти ще один набір дівок у кожному стовпчику та встановити дисплей батьків стовпця на згинання зі згинальним напрямком: стовпець.

    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>

І ось 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

Рішення цієї проблеми полягає лише в тому, щоб додати overflow: auto;до вмісту .content, щоб зробити обгортку вмісту прокручуваною.

Крім того, існують обставини, поряд із обгорткою Flexbox та overflowedвмістом, що прокручується, як цей коден .

Рішення полягає в тому, щоб додати overflow: hidden (or auto);до батьківського обгортка (встановлений з переповненням: auto;) навколо великого вмісту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.