Когда элементы flexbox переносятся в режиме столбца, контейнер не увеличивает свою ширину


я работаю над вложенным макетом flexbox, который должен работать следующим образом:

самый внешний уровень (ul#main) - это горизонтальный список, который должен расширяться вправо при добавлении в него дополнительных элементов. Если он становится слишком большим, должна быть горизонтальная полоса прокрутки.

#main {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* ...and more... */
}

каждый элемент этого списка (ul#main > li) имеет заголовок (ul#main > li > h2) и внутренний список (ul#main > li > ul.tasks). Этот внутренний список является вертикальным и должен быть обернут в столбцы, когда это необходимо. При обертывании в несколько столбцов, его ширина должна увеличиться, чтобы освободить место для большего количества предметов. Это увеличение ширины должно применяться также к содержащему элементу внешнего списка.

.tasks {
    flex-direction: column;
    flex-wrap: wrap;
    /* ...and more... */
}

моя проблема заключается в том, что внутренние списки не заворачивают, когда высота окна становится слишком мала. Я пробовал много подделок со всеми свойствами flex, пытаясь следовать рекомендациям по CSS-трюки дотошно, но не повезло.

этой JSFiddle показывает, что у меня так далеко.

ожидаемый результат(чего я хочу):

фактический результат(что я получаю):

старый результат(то, что я получил в 2015 году):

обновление

после некоторого расследования, это начинает выглядеть как большая проблема. все основные браузеры ведут себя так же путь, и это не имеет ничего общего с моим вложенным дизайном flexbox. Еще более простые макеты столбцов flexbox отказываются увеличивать ширину списка при обертывании элементов.

этой другие JSFiddle наглядно демонстрирует проблему. В текущих версиях Chrome, Firefox и IE11 все элементы переносятся правильно; высота списка увеличивается в row режим, но его ширина не увеличится в column режим. Кроме того, нет никакого немедленного оплавления элементов вообще при изменении высота a column режим, но есть в row режим.

на характеристики (посмотрите конкретно на пример 5) кажется, указывает на то, что то, что я хочу сделать, должно быть возможно.

может кто-нибудь придумать обходной путь к этой проблеме?

обновление 2

после многих экспериментов с использованием JavaScript для обновления высоты и ширины различных элементов во время событий изменения размера, я пришел к вывод, что это слишком сложно и слишком много проблем, чтобы попытаться решить его таким образом. Кроме того, добавление JavaScript определенно нарушает модель flexbox, которая должна быть максимально чистой.

сейчас я возвращаюсь к overflow-y: auto вместо flex-wrap: wrap так, что внутренний контейнер прокручивается вертикально, когда это необходимо. Это не очень красиво, но это один из путей вперед, который, по крайней мере, не слишком нарушает удобство использования.

3 101

3 ответа:

Проблема

это выглядит как фундаментальный недостаток в гибкой компоновке.

гибкий контейнер в направлении столбца не будет расширяться для размещения дополнительных столбцов. (Это не проблема flex-direction: row.)

этот вопрос задавался много раз (см. список ниже), без чистых ответов в CSS.

трудно закрепить это как ошибку, потому что проблема возникает во всех основных браузерах. Но это поднимает вопрос:

как это возможно, что все основные браузеры есть контейнер для разверните на wrap в направлении строки, но не в направлении столбца?

вы могли бы подумать, что по крайней мере один из них получит это право. Я могу только догадываться о причине. Возможно, это была технически сложная реализация и была отложена для этой итерации.

обновление: проблема, по-видимому, решена в Edge v16.


Иллюстрация Проблема

ОП создал полезную демонстрацию, иллюстрирующую проблему. Я копирую его здесь: http://jsfiddle.net/nwccdwLw/1/


Решение Вариантов

хакерские решения из сообщества переполнения стека:


Больше Анализа


другие сообщения, описывающие то же самое Проблема

возможное решение JS..

var ul = $("ul.ul-to-fix");

if(ul.find("li").length>{max_possible_rows)){
    if(!ul.hasClass("width-calculated")){
        ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
        ul.addClass("width-calculated");
     }
}

другой возможный подход:

ul.tasks {
  column-count: 2; /*or whatever */
}
li.task {
  display: inline-block;
}

https://developer.mozilla.org/en-US/docs/Web/CSS/column-count

вы также можете настроить margin-top of li.task:first-child если они не выровнены по верху.