Flex-grow не подбирает гибкие элементы, как ожидалось
Кажется, что содержимое внутри гибкого div влияет на его расчетный размер относительно свойства flex-grow
. Я делаю что-то неправильно?
В приведенной ниже скрипте вы увидите цифровую панель. Все строки содержат 3 номера, кроме нижней строки. Эта строка должна иметь "0" ширину из двух чисел, поэтому flex-grow: 2
и ":" (двоеточие) будет размером 1 число, следовательно flex-grow: 1
.
Я что-то упустил?
Правая сторона "0" должна быть выровнена с 8, 5 и 2 над ней. Это немного.
![введите описание изображения здесь]()
.numbers {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
flex-grow: 1;
justify-content: space-between;
}
.button {
display: flex;
flex-grow: 1;
justify-content: center;
align-items: center;
margin: 5px;
border-radius: 5px;
border: 1px solid gray;
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
}
.button#number0 {
flex-grow: 2;
}
.button#colon {
flex-grow: 1;
}
<div class="numbers">
<div class="row">
<div class="button number" id="number1">1</div>
<div class="button number" id="number2">2</div>
<div class="button number" id="number3">3</div>
</div>
<div class="row">
<div class="button number" id="number4">4</div>
<div class="button number" id="number5">5</div>
<div class="button number" id="number6">6</div>
</div>
<div class="row">
<div class="button number" id="number7">7</div>
<div class="button number" id="number8">8</div>
<div class="button number" id="number9">9</div>
</div>
<div class="row">
<div class="button number" id="number0">0</div>
<div class="button" id="colon">:</div>
</div>
</div>
Ответы
Ответ 1
Краткий анализ
Проблема состоит в том, что строки 1-3 имеют два горизонтальных поля, а строка 4 имеет только одну.
![enter image description here]()
При горизонтальных полях по 10 пикселей каждая строка 4 имеет на 10 пикселей больше свободного пространства, чем остальные строки. Это сбивает выравнивание столбцов.
Поскольку flex-grow
применяется только к свободному пространству и находится под сильным влиянием содержимого и полей, это не самый безопасный способ определения размера элементов Flex.
Попробуйте вместо этого flex-basis
base. Добавьте это к своему коду:
.button { flex-basis: 33.33%; }
#number0 { flex-basis: calc(66.67% + 10px); }
* { box-sizing: border-box; }
.numbers {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
flex-grow: 1;
justify-content: space-between;
}
.button {
display: flex;
flex-basis: 33.33%;
justify-content: center;
align-items: center;
margin: 5px;
border-radius: 5px;
border: 1px solid gray;
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
}
#number0 { flex-basis: calc(66.67% + 10px); }
* { box-sizing: border-box; }
<div class="numbers">
<div class="row">
<div class="button number" id="number1">1</div>
<div class="button number" id="number2">2</div>
<div class="button number" id="number3">3</div>
</div>
<div class="row">
<div class="button number" id="number4">4</div>
<div class="button number" id="number5">5</div>
<div class="button number" id="number6">6</div>
</div>
<div class="row">
<div class="button number" id="number7">7</div>
<div class="button number" id="number8">8</div>
<div class="button number" id="number9">9</div>
</div>
<div class="row">
<div class="button number" id="number0">0</div>
<div class="button" id="colon">:</div>
</div>
</div>
Ответ 2
Обновление 3:
Я выяснил еще один способ избавиться от несоосности.
Эта версия, вместе с обновлением 2: nd, работает с оригинальным html нетронутым и использует псевдоэлементы для создания кнопок, включающих кнопки наведения/щелчка.
flex
только версия
.row {
width: 60%;
margin: auto;
display: flex;
}
.button {
flex: 0 0 33.3%;
text-align: center;
position: relative;
padding: 10px 5px;
box-sizing: border-box;
pointer-events: none;
}
.button#number0 {
flex: 0 0 66.6%;
}
.button:before,
.button:after {
content: " ";
border-radius: 5px;
border: 1px solid gray;
cursor: pointer;
position: absolute;
left: 5px;
top: 5px;
right: 5px;
bottom: 5px;
pointer-events: auto;
}
.button:before {
background: rgba(255, 255, 255, 0.9);
z-index: -1
}
.button:hover:before {
background: rgba(0, 0, 0, 0.1);
}
.button:hover:after {
border: 2px solid red;
}
.button:active:before {
background: rgba(255, 0, 0, 0.5);
}
<div class="numbers">
<div class="row">
<div class="button number" id="number1">1</div>
<div class="button number" id="number2">2</div>
<div class="button number" id="number3">3</div>
</div>
<div class="row">
<div class="button number" id="number4">4</div>
<div class="button number" id="number5">5</div>
<div class="button number" id="number6">6</div>
</div>
<div class="row">
<div class="button number" id="number7">7</div>
<div class="button number" id="number8">8</div>
<div class="button number" id="number9">9</div>
</div>
<div class="row">
<div class="button number" id="number0">0</div>
<div class="button" id="colon">:</div>
</div>
</div>
Ответ 3
Я думаю, что все, что сказал Michael_B, верное. Только решения немного неудобны. Я лично не люблю вычислять. Он просто не чувствует себя хорошо.
Проблема у вас более общая. Вы накладываете слишком много обязанностей на один элемент. В этом случае это класс .button
. Flex и Margin с гибким ростом - это слишком большая ответственность. Попытайтесь разбить это. Это означает больше элементов DOM, но это избавляет вас от большой боли.
.numbers {
display: flex;
flex-direction: column;
max-width: 200px;
margin: 0 auto;
}
.row {
display: flex;
flex-direction: row;
flex-grow: 1;
justify-content: space-between;
}
.row > .box {
display: flex;
flex-basis: 33.3333%;
justify-content: center;
align-items: center;
}
.row > .box.box-2 {
flex-basis: 66.6667%;
}
.button {
border-radius: 5px;
border: 1px solid gray;
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
width: auto;
text-align: center;
margin: 5px;
width: 100%;
}
<div class="numbers">
<div class="row">
<div class="box"><div class="button number" id="number1">1</div></div>
<div class="box"><div class="button number" id="number2">2</div></div>
<div class="box"><div class="button number" id="number3">3</div></div>
</div>
<div class="row">
<div class="box"><div class="button number" id="number4">4</div></div>
<div class="box"><div class="button number" id="number5">5</div></div>
<div class="box"><div class="button number" id="number6">6</div></div>
</div>
<div class="row">
<div class="box"><div class="button number" id="number7">7</div></div>
<div class="box"><div class="button number" id="number8">8</div></div>
<div class="box"><div class="button number" id="number9">9</div></div>
</div>
<div class="row">
<div class="box box-2"><div class="button number" id="number0">0</div></div>
<div class="box"><div class="button" id="colon">:</div></div>
</div>
</div>
Ответ 4
flexbox, на мой взгляд, плохо реагирует на полях.
Лучший подход/обходной путь, который я предпочитаю, состоит в том, чтобы убедиться, что все дети Flex имеют 0 полей, установите контейнер flex на justify-content: space-between;
, а затем дайте детям общую ширину менее 100%. Остальная часть будет вашей маржой.
Другими словами, если вам нужно два элемента в строке, установите их шириной 49%, и у вас будет 2% пространства между ними. Три элемента, каждый по 32% в ширину, и у вас будет 2% между ними. В примере калькулятора ячейка 0
должна быть 66%, а остальные 32%.
Изменить: обратите внимание, что, поскольку причины (а именно, что content-box
ужасно), если у какого-либо из ваших детей есть границы, вам нужно использовать box-sizing: border-box
, чтобы мое предложение работало правильно.
https://jsfiddle.net/r3L1mtbe/2/
Ответ 5
Важно использовать стенографию для поддержки кросс-браузера:
.row {
display: flex;
flex-direction: row; /* <-- this is the default so unnecessary to state */
flex-grow: 1;
justify-content: space-between;
}
.button {
display: flex;
/* flex-grow: 1; replace with shorthand */
flex:1 0 100%; /* probably making the "width: 100%;" unnecessary */
justify-content: center;
}
.button#number0 {
/* flex-grow: 2; replace with shorthand */
flex:2 0 100%;
}
.button#colon {
/* flex-grow: 1; replace with shorthand */
flex:1 0 100%;
}