Css сетка квадратов с flexbox
Я пытаюсь создать гибкую сетку квадратов. Квадраты должны быть изменены в соответствии с шириной окна просмотра. Квадраты не должны изменять размер при изменении высоты окна просмотра.
Мне удалось настроить ширину каждого квадрата, но я не знаю, как сделать элементы квадратными и как увеличить их высоту при изменении ширины видового экрана.
В примере на скрипке ниже семь квадратов должны всегда располагаться горизонтально, и они должны масштабироваться как квадраты. Мне все равно, сколько строк видно.
Загадка здесь http://jsfiddle.net/gonyhvz8/11/
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row;
justify-content: space-around;
height: 50px;
line-height:30px;
}
.flex-item {
background: tomato;
margin: 5px;
color: white;
font-weight: bold;
font-size: 1.5em;
text-align: center;
flex: 1 0 0px;
height: auto;
}
Ответы
Ответ 1
вы не должны устанавливать какой-либо размер.
вы можете использовать дополнительный элемент или псевдоэлемент с вертикальным заполнением в%. это позволит вам использовать ширину в качестве ссылки: фрагмент для отображения:
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row;
justify-content: space-around;
line-height:30px;
}
.flex-item {
background: tomato;
margin: 5px;
color: white;
font-weight: bold;
font-size: 1.5em;
text-align: center;
flex: 1 0 auto;
height:auto;
}
.flex-item:before {
content:'';
float:left;
padding-top:100%;
}
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
</body>
Ответ 2
Для тех, кто также хочет использовать display: flex
внутри квадратных div, вам нужно использовать display: table
для элемента :before
, иначе квадрат будет работать с Chrome, но не будет работать с Firefox или Edge (как Firefox 47 и Edge 13).
В нижеприведенном фрагменте, который должен работать для всех браузеров, я также демонстрирую, как обматывать неограниченные элементы с процентными столбцами (в данном случае 20%) и разделять их с заполнением и внутренними div, поскольку поля с процентами не работают правильно в FF и, конечно, Edge.
.flex-container {
display: flex;
justify-content: start;
flex-wrap: wrap;
}
.flex-cell {
flex: 0 0 20%;
display: flex;
justify-content: center;
align-items: stretch;
padding: 0.5rem;
box-sizing: border-box;
}
.flex-cell:before {
content: '';
display: table;
padding-top: 100%;
}
.flex-item {
flex-grow: 1;
border: 1px solid black;
background: tomato;
color: white;
display: flex;
justify-content: center;
align-items: center;
}
<body>
<div class="flex-container">
<div class="flex-cell">
<div class="flex-item">1</div>
</div>
<div class="flex-cell">
<div class="flex-item">2</div>
</div>
<div class="flex-cell">
<div class="flex-item">3</div>
</div>
<div class="flex-cell">
<div class="flex-item">4</div>
</div>
<div class="flex-cell">
<div class="flex-item">5</div>
</div>
<div class="flex-cell">
<div class="flex-item">6</div>
</div>
<div class="flex-cell">
<div class="flex-item">7</div>
</div>
<div class="flex-cell">
<div class="flex-item">8</div>
</div>
<div class="flex-cell">
<div class="flex-item">9</div>
</div>
<div class="flex-cell">
<div class="flex-item">10</div>
</div>
<div class="flex-cell">
<div class="flex-item">11</div>
</div>
<div class="flex-cell">
<div class="flex-item">12</div>
</div>
</div>
</body>
Ответ 3
Обычным трюком для поддержания пропорции является использование того факта, что процентные значения поля и/или верхнего и нижнего полей вычисляются на основе ширины содержащего элемента, а не высоты.
Вы можете просмотреть негибкую версию этого вопроса ЗДЕСЬ
Однако вы хотели бы иметь flex
дело с шириной ваших элементов, а не устанавливать ширину, основанную на процентах. Для этого я придумал вариант такого подхода, который будет работать с flex:
.flex-item:before {
content: "";
display: block;
padding-top: 100%;
float: left;
}
Трюк здесь заключается в использовании псевдоэлемента :before
для вставки элемента ширины 0 с padding-top
100%. Это 100% составляет 100% от ширины, что означает, что этот элемент без содержимого будет одинаково высок, как его контейнер. Это растянет гибкий элемент на ту же высоту, что и его ширина:
Кроме того, вам нужно будет удалить определенную высоту из вашего гибкого контейнера или высота не может расти. Вы также можете добавить min-width: 1.5em
, чтобы ваши элементы не уменьшались ниже высоты символа, который у вас есть на каждом квадрате.
http://jsfiddle.net/gonyhvz8/14/
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row;
justify-content: space-around;
line-height:30px;
}
.flex-item {
background: tomato;
margin: 5px;
color: white;
font-weight: bold;
font-size: 1.5em;
text-align: center;
flex: 1 0 0px;
min-width: 1.5em;
}
.flex-item:before {
content: "";
display: block;
padding-top: 100%;
float: left;
}
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
</body>
Ответ 4
Конечно, хорошо использовать flexboxes, но упомянутое решение имеет недостаток гибкости, даже если он использует flexboxes
. Вы не можете настроить плавающие ящики. Вы ограничены, чтобы установить количество ящиков на строку раньше.
В этом решении вы можете адаптировать динамическую ширину плитки/квадрата и поплавать им, как вам нравится. Если вы попробуете это с помощью flexboxes, у вас возникнет проблема с padding-top
, потому что она не ориентируется на заданную ширину содержащихся блоков.
Решение без flexboxes
, но более гибкое:
.flex-container {
padding: 0;
margin: -5px;
font-size: 0;
font-family: Helvetica, Arial, sans-serif;
}
.flex-item {
position: relative;
display: inline-block;
height: 0;
width: 100%;
padding-top: 100%;
height: auto;
font-size: 20px;
color: white;
font-weight: bold;
text-align: center;
}
@media (min-width: 480px) {
.flex-item {
width: 33.3333%;
padding-top: 33.3333%;
}
}
@media (min-width: 768px) {
.flex-item {
width: 25%;
padding-top: 25%;
}
}
.flex-item-inner {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: 10px;
background: tomato;
}
<body>
<div class="flex-container">
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
1
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
2
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
3
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
4
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
5
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
6
</div>
</div>
</div>
</div>
</body>