Flex-grow no dimensiona los artículos flexibles como se esperaba

Parece que el contenido dentro de un div flexible afecta su tamaño calculado con respecto a la propiedad flex-grow . ¿Estoy haciendo algo mal?

En el violín provisto abajo, verás un teclado numérico. Todas las filas contienen 3 números excepto la fila inferior. Esa fila debe tener el ‘0’ como el ancho de 2 números, por lo tanto, flex-grow: 2 y ‘:’ (dos puntos) ser del tamaño de 1 número, por lo tanto, flex-grow: 1 .

¿Me estoy perdiendo de algo?

El lado derecho del ‘0’ debe estar alineado con el 8, 5 y 2 encima de él. Está un poco apagado.

enter image description here

 .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; } 
 
1
2
3
4
5
6
7
8
9
0
:

https://jsfiddle.net/0r4hemdu/

Parece que el contenido dentro de un div flexible afecta su tamaño calculado con respecto a la propiedad flex-grow . ¿Estoy haciendo algo mal?

La fuente de su problema no es el contenido dentro del elemento flexible.

En el violín provisto abajo, verás un teclado numérico. Todas las filas contienen 3 números excepto la fila inferior. Esa fila debería tener el ‘0’ como el ancho de 2 números, por lo tanto, flex-grow: 2 y ‘:’ el tamaño de 1 número, por lo tanto, flex-grow: 1 . ¿Me estoy perdiendo de algo?

Sí. Su interpretación de la propiedad flex-grow es incorrecta. flex-grow no está destinado a definir el tamaño de un elemento flexible. Su trabajo es distribuir espacio libre en el contenedor flexible entre los artículos flexibles.

Al aplicar flex-grow: 1 a un grupo de elementos flexibles, les está diciendo que distribuyan el espacio libre de manera equitativa entre ellos. Por esta razón, en su demostración, las filas uno, dos y tres tienen elementos flexibles de igual tamaño.

Cuando aplica flex-grow: 2 , le está diciendo al elemento flexible que consum el doble de espacio libre que los elementos con flex-grow: 1 . Esto no necesariamente significa que el elemento flexible tendrá el doble de tamaño.

Además, en su caso, incluso si flex-grow: 2 significaba el doble de tamaño, ¿cómo sabría incluir ese segundo margen de 10px desde las filas anteriores hasta su cálculo de ancho (que sería necesario para lograr la alineación que desea)? enter image description here

El motivo por el que la alineación está desactivada en la fila cuatro es porque solo tiene un margen de 10 píxeles.

Notará que si elimina la regla de margen obtiene la alineación deseada.

 .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; } 
 
1
2
3
4
5
6
7
8
9
0
:

Actualización 3:

Descubrí otra forma de deshacerme de la desalineación.

Esta versión, junto con la actualización 2: nd, funciona con el html original intacto, y está usando pseudoelementos para crear los botones, los efectos de desplazamiento / clic del botón incluidos.

solo flex versión

 .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); } 
 
1
2
3
4
5
6
7
8
9
0
:

Creo que todo lo que Michael_B dijo es correcto. Solo las soluciones son un poco incómodas. Personalmente no me gusta calc. Simplemente no se siente bien.

El problema que tienes es uno más general. Usted pone demasiadas responsabilidades en un elemento. En este caso es la clase .button . Flex y Margin con flex-grow es demasiada responsabilidad. Intenta dividir eso. Significa más elementos DOM, pero te ahorra mucho dolor.

 .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%; } 
 
1
2
3
4
5
6
7
8
9
0
:

Flexbox no responde bien a los márgenes, en mi opinión.

El mejor enfoque / solución alternativa que prefiero es asegurarse de que todos los niños flexibles tengan 0 márgenes, configure el contenedor flexible para justify-content: space-between; , y luego déles a los niños un ancho total inferior al 100%. El rest será su margen.

En otras palabras, si desea dos elementos por fila, configure cada uno al 49% de ancho y tendrá un 2% de espacio entre ellos. Tres elementos, cada uno al 32% de ancho y tendrás un 2% entre ellos. En el ejemplo de la calculadora, la celda 0 debe tener un 66% de ancho y el rest un 32%.

Editar: tenga en cuenta que, debido a razones (es decir, que content-box es terrible), si alguno de sus hijos tiene bordes necesitará usar box-sizing: border-box para que mi sugerencia funcione correctamente.

https://jsfiddle.net/r3L1mtbe/2/

Es importante usar la abreviatura para acomodar el soporte de navegador cruzado:

 .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%; }