Mejor forma de establecer la distancia entre los elementos de la caja flexible

Para establecer la distancia mínima entre los elementos de la caja flexible, estoy usando el margin: 0 5px en .item y margin: 0 -5px en el contenedor. Para mí, parece un truco, pero no puedo encontrar una forma mejor de hacerlo.

Ejemplo

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

  • Flexbox no tiene márgenes colapsables.
  • Flexbox no tiene nada parecido al border-spacing de border-spacing para las tablas.

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

En mi experiencia, la forma “más limpia” que no se usa :first-child / :last-child y funciona sin ninguna modificación en flex-wrap:wrap es para establecer el padding:5px en el contenedor y margin:5px en los niños . Eso producirá un espacio de 10 10px entre cada niño y entre cada niño y su padre.

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;} 
 
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa
aaa

Esto no es un truco. La misma técnica también es utilizada por bootstrap y su cuadrícula, sin embargo, en lugar de margen, bootstrap usa relleno para sus cols.

 .row { margin:0 -15px; } .col-xx-xx { padding:0 15px; } 

Puedes usar bordes transparentes.

He contemplado este problema al tratar de construir un modelo de cuadrícula flexible que puede recurrir a un modelo tablas + tabla-celda para navegadores más antiguos. Y Borders for column gutters me pareció la elección más adecuada. 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; para flexbox El modelo de flexión no manejará tamaños fijos a menos que flex: none; en el elemento hijo particular que desea como fijo y, por lo tanto, excluido de ser "flexi" . http://jsfiddle.net/GLpUp/4/ Pero todas las columnas junto con flex:none; ya no es un modelo flexible. Aquí hay algo más cerca de un modelo flexible: http://jsfiddle.net/GLpUp/5/

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

Setting background-clip: padding-box; será necesario cuando se utiliza un fondo, ya que de lo contrario el fondo fluirá hacia el área del borde transparente.

flexbox y css calc ()

Hola, a continuación se muestra mi solución de trabajo para todos los navegadores compatibles con flexbox. Sin márgenes negativos, sin cortes, sin soluciones, Css puro.

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-bottom: 10px; width: calc(1/3*100% - (1 - 1/3)*10px); } 
 
col
col
col
col
col
col

He encontrado una solución que se basa en el css preceded by selector ~ , y permite el anidamiento inifinite.

Vea este código pluma para un ejemplo de trabajo

Básicamente, dentro de los contenedores de columnas, cada niño que está precedido por otro niño obtiene un margen superior. Del mismo modo, dentro de cada contenedor de fila, cada niño que está 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; } 
 

Si lo deseas, siempre puedes usar la combinación de hermanos CSS :

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

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

Una muestra de trabajo para usted ↓

 #box { display: flex; width: 100px; } .item { background: gray; width: 50px; height: 50px; } .item+.item{ margin-left: 5px; } 
 

Pasando de 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 de 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; } 
text
text
text
text
text
text

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

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

Flexbox es tan inteligente que recalcula automáticamente e igualmente distribuye la grilla.

 body { margin: 0; } .container { display: flex; } .item { flex: 1; background: gray; height: 50px; margin-right: 10px; } .item:last-child { margin-right: 0; } 
 

Lo he usado para columnas envolventes y de ancho fijo. La clave aquí es calc()

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

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

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

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

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

Puede usar el 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; } 
 

¿Por qué no hacerlo así?

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

Utiliza el selector de hermanos adyacente para dar a todos los elementos .item , excepto el primero un margin-left . Gracias a Flexbox, esto incluso da como resultado elementos igualmente amplios. Esto también podría hacerse con elementos posicionados verticalmente y margin-top , por supuesto.

Usando Flexbox en mi solución, he usado la propiedad justify justify-content para el elemento padre (container) y he especificado los márgenes dentro de la propiedad de flex-basis de los artículos. 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); } 
 
1
2
3
4
1
2
3
1
2

Aquí está mi solución, que no requiere configurar 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:

 
Testing 123

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

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

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

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

… o alterar el HTML ( como se muestra en otra respuesta ):

 
...

… o algo mas.

En cualquier caso, necesita un hack feo para hacerlo funcionar porque flexbox no proporciona una función de ” 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 Grid proporciona propiedades que crean espacio entre los elementos de la cuadrícula, sin tener en cuenta el espacio entre los elementos y el contenedor. Estas propiedades son:

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

Recientemente, la especificación se ha actualizado para cumplir con el Módulo de alineación de CSS Box , que proporciona un conjunto de propiedades de alineación para usar en todos los modelos de recuadro. 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 usaré las versiones originales en la demostración a continuación.

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

De la especificación:

10.1. Canalones: las propiedades de gap column-gap , column-gap row-gap column-gap y gap

Las propiedades row-gap y column-gap (y su gap abreviada), cuando se especifican en un contenedor de cuadrícula, definen los canales entre las filas de la grilla y las columnas de la grilla. Su syntax se define en CSS Box Alignment 3 §8 Gaps Between Boxes .

El efecto de estas propiedades es como si las líneas de cuadrícula afectadas adquirieran grosor: la ruta de cuadrícula entre dos líneas de cuadrícula es el espacio entre las cunetas 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; } 
 


Columnify – Una clase en solitario 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; } 
 

Simplemente use .item + .item en el selector para que coincida con el segundo .item

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

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

La forma más fácil de hacerlo es con porcentajes y simplemente permitir que el margen calcule tu ancho

Esto significa que terminas con algo como esto si estás usando 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.

Aquí hay una grilla de elementos de la IU de la tarjeta con espacios completados usando una caja flexible:

enter image description here

Me sentí frustrado con el espaciado manual de las cartas al manipular el relleno y los márgenes con resultados dudosos. Así que 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; } 
 

Encontré un truco porque realmente necesito esto.

 /* grid */ .container { display: flex; flex-flow: row wrap; justify-content: space-between; } .container::after, /* this makes sure odd element goes left and not space between */ .item { content:""; width: calc(33.3333% - 20px); margin-bottom: 40px; } /* extra styling - not important */ .item { height: 100px; background: #787878; } 
 

Asumiendo:

  • Desea un diseño de cuadrícula de 4 columnas con envoltura
  • La cantidad de artículos no es necesariamente un múltiplo de 4

Establezca un margen izquierdo en cada elemento excepto 1.o, 5. °, 9. ° elemento y así sucesivamente; y establecer ancho fijo en cada elemento. Si el margen izquierdo es 10px, cada fila tendrá un margen de 30px 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 los 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; } 
 
1
2
3
4
1
2
3
4
5
6
1
2
3
4
5
6
7
8
9

Establecí el espaciado en los ítems flexibles solo en la dirección establecida por su contenedor. Por ejemplo, si un contenedor flexible está configurado para fluir de izquierda a derecha ( flex-direction:row ), solo estableceré el margen derecho en sus elementos secundarios, excepto el último:

 .flex-lr{ display:flex; flex-direction:row; } .flex-lr > *:not(:last-child){ margin-right:5px; } 

Esto podría parecer que funciona a primera vista, ¡pero espera! esto no debe hacerse cuando justify-content se establece en un valor distinto de start o end , ya que todos los demás valores ya están distribuyendo el espacio por sí solos.

¿Y qué pasa si los artículos se envuelven? Entonces deberíamos agregar espacio al lado del eje transversal adecuado también. Pero, ¿cómo saber si un contenedor permite que sus hijos se envuelvan? ¿Y qué pasa con wrap-reverse ?

Todas estas consideraciones me hicieron pensar que esta no es una tarea trivial y que requiere un pequeño paso más allá.

Mi enfoque se basa en la construcción de un breve conjunto de clases que actúa como un contenedor de flexbox. Esto tiene algunos beneficios:

  1. Permite “centralizar” todos los prefijos de proveedor en un solo punto y olvidarse de eso.
  2. Permite agrupar propiedades de flexbox en una sola clase, o incluso renombrar algunas de las palabras utilizadas por flexbox, que a veces pueden parecer no muy intuitivas (en mi humilde opinión).
  3. Si utilizo estas clases, podré escribir otras clases basadas en los valores de las propiedades flexibles en las que confían. Por ejemplo, podría establecer el espaciado en función de la dirección del flujo, la alineación del eje transversal, la envoltura, etc.

Terminé construyendo un diseñador de flexbox para jugar con todo esto, para ayudar a entenderme a mí mismo (y a otros) cómo funciona flexbox y darme cuenta de lo maravilloso que es flexbox. Plese no dude en utilizarlo siguiendo el siguiente enlace:

http://algid.com/Flex-Designer

Por lo tanto, a continuación encontrará y resumen de las clases que uso y el espaciado (margen) utlity para una dirección de flujo. Podrá inferir los otros o encontrarlos en el enlace proporcionado anteriormente. Los prefijos del proveedor se han omitido aquí por brevedad.

 /* Flex container definition */ .flex-lr{display:flex; flex-direction:row;} .flex-tb{display:flex; flex-direction:column;} .flex-rl{display:flex; flex-direction:row-reverse;} .flex-bt{display:flex; flex-direction:column-reverse;} /* Wrapping */ .wrap{flex-wrap:wrap;} .nowrap{flex-wrap:nowrap;} .wrap-rev{flex-wrap:wrap-reverse;} /* Main axis alignment */ .align-start{justify-content:flex-start;} .align-end{justify-content:flex-end;} .align-center{justify-content:center;} .align-between{justify-content:space-between;} .align-around{justify-content:space-around;} .align-evenly{justify-content:space-evenly;} /* Cross axis alignment */ .cross-align-start{align-items:flex-start;} .cross-align-end{align-items:flex-end;} .cross-align-center{align-items:center;} .cross-align-stretch{align-items:stretch;} .cross-align-baseline{align-items:baseline;} /* Cross axis alignment when content is wrapped */ .wrap-align-start{align-content:flex-start;} .wrap-align-end{align-content:flex-end;} .wrap-align-center{align-content:center;} .wrap-align-stretch{align-content:stretch;} .wrap-align-between{align-content:space-between;} .wrap-align-around{align-content:space-around;} /* Item alignment */ .item-cross-align-start{align-self:flex-start;} .item-cross-align-end{align-self:flex-end;} .item-cross-align-center{align-self:center;} .item-cross-align-stretch{align-self:stretch;} .item-cross-align-baseline{align-self:baseline;} .item-cross-align-auto{align-self:auto;} 

Y ahora lo que nos trajo aquí: el espacio entre los elementos:

 /* Flow margin (left to right) */ .flex-lr.fm-0 > *:not(:last-child){margin-right:0;} .flex-lr.fm-1 > *:not(:last-child){margin-right:3px;} .flex-lr.fm-2 > *:not(:last-child){margin-right:7px;} .flex-lr.fm-3 > *:not(:last-child){margin-right:15px;} .flex-lr.fm-4 > *:not(:last-child){margin-right:32px;} /* Cross axis */ .flex-lr.wrap.fm-0:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-0.wrap-align-stretch.cross-align-stretch > * {margin-bottom:0;} .flex-lr.wrap.fm-1:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-1.wrap-align-stretch.cross-align-stretch > * {margin-bottom:3px;} .flex-lr.wrap.fm-2:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-2.wrap-align-stretch.cross-align-stretch > * {margin-bottom:7px;} .flex-lr.wrap.fm-3:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-3.wrap-align-stretch.cross-align-stretch > * {margin-bottom:15px;} .flex-lr.wrap.fm-4:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-4.wrap-align-stretch.cross-align-stretch > * {margin-bottom:32px;} /* wrap reverse */ .flex-lr.wrap-rev.fm-0:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-0.wrap-align-stretch.cross-align-stretch > * {margin-top:0;} .flex-lr.wrap-rev.fm-1:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-1.wrap-align-stretch.cross-align-stretch > * {margin-top:3px;} .flex-lr.wrap-rev.fm-2:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-2.wrap-align-stretch.cross-align-stretch > * {margin-top:7px;} .flex-lr.wrap-rev.fm-3:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-3.wrap-align-stretch.cross-align-stretch > * {margin-top:15px;} .flex-lr.wrap-rev.fm-4:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-4.wrap-align-stretch.cross-align-stretch > * {margin-top:32px;} 

Finalmente, así es como se vería el marcado:

 
Some content here...
A bit more stuff here...
Now vertical content
etc.

Esto es lo que llamo código en voz alta.

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

Depende en gran medida de lo que quiere decir con “mejor”. De esta forma, no se requiere el marcado de envoltura adicional para elementos secundarios o negativos, pero ambos 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%; } 
   

I posted my flexbox approach here :

One idea I rejected was to remove the padding from the outer columns with something like this:

 div:nth-child(#{$col-number}n+1) { padding-left: 0; } div:nth-child(#{$col-number}n+#{$col-number}) { padding-left: 0; } 

But, like other posters here, I prefer the negative margin trick. My fiddle also has responsiveness for anyone is looking for a Sass-based solution. I basically use this approach in place of a grid.

https://jsfiddle.net/x3jvfrg1/

I came across the same issue earlier, then stumbled upon the answer for this. Hope it will help others for future reference.

long answer short, add a border to your child flex-items. then you can specify margins between flex-items to whatever you like. In the snippet, i use black for illustration purposes, you can use ‘transparent’ if you like.

 #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; } 
 
 #box { display: flex; width: 100px; } .item { background: gray; width: 50px; height: 50px; } /* u mean utility */ .u-gap-10 > *:not(:last-child) { margin-right: 10px; } 
 

The negative margin trick on the box container works just great. Here is another example working great with order, wrapping and what not.

 .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; } 
 
1
2
3*
4
5
  :root{ --inner: 20px; --gap: 10px; /* same as gutter */ /* flex-flow in row ---------------------*/ --row-wrap: row wrap; --row-nowrap: row nowrap; /* flex-flow in col ---------------------*/ --col-wrap: column wrap; } .row { display: flex; flex-direction: var(--flex-row); } /* additional wrapping classes (if needed) -------------------------------------------*/ .nowrap { display: flex; flex-flow: var(--row-nowrap); } .wrap { display: flex; flex-flow: var(--col-wrap); } /*----------------------------------------*/ [class*="col-"] { border: 1px solid #ccc; margin: var(--gap); padding: var(--inner); height: auto; background: #333; flex: 1 0 auto; } .col-3 { flex: 3; }