Получение 100% высоты внутри элемента flexbox

Я пытаюсь создать следующий макет, используя flexbox.

Верхняя черная полоса, средняя секция и нижняя черная полоса - это все элементы flex, которые являются потомками div-оболочки, находящегося внутри тега body, который выглядит следующим образом.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic' rel='stylesheet' type='text/css'>
    <link href="~/Styles/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Styles/font-awesome.min.css" rel="stylesheet" />
    <link href="~/Styles/ppt_site.css" rel="stylesheet" />
</head>
<body>
    <div class="wrapper">

        <div id="topRow">
        </div>

        <div id="centralRow">

            <div id="sidebarColumn">
            </div>

            <div id="contentColumn">
            </div>

        </div>

        <div id="bottomRow">
        </div>

    </div>

    @Section['customScripts']
    <script src="~/Scripts/siteGlobals.js"></script>

    <script src="~/requireconfig"></script>
    <script data-main="~/scripts/NewTemplatesAppLoader.js" src="~/requirejs"></script>

</body>
</html>

Таблица стилей, управляющая всем этим, выглядит следующим образом

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

.wrapper {
    display: flex;
    -ms-flex-direction: column;
    -webkit-flex-direction: column;
    flex-direction: column;
}

#topRow {
    background-color: black;
    color: white;
}

#centralRow {
    -ms-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    display: flex;
    -ms-flex-direction: row;
    -webkit-flex-direction: row;
    flex-direction: row;
}

#bottomRow {
    background-color: #333333;
    color: white;
}

#sidebarColumn {
    background-color: #B83B1D;
    color: white;
}

#contentColumn {
    -ms-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    background-color: #F7F7F7;
    color: black;
    padding: 10px;
    overflow-y: auto;
}

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

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

В идеале, я хочу, чтобы это был div, это гибкий контейнер, в который я мог бы затем поместить 4 flex-элемента, и каждый из них занимал четверть доступного пространства каждый, но, поскольку div с желтой рамкой, похоже, не может Посмотрите на высоту родительского контейнера (красная боковая панель, которая сама является гибким элементом), тогда он будет занимать только высоту пространства вокруг своего содержимого.

Я попытался обернуть его в большее количество элементов div и расположить эти div, я обернул дополнительные flex-блоки в дальнейшие div, я пробовал блоки, inline, табличные ячейки и почти все остальное, что я могу придумать.

Независимо от того, что я пытаюсь, я просто не могу получить контейнер с желтой рамкой такой же высоты, как его родитель.

Любые идеи кто-нибудь?

Обновление (на следующее утро)

Два предложенных решения действительно работают сами по себе, и они работают так, как я ожидал.

В моем конкретном случае, однако, они не работают.

Я использую NancyFX с его очень простым механизмом просмотра, и я использую KnockoutJS для создания "Веб-компонентов", чтобы я мог сохранить свои фрагменты для повторного использования.

Если я отредактирую свой "Основной шаблон" и вставлю элементы div прямо в разметку, вложенную ниже #sidebarColumn, я получу 4 элемента одинакового размера по желанию.

Однако на самом деле должно произойти следующее: мой шаблон выглядит следующим образом:

<div class="wrapper">

    <div id="topRow">
        @Section['topbarContent']
    </div>

    <div id="centralRow">

        <div id="sidebarColumn">
            @Section['sidebarContent']
        </div>

        <div id="contentColumn">
            @Section['bodyContent']
        </div>

    </div>

    <div id="bottomRow">
        @Section['bottombarContent']
    </div>

</div>

Если я удаляю "@Section['sidebarContent']" и помещаю div непосредственно в них, они работают.

Если я поместил div непосредственно в мою "Страницу", которая использует шаблон следующим образом:

@Master['shared/ppt_layout.html']

@Section['topbarContent']
    <toptoolbar></toptoolbar>
@EndSection

@Section['sidebarContent']
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
@EndSection

@Section['bodyContent']
    <h1>Body Content</h1>
    <p class="lead">I am the test page that uses a wide sidebar component</p>
    <p>If you notice however, I also have a top toolbar with title added to me, and a footer bar.</p>
    <p>We all use the same template however....</p>
@EndSection

@Section['bottombarContent']
    <footerbar></footerbar>
@EndSection

@Section['customScripts']
@EndSection

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

Так что по какой-то причине добавление контента, использование нокаут-компонентов - это то, что вызывает проблему.

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

Например, нижний колонтитул разделен на левую и правую части без каких-либо проблем, но вертикальное выравнивание просто отменяется.

3 ответа

Решение

Итак, после нескольких дней пыток я наконец понял, в чем проблема.

Я использую knockout.js в своем проекте, в частности компоненты knockout, и именно барьер между ними вызывает проблему.

Для тех, кто раньше не использовал компоненты KO, это довольно простой процесс. Вы создаете модель представления JS и небольшой фрагмент HTML, чтобы обеспечить поверхность отображения компонентов.

Затем вы используете:

ko.components.register("myComponent", {
    viewModel: "Components/myComponent.js",
    template: "Components/myComponent.html"
});

ko.applyBindings();

Чтобы зарегистрировать свой компонент.

Как только компонент зарегистрирован, вы можете просто использовать его, поставив

<myComponent></myComponent>

Где бы вы ни захотели добавить его на свою веб-страницу.

Теперь все в порядке, но... когда KO создает экземпляр компонента, он оставляет собственный тег на месте.

Так что, если вы представляете, что ваш компонент выглядит так

<div>
    <div>Item...</div>
    <div>Item...</div>
    <div>Item...</div>
    <div>Item...</div>
</div>

и ваша страница выглядит

<body>
    <div>
        <myComponent></myComponent>
    </div>
</body>

Тогда конечный результат будет выглядеть

<body>
    <div>
        <myComponent>
            <div>
                <div>Item...</div>
                <div>Item...</div>
                <div>Item...</div>
                <div>Item...</div>
            </div>
        </myComponent>
    </div>
</body>

Учитывая, что правила в приведенном выше CSS, моем и обоих респондентах были нацелены на div обертки, правило никогда не совпадало с целевым div, чтобы включить в нем flex.

Ключ (как я обнаружил методом проб и ошибок) заключается в использовании имени пользовательского тега, например:

#sidebarColumn > narrowsidebar {
     width: 70px;
     flex: 1;
     display: flex;
     flex-direction: column;
}

и затем продолжите дальнейшие операции сгибания от того родителя.

Тем не менее, это не объясняет, почему, когда вы делаете полный макет flexbox с нуля внутри компонента (то есть без каких-либо операций с изгибом на главной веб-странице и / или в шаблоне), у него все еще есть проблемы с вертикальным выравниванием, как Насколько я понимаю, нокаут не делает ничего с домом, который должен вызывать такое поведение.

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

Shawty

Использование flex: 1 гибкому ребенку, чтобы он охватывал максимально возможное пространство

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

/* header */
#topRow {
    background-color: black;
    color: white;
    height:20%;
}

/* footer */
#bottomRow {
    background-color: #333333;
    color: white;
    height:10%;
}

/* main */
#centralRow {
  height:70%;
  display: flex;
}

/* sidebar */
#sidebarColumn {
    background-color: #B83B1D;
    color: white;
    width:20%;
    display: flex;
    flex-direction: column;
}

#sidebarColumn nav {
  padding:1em;
  border:1px solid yellow;
  flex:1;
}

/* content */
#contentColumn {
  overflow: auto;
  flex:1;
}

.big {
  border:1px solid red;
  margin:1em;
  height:400px;
}
<div class="wrapper">

  <div id="topRow">
    header
  </div>

  <div id="centralRow">
    <div id="sidebarColumn">
      sidebar
      <nav>
        nav links
      </nav>
    </div>
    <div id="contentColumn">
      body content
      <div class="big">some big content</div>
    </div>
  </div>

  <div id="bottomRow">
    footer
  </div>
</div>

https://jsfiddle.net/azizn/y4hag5o3/

Вы можете использовать вложенный flexbox:

<div id="sidebarColumn">
  <div>...</div>
  <div>...</div>
  <div>...</div>
  <div>...</div>
</div>

#sidebarColumn {
  display: flex;
  flex-direction: column;
}
#sidebarColumn > div {
  flex: 1;
}

jsFiddle

Другие вопросы по тегам