Mejor manera de establecer la distancia entre los elementos de flexbox

781

Para establecer la distancia mínima entre los elementos de flexbox que estoy usando margin: 0 5pxen .itemy margin: 0 -5pxen el contenedor. Para mí parece un truco, pero no puedo encontrar una mejor manera de hacerlo.

Ejemplo

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  margin: 0 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Sasha Koss
fuente
29
No es un truco, es uno de los métodos previstos para alinear elementos. Sin embargo, hay otras propiedades. Ver w3.org/TR/css3-flexbox/#alignment
BoltClock
44
Si, lo entiendo. Pero, por ejemplo, existe una propiedad de espacio entre columnas que nos da la capacidad de controlar la distancia desde el contenedor: w3.org/TR/css3-multicol/#column-gap
Sasha Koss
Porque es un colapso del margen de la caja flexible. La otra pregunta tiene la respuesta correcta de [¿Cómo puedo detener el colapso del último margen en la caja flexible? ] ( stackoverflow.com/questions/38993170/… )
Jack Yang
66
El nivel 3 del módulo de alineación de cuadros CSS incluye una sección sobre los espacios entre cuadros , que se aplica a elementos de varias columnas, contenedores flexibles y contenedores de cuadrícula. Finalmente, esto será simple como: row-gap: 5px- hecho.
Danield
2
@JohnCarrell firefox ya admite la gappropiedad en contenedores flexibles ( caniuse )
Danield

Respuestas:

428
  • Flexbox no tiene márgenes colapsables.
  • Flexbox no tiene nada parecido a las border-spacingtablas (excepto la propiedad CSS gapque no es compatible con la mayoría de los navegadores, caniuse )

Por lo tanto, lograr lo que está pidiendo es un poco más difícil.

En mi experiencia, la forma "más limpia" que no utiliza :first-child/ :last-childy funciona sin ninguna modificación flex-wrap:wrapes establecer padding:5pxen el contenedor y margin:5pxen los niños. Eso producirá una 10pxbrecha entre cada niño y entre cada niño y sus padres.

Manifestación

.upper
{
  margin:30px;
  display:flex;
  flex-direction:row;
  width:300px;
  height:80px;
  border:1px red solid;

  padding:5px; /* this */
}

.upper > div
{
  flex:1 1 auto;
  border:1px red solid;
  text-align:center;

  margin:5px;  /* and that, will result in a 10px gap */
}

.upper.mc /* multicol test */
{flex-direction:column;flex-wrap:wrap;width:200px;height:200px;}
<div class="upper">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>

<div class="upper mc">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>

Todos los trabajadores son esenciales
fuente
220
Esto no logra lo mismo que la pregunta, tendrá una sangría de 10px en el extremo izquierdo y derecho, lo que supongo que no tienen la intención de tener. Por lo tanto, los márgenes negativos en la pregunta original.
Chris Nicola
17
¿Qué pasa si se orderestablece la propiedad? :first-child/:last-childNo funcionará como se esperaba.
Guria
44
"Flexbox no tiene márgenes de colapso". Muy perspicaz, y aparentemente cierto, pero ¿puedo pedir una cita?
chharvey
2
¿No es esta una respuesta peor que la pregunta original? Este método requiere que tenga espacio alrededor del contenedor y la canaleta siempre debe ser un número par.
limitlessloop
77
@chharvey, de la especificación w3.org/TR/css-flexbox-1/#item-margins , "Los márgenes de los elementos flexibles adyacentes no colapsan".
romellem
197

Esto no es un truco. Bootstrap y su cuadrícula también utilizan la misma técnica, aunque, en lugar de margen, bootstrap utiliza relleno para sus cols.

.row {
  margin:0 -15px;
}
.col-xx-xx {
  padding:0 15px;
}
Roumelis George
fuente
1
El único problema con este método es mantener elementos de igual altura con colores de fondo. El posicionamiento absoluto con height:100%; width:100%ignora el relleno del elemento.
Steven Vachon
3
El problema aquí es con IE10 y 11. los flex-basisvalores no tienen en cuenta box-sizing: border-box, por lo que un niño con cualquier relleno o borde desbordará al padre (o se ajustará en este caso). Fuente
Carson
18
Hay otro problema con este enfoque: ajustar el margen de esta manera puede expandir el ancho de la página. Demostración: jsfiddle.net/a97tatf6/1
Nathan Osman
44
Aunque estoy de acuerdo en que esto no es un hack, el hecho de que algo se use ampliamente no significa que no sea un hack. Vea polyfills, parches de seguridad temporales, edición hexadecimal, etc., etc.
William
15
Por supuesto, esto es un truco. Porque Bootstrap usa este método no significa que no sea un truco. Simplemente significa que Bootstrap usa un hack.
Michael Benjamin
108

Flexbox y css calc con soporte para múltiples filas

Hola, a continuación es mi solución de trabajo para todos los navegadores que admiten flexbox. Sin márgenes negativos.

Fiddle Demo

   
.flexbox {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
}

.flexbox > div {
  /*
    1/3  - 3 columns per row
    10px - spacing between columns 
  */
  box-sizing: border-box;
  margin: 10px 10px 0 0;
  outline: 1px dotted red;
  width: calc(1/3*100% - (1 - 1/3)*10px);
}

/*
  align last row columns to the left
  3n - 3 columns per row
*/
.flexbox > div:nth-child(3n) {
  margin-right: 0;
}

.flexbox::after {
  content: '';
  flex: auto;
}

/*
  remove top margin from first row
  -n+3 - 3 columns per row 
*/
.flexbox > div:nth-child(-n+3) {
  margin-top: 0;
}
<div class="flexbox">
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
</div>

Tome nota de que este código puede ser más corto usando SASS

Actualización 2020.II.11 Columnas alineadas en la última fila a la izquierda

Actualización 2020.II.14 Se eliminó el margen inferior en la última fila

Dariusz Sikorski
fuente
13
Me gusta esta solución, pero falla si solo hay 2 elementos en la última fila. Los elementos no se apilan juntos debido a la justify-content.
James Brantly
44
para solucionar el problema de dos elementos simplemente cambie a justify-content: space-evenly;o justify-content: space-around;.
Paul Rooney
66
@PaulRooney En el sitio con múltiples listas, es posible que no siempre sepa la cantidad de elementos, si las listas son generadas por un CMS.
NinjaFart
1
@ 1.21gigawatts No haga cambios arbitrarios en el código / respuesta de otra persona; escribe tu propia respuesta en su lugar.
TylerH
2
@ TylerH No fue arbitrario. La pregunta preguntaba cómo, "... establecer la distancia entre los elementos de flexbox". Esta respuesta no muestra el tamaño de la canaleta. Establecer un color de fondo muestra la canaleta. Agregar un borde muestra que hay un margen debajo de la última fila.
1.21 gigavatios
93

Puedes usar bordes transparentes.

He contemplado este problema al intentar construir un modelo de cuadrícula flexible que puede recurrir a un modelo de tablas + celdas de tabla para navegadores más antiguos. Y las fronteras para canalones de columna me parecieron la mejor opción apropiada. es decir, las celdas de tabla no tienen márgenes.

p.ej

.column{
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 10px solid transparent;
}

También tenga en cuenta que necesita min-width: 50px;flexbox. El modelo flexible no manejará tamaños fijos a menos que lo haga flex: none;en el elemento secundario particular que desea como fijo y, por lo tanto, excluido de ser "flexi". http://jsfiddle.net/GLpUp/4/ Pero todas las columnas juntas flex:none;ya no es un modelo flexible. Aquí hay algo más cercano a un modelo flexible: http://jsfiddle.net/GLpUp/5/

Por lo tanto, puede usar los márgenes normalmente si no necesita el respaldo de celda de tabla para navegadores más antiguos. http://jsfiddle.net/GLpUp/3/

La configuración background-clip: padding-box;será necesaria al usar un fondo, ya que de lo contrario el fondo fluirá hacia el área del borde transparente.

hexalys
fuente
55
gran respuesta. los márgenes se usan de manera diferente en los flexbox's (como para absorber espacio adicional), por lo que los bordes transparentes proporcionan una solución excelente para elementos espaciados uniformemente que pueden envolverse con un comportamiento similar a los márgenes
Eolis
44
excepto cuando utiliza el color de fondo, su fondo excede los límites deseados.
ahnbizcad
2
@ahnbizcad Bueno, con diferentes colores de fondo, puede usar el blanco o el color adecuado dependiendo de la forma en que sea el fondo.
hexalys
27
@ahnbizcad: Si no necesita soporte para IE8, esta es una solución mejor:background-clip: padding-box
Albin
55
¡El comentario de Albin aquí necesita más votos! Esta es la mejor solución. Los bordes transparentes, en combinación con background-clip: padding-box (y márgenes negativos en el contenedor, si es necesario, para una alineación adecuada de los bordes) son una solución perfecta. IE8 no es compatible con flexbox de todos modos, por lo que su falta de soporte para clip de fondo no debería importar.
Brian
74

Esta solución funcionará para todos los casos, incluso si hay varias filas o cualquier número de elementos. Pero el recuento de la sección debe ser el mismo que desea 4 en la primera fila y 3 es la segunda fila, no funcionará de esa manera, el espacio para el 4to contenido estará en blanco y el contenedor no se llenará.

Estamos usando display: grid; y sus propiedades.

#box {
  display: grid;
  width: 100px;
  grid-gap: 5px;
  /* Space between items */
  grid-template-columns: 1fr 1fr 1fr 1fr;
  /* Decide the number of columns and size */
}

.item {
  background: gray;
  width: 100%;
  /* width is not necessary only added this to understand that width works as 100% to the grid template allocated space **DEFAULT WIDTH WILL BE 100%** */
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

La desventaja de este método es que Mobile Opera Mini no será compatible y en PC solo funciona después de IE10 .

Nota para la compatibilidad completa del navegador, incluido IE11, utilice Autoprefixer


ANTIGUA RESPUESTA

No lo piense como una solución antigua, sigue siendo una de las mejores si solo desea una sola fila de elementos y funcionará con todos los navegadores.

Este método lo utiliza la combinación de hermanos CSS , por lo que también puede manipularlo de muchas otras maneras, pero si su combinación es incorrecta, también puede causar problemas.

.item+.item{
  margin-left: 5px;
}

El siguiente código hará el truco. En este método, no hay necesidad de dar margin: 0 -5px;al #boxenvoltorio.

Una muestra de trabajo para usted:

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 22px;
  height: 50px;
}
.item+.item{
 margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

weBBer
fuente
Edité su respuesta basada en la cuadrícula para demostrar que funciona correctamente, incluso si la fila final tiene menos elementos. Para demostrar que funciona en ese caso. (Siéntase libre de revertir si no le gusta este cambio.)
ToolmakerSteve
Según esta pregunta, solo pidieron llenar el espacio correctamente con los elementos secundarios sin un truco, eso es lo que hice, usando la cuadrícula que podemos administrar según lo grid-template-columnsque definimos no dinámicamente. Entonces, si le das el valor 1fr 1fr 1fr 1fr, dividirá el div en 4fractionse intentará llenar los elementos secundarios en cada uno fractions, que yo sepa, esa es la única forma de hacerlo grid. Lo que he dicho en la respuesta es que si el usuario necesita dividir el div en 4 y usarlos con muchos elementos, incluso para varias filas, gidesto ayudará.
weBBer
69

Puede usarlo & > * + *como selector para emular un flex-gap(para una sola línea):

#box { display: flex; width: 230px; outline: 1px solid blue; }
.item { background: gray; width: 50px; height: 100px; }

/* ----- Flexbox gap: ----- */

#box > * + * {
  margin-left: 10px;
}
<div id='box'>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
</div>

Si necesita admitir envoltura flexible , puede usar un elemento envoltorio:

.flex { display: flex; flex-wrap: wrap;  }
.box { background: gray; height: 100px; min-width: 100px; flex: auto; }
.flex-wrapper {outline: 1px solid red; }

/* ----- Flex gap 10px: ----- */

.flex > * {
  margin: 5px;
}
.flex {
  margin: -5px;
}
.flex-wrapper {
  width: 400px; /* optional */
  overflow: hidden; /* optional */
}
<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
  </div>
</div>

Hacer asíncrono
fuente
3
Solución limpia Funciona para cualquier cantidad de elementos secundarios flexibles.
Konrad Gałęzowski
1
Esto era lo que estaba buscando y funcionó muy bien para mí 👍
Paul Odeon
Sin embargo, un punto a tener en cuenta es que el *operador no aumenta la especificidad como cabría esperar. Entonces, dependiendo de su CSS existente, es posible que necesite aumentar la especificidad en el .flex > *selector o agregar !importanta la regla si hay otros selectores que aplican margen a ese elemento.
Paul Odeon
La mejor solución 👍
o01
26

Supongamos que si desea establecer 10pxespacio entre los elementos, puede configurarlo .item {margin-right:10px;}para todos y restablecerlo en el último.item:last-child {margin-right:0;}

También puede usar el hermano general ~o el siguiente +selector de hermanos para establecer el margen izquierdo en los elementos, excluyendo el primero .item ~ .item {margin-left:10px;}o usar.item:not(:last-child) {margin-right: 10px;}

Flexbox es tan inteligente que recalcula automáticamente y distribuye equitativamente la cuadrícula.

body {
  margin: 0;
}

.container {
  display: flex;
}

.item {
  flex: 1;
  background: gray;
  height: 50px;
}

.item:not(:last-child) {
  margin-right: 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Si desea permitir el ajuste flexible , consulte el siguiente ejemplo.

body {
  margin: 0;
}

.container {
  display: flex;
  flex-wrap: wrap;
  margin-left: -10px;
}

.item {
  flex: 0 0 calc(50% - 10px);
  background: gray;
  height: 50px;
  margin: 0 0 10px 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Pegatinas
fuente
66
Esto no funcionaría si los elementos están envueltos, ya :last-childque no afecta a cada último niño al final de una línea, ¿correcto?
Flimm
2
@Flimm Agregué un enfoque para trabajar con flex wrap, consulte la segunda parte anterior.
Pegatinas
La mejor respuesta para mí ... ¡simple, limpio, eficiente! Funcionó perfectamente con flex wrap, gracias
Matthieu Marcé
16

He encontrado una solución que se basa en el selector general de hermanos, ~ , y permite el anidamiento infinito.

Vea este bolígrafo de código para un ejemplo de trabajo

Básicamente, dentro de los contenedores de columnas, cada niño precedido por otro niño obtiene un margen superior. Del mismo modo, dentro de cada contenedor de filas, cada niño precedido por otro obtiene un margen izquierdo.

.box {
  display: flex;
  flex-grow: 1;
  flex-shrink: 1;
}

.box.columns {
  flex-direction: row;
}

.box.columns>.box~.box {
  margin-left: 5px;
}

.box.rows {
  flex-direction: column;
}

.box.rows>.box~.box {
  margin-top: 5px;
}
<div class="box columns">
  <div class="box" style="background-color: red;"></div>
  <div class="box rows">
    <div class="box rows">
      <div class="box" style="background-color: blue;"></div>
      <div class="box" style="background-color: orange;"></div>
      <div class="box columns">
        <div class="box" style="background-color: yellow;"></div>
        <div class="box" style="background-color: pink;"></div>
      </div>
    </div>
    <div class="box" style="background-color: green;"></div>
  </div>
</div>

Simon Epskamp
fuente
Esto da como resultado elementos de diferentes tamaños debido a que los márgenes no se aplican globalmente.
Steven Vachon
También necesitará agregar un poco de CSS adicional para manejar pantallas más pequeñas, ya que se ve un poco extraño en dispositivos móviles, aplicaría la regla .box ~ .box a pantallas más grandes y para pantallas más pequeñas, establezca que la clase .box tenga un ancho máximo del 100% y un margen inferior.
rhysclay
14

Continuando con la respuesta de sawa, aquí hay una versión ligeramente mejorada que le permite establecer un espacio fijo entre los elementos sin el margen circundante.

http://jsfiddle.net/chris00/s52wmgtq/49/

También se incluye la versión Safari "-webkit-flex".

.outer1 {
    background-color: orange;
    padding: 10px;
}

.outer0 {
    background-color: green;
    overflow: hidden;
}

.container
{
    display: flex;
    display: -webkit-flex;
    flex-wrap: wrap;    
    -webkit-flex-wrap: wrap;
    background-color: rgba(0, 0, 255, 0.5);
    margin-left: -10px;
    margin-top: -10px;
}

.item
{
    flex-grow: 1;
    -webkit-flex-grow: 1;
    background-color: rgba(255, 0, 0, 0.5);
    width: 100px;
    padding: 10px;
    margin-left: 10px;
    margin-top: 10px;
    text-align: center;
    color: white;
}

<div class="outer1">
    <div class="outer0">
        <div class="container">
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
        </div>
    </div>
</div>
Chris
fuente
2
¿No es esto esencialmente lo mismo que el ejemplo dado en la pregunta?
Ford
9

He usado esto para columnas de ancho fijo y envuelto. La clave aquí escalc()

Muestra SCSS

$gap: 10px;

dl {
  display: flex;
  flex-wrap: wrap;
  padding: $gap/2;

  dt, dd {
    margin: $gap/2;}

  dt { // full width, acts as header
    flex: 0 0 calc(100% - #{$gap});}

  dd { // default grid: four columns 
    flex: 0 0 calc(25% - #{$gap});}

  .half { // hall width columns
    flex: 0 0 calc(50% - #{$gap});}

}

Muestra completa de Codepen

Veiko Jääger
fuente
2
Esto todavía agrega una canaleta antes del primero y después del último elemento, lo que OP evita el uso de márgenes negativos.
herman
2
Flexbox no admite calc () dentro del elemento "flex" en IE 11.
Adam Šipický
No se puede usar siempre. imagínese si también se necesita un límite para niños directos
Andris
9

Un contenedor flexible con margen -x (negativo) y elementos flexibles con margen x (positivo) o relleno, ambos conducen al resultado visual deseado: los elementos flexibles tienen un espacio fijo de 2x solo entre sí.

Parece ser simplemente una cuestión de preferencia, ya sea usar margen o relleno en los elementos flexibles.

En este ejemplo, los elementos flexibles se escalan dinámicamente para preservar el espacio fijo:

.flex-container { 
  margin: 0 -5px;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.flex-item {
  margin: 0 5px; // Alternatively: padding: 0 5px;
  flex: 1 0 auto;
}
Tim
fuente
3
Lo siento, no lo entendí. ¿Qué novedades presenta su respuesta que no se dice directamente en la pregunta?
usuario
En primer lugar, quería resumir que tanto el margen como el relleno en el elemento flexible conducen al resultado deseado, porque las respuestas existentes solo mencionan uno u otro. En segundo lugar, quería dar un ejemplo, donde se conservan los huecos al escalar los elementos flexibles.
Tim
Aquí hay un ejemplo de codepen que muestra este efecto. codepen.io/dalgard/pen/Dbnus
pedalpete
8

Eventualmente agregarán la gappropiedad a flexbox. Hasta entonces, podría usar la cuadrícula CSS que ya tiene la gappropiedad, y solo tener una sola fila. Más agradable que lidiar con los márgenes.

Ollie Williams
fuente
Debate aquí: github.com/w3c/csswg-drafts/issues/1696 : también simplificarán la asignación de nombres a través de las columnas CSS Grid, Flexbox y CSS.
Frank Lämmer
6

CSS gapPropiedad :

¡Hay una nueva gappropiedad CSS para diseños de múltiples columnas, flexbox y cuadrícula que funciona en algunos navegadores ahora! (Consulte ¿Puedo usar el enlace 1 ; enlace 2 ).

#box {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  background-color: red;
  gap: 10px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Al momento de escribir, esto solo funciona en Firefox tristemente. Actualmente funciona en Chrome si habilita "Habilitar funciones experimentales de la plataforma web" en about:flags.

Flimm
fuente
5

Usando Flexbox en mi solución, he usado la justify-contentpropiedad para el elemento padre (contenedor) y he especificado los márgenes dentro de la flex-basispropiedad de los elementos. Verifique el fragmento de código a continuación:

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-bottom: 10px;
}

.item {
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #999;
}

.item-1-4 {
  flex-basis: calc(25% - 10px);
}

.item-1-3 {
  flex-basis: calc(33.33333% - 10px);
}

.item-1-2 {
  flex-basis: calc(50% - 10px);
}
<div class="container">
  <div class="item item-1-4">1</div>
  <div class="item item-1-4">2</div>
  <div class="item item-1-4">3</div>
  <div class="item item-1-4">4</div>
</div>
<div class="container">
  <div class="item item-1-3">1</div>
  <div class="item item-1-3">2</div>
  <div class="item item-1-3">3</div>
</div>
<div class="container">
  <div class="item item-1-2">1</div>
  <div class="item item-1-2">2</div>
</div>

iClusterDev
fuente
5

Con flexbox, crear canales es un dolor, especialmente cuando se trata de envolver.

Debe usar márgenes negativos ( como se muestra en la pregunta ):

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}

... o modifique el HTML ( como se muestra en otra respuesta ):

<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
            ...
  </div>
</div>

... o algo mas.

En cualquier caso, necesitas un truco feo para que funcione porque flexbox no proporciona una función " flex-gap" ( al menos por ahora ).

Sin embargo, el problema de las canaletas es simple y fácil con CSS Grid Layout.

La especificación de cuadrícula proporciona propiedades que crean espacio entre los elementos de la cuadrícula, mientras ignora el espacio entre los elementos y el contenedor. Estas propiedades son:

  • grid-column-gap
  • grid-row-gap
  • grid-gap (la abreviatura de ambas propiedades anteriores)

Recientemente, la especificación se ha actualizado para cumplir con el Módulo de alineación de cajas CSS , que proporciona un conjunto de propiedades de alineación para usar en todos los modelos de cajas. Entonces las propiedades son ahora:

  • column-gap
  • row-gap
  • gap (taquigrafía)

Sin embargo, no todos los navegadores compatibles con Grid admiten las propiedades más nuevas, por lo que utilizaré las versiones originales en la demostración a continuación.

Además, si se necesita espacio entre los artículos y el contenedor, padding el contenedor funciona bien (consulte el tercer ejemplo en la demostración a continuación).

De la especificación:

10.1 Canales: los row-gap, column-gapy gap propiedades

Las propiedades row-gapy column-gap(y su gapabreviatura), cuando se especifican en un contenedor de cuadrícula, definen los canales entre las filas y las columnas de la cuadrícula. Su sintaxis se define en CSS Box Alignment 3 §8 Brechas entre cuadros .

El efecto de estas propiedades es como si las líneas de cuadrícula afectadas adquirieran grosor: la pista de cuadrícula entre dos líneas de cuadrícula es el espacio entre las canaletas que las representan.

.box {
  display: inline-grid;
  grid-auto-rows: 50px;
  grid-template-columns: repeat(4, 50px);
  border: 1px solid black;
}

.one {
  grid-column-gap: 5px;
}

.two {
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

.three {
  grid-gap: 10px;
  padding: 10px;
}

.item {
  background: lightgray;
}
<div class='box one'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box two'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box three'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Más información:

Michael Benjamin
fuente
4

¿Por qué no hacerlo así?

.item + .item {
    margin-left: 5px;
}

Esto usa el selector de hermanos adyacentes , para dar todos los .itemelementos, excepto el primero a margin-left. Gracias a flexbox, esto incluso da como resultado elementos igualmente anchos. Esto también podría hacerse con elementos posicionados verticalmente y margin-top, por supuesto.

tillsanders
fuente
8
Esto funcionaría siempre que los elementos flexibles estén siempre en una sola fila. Si se permite envolver, entonces probablemente no sea suficiente.
Nick F
4

Aquí está mi solución, que no requiere establecer ninguna clase en los elementos secundarios:

.flex-inline-row {
    display: inline-flex;
    flex-direction: row;
}

.flex-inline-row.flex-spacing-4px > :not(:last-child) {
    margin-right: 4px;
}

Uso:

<div class="flex-inline-row flex-spacing-4px">
  <span>Testing</span>
  <span>123</span>
</div>

La misma técnica se puede utilizar para filas y columnas flexibles normales además del ejemplo en línea dado anteriormente, y se puede ampliar con clases para espaciado que no sea 4px.

MK10
fuente
4

A menudo uso el operador + para tales casos

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
.item + .item {
    margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

wutzebaer
fuente
3

Creo que la forma más fácil de hacerlo es con porcentajes y simplemente permitiendo que el margen aumente su ancho

Esto significa que terminas con algo como esto si usas tu ejemplo

#box {
   display: flex;
}

.item {
   flex: 1 1 23%;
   margin: 0 1%;
}

Significa que sus valores se basan en el ancho, lo que podría no ser bueno para todos.

Lukefrake
fuente
Acabo de encontrar esta solución y sí, es muy agradable. Funciona en mi caso, al menos (un bolígrafo para aquellos que puedan encontrarlo interesante: codepen.io/rishatmuhametshin/pen/XXjpaV ).
rishat
2

Aquí hay una cuadrícula de elementos de la interfaz de usuario de la tarjeta con el espacio completado usando un cuadro flexible:

ingrese la descripción de la imagen aquí

Estaba frustrado con el espaciado manual de las tarjetas al manipular el relleno y los márgenes con resultados dudosos. Aquí están las combinaciones de atributos CSS que he encontrado muy efectivas:

.card-container {
  width: 100%;
  height: 900px;
  overflow-y: scroll;
  max-width: inherit;
  background-color: #ffffff;
  
  /*Here's the relevant flexbox stuff*/
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap; 
}

/*Supplementary styles for .card element*/
.card {
  width: 120px;
  height: 120px;
  background-color: #ffeb3b;
  border-radius: 3px;
  margin: 20px 10px 20px 10px;
}
<section class="card-container">
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
      </section>

Espero que esto ayude a la gente, presente y futuro.

buildpax
fuente
Actualización: este espacio es efectivo para elementos HTML de representación móvil que necesitan una cierta alineación (por ejemplo, centro, izquierda, etc.). Si te encuentras usando flex box para el desarrollo móvil, he encontrado alivio al cambiar a una alineación puramente basada en márgenes.
buildpax
2

Columnify: una clase individual para N columnas

Flexbox y SCSS

.columnify {
  display: flex;

  > * {
    flex: 1;

    &:not(:first-child) {
      margin-left: 2rem;
    }
  }
}

Flexbox y CSS

.columnify {
  display: flex;
}

.columnify > * {
  flex: 1;
}

.columnify > *:not(:first-child) {
  margin-left: 2rem;
}
<div class="columnify">
  <div style="display: inline-block; height: 20px; background-color: blue;"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
</div>

Juega con él en JSFiddle .

zurfyx
fuente
1

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
/* u mean utility */
.u-gap-10 > *:not(:last-child) {
  margin-right: 10px;
}
<div id='box' class="u-gap-10">
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Amo Wu
fuente
1

Simplemente use .item + .itemen el selector para que coincida desde el segundo.item

#box {
  display: inline-flex;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 10px;
  height: 50px;
}

#box .item + .item {
  margin-left: 10px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Andrew Luca
fuente
1

Asumiendo:

  • Desea un diseño de cuadrícula de 4 columnas con ajuste
  • El número de elementos no es necesariamente un múltiplo de 4

Establezca un margen izquierdo en cada elemento, excepto el 1º, 5º, 9º elemento, etc. y establecer ancho fijo en cada artículo. Si el margen izquierdo es de 10 píxeles, cada fila tendrá un margen de 30 píxeles entre 4 elementos, el ancho porcentual del elemento se puede calcular de la siguiente manera:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

Esta es una solución decente para problemas relacionados con la última fila de flexbox.

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>

Salman A
fuente
1

De hecho, hay una manera agradable, ordenada y solo de CSS para hacer esto (que uno puede considerar "mejor").

De todas las respuestas publicadas aquí, solo encontré una que usa calc () con éxito (por Dariusz Sikorski). Pero cuando se plantea con: "pero falla si solo hay 2 elementos en la última fila", no hubo solución expandida.

Esta solución aborda la pregunta del OP con una alternativa a los márgenes negativos y aborda el problema planteado a Dariusz.

notas:

  • Este ejemplo solo muestra un diseño de 3 columnas
  • Se utiliza calc()para permitir que el navegador haga las matemáticas de la manera que desee 100%/3 (aunque el 33.3333% debería funcionar igual de bien) y (1em/3)*2 (aunque .66em también debería funcionar bien) .
  • Se utiliza ::afterpara rellenar la última fila si hay menos elementos que columnas

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}
.flex-container:after {
  content: "";
}
.flex-container > div,
.flex-container:after {
  box-sizing: border-box;
  width: calc((100%/3) - ((1em/3)*2));
}
.flex-container > :nth-child(n + 4) {
  margin-top: 1em;
}

/* the following is just to visualize the items */
.flex-container > div,
.flex-container:after {
  font-size: 2em;
}
.flex-container {
  margin-bottom:4em;
}
.flex-container > div {
  text-align: center;
  background-color: #aaa;
  padding: 1em;
}
.flex-container:after {
  border: 1px dashed red;
}
<h2>Example 1 (2 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
</div>

<h2>Example 2 (3 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>

También en https://codepen.io/anon/pen/rqWagE

aequalsb
fuente
1

Podrías usar la nueva propiedad gap. Copio y pego la explicación que encontré en este artículo , así como más información

El diseño de la cuadrícula CSS ha tenido una brecha (anteriormente brecha de cuadrícula) durante algún tiempo. Al especificar el espacio interno de un elemento contenedor en lugar del espacio alrededor de los elementos secundarios, gap resuelve muchos problemas comunes de diseño. Por ejemplo, con gap, no tiene que preocuparse por los márgenes en los elementos secundarios que causan espacios en blanco no deseados alrededor de los bordes de un elemento contenedor:

Desafortunadamente en este momento, solo FireFox admite la brecha en los diseños flexibles.

@use postcss-preset-env {
  stage: 0;
  browsers: last 2 versions
}

section {
  width: 30vw;
  
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(12ch, 1fr));
  
  &[flex] {
    display: flex;
    flex-wrap: wrap;
  }
  
  margin-bottom: 3rem;
}

.tag {
  color: white;
  background: hsl(265 100% 47%);
  padding: .5rem 1rem;
  border-radius: 1rem;
}

button {
  display: inline-flex;
  place-items: center;
  gap: .5rem;
  background: hsl(265 100% 47%);
  border: 1px solid hsl(265 100% 67%);
  color: white;
  padding: 1rem 2rem;
  border-radius: 1rem;
  font-size: 1.25rem;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
<section>
  <h1>Grid</h1> 
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>
<br>
<section flex>
  <h1>Flex</h1>
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>

Andres Paul
fuente
gapya fue recomendado en una respuesta aquí stackoverflow.com/a/58041749/2756409 Además, esto no es CSS.
TylerH
0

No funcionará en todos los casos, pero si tiene anchos secundarios flexibles (%) y conoce la cantidad de elementos por fila, puede especificar de manera muy clara los márgenes de los elementos necesarios utilizando nth-child selector / s.

Depende en gran medida de lo que quiere decir con "mejor". De esta manera no se requiere un marcado adicional para elementos secundarios o elementos negativos, pero ambas cosas tienen su lugar.

section {
  display: block
  width: 100vw;
}
.container {
  align-content: flex-start;
  align-items: stretch;
  background-color: #ccc;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  width: 100%;
}

.child-item {
  background-color: #c00;
  margin-bottom: 2%;
  min-height: 5em;
  width: 32%;
}

.child-item:nth-child(3n-1) {
  margin-left: 2%;
  margin-right: 2%;
}
<html>
  <body>
      <div class="container">
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
      </div>
   </body>
</html>

jnmrobinson
fuente
No responde Funciona solo para padres de ancho fijo.
Verde
1
El OP no solicita una solución receptiva y su ejemplo utiliza un ancho fijo. Dado que esto usa valores de%, es fácil argumentar que responde, ya que los elementos se adaptarán al tamaño del padre, que se establece por porcentaje.
jnmrobinson
0

Me encontré con el mismo problema anteriormente, luego me topé con la respuesta para esto. Espero que ayude a otros para futuras referencias.

respuesta larga corta, agregue un borde a los elementos flexibles de su hijo. entonces puede especificar márgenes entre elementos flexibles a lo que quiera. En el fragmento, uso el negro con fines ilustrativos, puede usar 'transparente' si lo desea.

#box {
  display: flex;
  width: 100px;
  /* margin: 0 -5px; *remove this*/
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  /* margin: 0 5px; *remove this*/
  border: 1px solid black; /* add this */
}
.item.special{ margin: 0 10px; }
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item special'></div>
</div>

Tunasing
fuente
0

El truco del margen negativo en el contenedor de la caja funciona muy bien. Aquí hay otro ejemplo que funciona muy bien con el orden, la envoltura y lo que no.

.container {
   border: 1px solid green;
   width: 200px;
   display: inline-block;
}

#box {
  display: flex;
  flex-wrap: wrap-reverse;
  margin: -10px;
  border: 1px solid red;
}
.item {
  flex: 1 1 auto;
  order: 1;
  background: gray;
  width: 50px;
  height: 50px;
  margin: 10px;
  border: 1px solid blue;
}
.first {
  order: 0;
}
<div class=container>
<div id='box'>
  <div class='item'>1</div>
  <div class='item'>2</div>
  <div class='item first'>3*</div>
  <div class='item'>4</div>
  <div class='item'>5</div>
</div>
</div>

cghislai
fuente