Получение 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>
Вы можете использовать вложенный flexbox:
<div id="sidebarColumn">
<div>...</div>
<div>...</div>
<div>...</div>
<div>...</div>
</div>
#sidebarColumn {
display: flex;
flex-direction: column;
}
#sidebarColumn > div {
flex: 1;
}