html - container - ¿Cómo especificar saltos de línea en un diseño flexbox de varias líneas?
flexbox grid (9)
¿Hay alguna manera de hacer un salto de línea en múltiples líneas de flexbox?
Por ejemplo, para romper después de cada 3er elemento en este CodePen .
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
height: 100px;
background: gold;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px;
}
.item:nth-child(3n) {
background: silver;
}
<div class="container">
<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 class="item">10</div>
</div>
Me gusta
.item:nth-child(3n){
/* line-break: after; */
}
¿Quieres un salto de línea semántico?
Entonces considere usar
<br>
.
W3Schools puede sugerirle que
BR
es solo para escribir poemas (el mío vendrá pronto) pero puede cambiar el estilo para que se comporte como un elemento de bloque de 100% de ancho que empujará su contenido a la siguiente línea.
Si ''br'' sugiere un descanso, entonces me parece más apropiado que usar
hr
o un 100%
div
y hace que el html sea más legible.
Inserte la
<br>
donde necesite saltos de línea y asígnele un estilo como este.
// Use `>` to avoid styling `<br>` inside your boxes
.container > br
{
width: 100%;
content: '''';
}
Puede
deshabilitar
<br>
con consultas de medios
, configurando
display:
para
block
o
none
según corresponda (he incluido un ejemplo de esto pero lo dejé comentado).
Puede usar
order:
para establecer el orden si es necesario también.
Y puedes poner tantos como quieras, con diferentes clases o nombres :-)
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.container > br
{
width: 100%;
content: '''';
}
// .linebreak1
// {
// display: none;
// }
// @media (min-width: 768px)
// {
// .linebreak1
// {
// display: block;
// }
// }
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<br class="linebreak1"/>
<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 class="item">10</div>
</div>
No es necesario limitarse a lo que dice W3Schools:
@Oriol tiene una excelente respuesta, lamentablemente a partir de octubre de 2017, ni
display:contents
, ni
page-break-after
es ampliamente compatible, mejor dicho, se trata de Firefox que admite esto, pero no los otros jugadores, se me ocurrió lo siguiente " piratear ", lo que considero mejor que la codificación rígida en un descanso después de cada 3er elemento, porque eso hará que sea muy difícil hacer que la página sea móvil.
Como se dijo, es un truco y el inconveniente es que necesita agregar muchos elementos adicionales para nada, pero funciona y funciona en varios navegadores incluso en el IE11 con fecha.
El "hack" es simplemente agregar un elemento adicional después de cada div, que se configura para
display:none
y luego usó css
nth-child
para decidir cuál de estos debería hacerse visible forzando un freno de línea como este:
<div class="container">
<div>1</div>
<div>2</div>
<hr>
<div>3</div>
<div>2</div>
...
</div>
.container {
display: flex;
flex-flow: wrap;
}
.container hr {
width: 100%;
}
Creo que la forma tradicional es flexible y bastante fácil de entender:
Margen
<div class="flex-grid">
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-3">.col-3</div>
<div class="col-9">.col-9</div>
<div class="col-6">.col-6</div>
<div class="col-6">.col-6</div>
</div>
Crear archivo grid.css :
.flex-grid {
display: flex;
flex-flow: wrap;
}
.col-1 {flex: 0 0 8.3333%}
.col-2 {flex: 0 0 16.6666%}
.col-3 {flex: 0 0 25%}
.col-4 {flex: 0 0 33.3333%}
.col-5 {flex: 0 0 41.6666%}
.col-6 {flex: 0 0 50%}
.col-7 {flex: 0 0 58.3333%}
.col-8 {flex: 0 0 66.6666%}
.col-9 {flex: 0 0 75%}
.col-10 {flex: 0 0 83.3333%}
.col-11 {flex: 0 0 91.6666%}
.col-12 {flex: 0 0 100%}
[class*="col-"] {
margin: 0 0 10px 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
@media (max-width: 400px) {
.flex-grid {
display: block;
}
}
He creado un ejemplo (jsfiddle)
Intenta cambiar el tamaño de la ventana por debajo de 400 px, ¡responde!
Desde mi perspectiva, es más semántico usar
elementos
<hr>
como saltos de línea
entre elementos flexibles.
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(3n-1) {
background: silver;
}
.breaker {display:none;}
.breaker:nth-child(3n) {
display:block;
width:100%;
height:0;
}
<div class="container">
<div class="item">1</div><p class=breaker></p>
<div class="item">2</div><p class=breaker></p>
<div class="item">3</div><p class=breaker></p>
<div class="item">4</div><p class=breaker></p>
<div class="item">5</div><p class=breaker></p>
<div class="item">6</div><p class=breaker></p>
<div class="item">7</div><p class=breaker></p>
<div class="item">8</div><p class=breaker></p>
<div class="item">9</div><p class=breaker></p>
<div class="item">10</div><p class=breaker></p>
</div>
Probado en Chrome 66, Firefox 60 y Safari 11.
Intenté varias respuestas aquí, y ninguna de ellas funcionó.
Irónicamente, lo que funcionó fue la alternativa más simple a una
<br/>
uno podría intentar:
<div style="flex-basis: 100%;"></div>
o también podrías hacer:
<div style="width: 100%;"></div>
Coloque eso donde quiera una nueva línea.
Parece funcionar incluso con los
<span>
adyacentes, pero lo estoy usando con los
<div>
adyacentes.
La solución más simple y confiable es insertar elementos flexibles en los lugares correctos.
Si son lo suficientemente anchos (
width: 100%
), forzarán un salto de línea.
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(4n - 1) {
background: silver;
}
.line-break {
width: 100%;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="line-break"></div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="line-break"></div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="line-break"></div>
<div class="item">10</div>
</div>
Pero eso es feo y no semántico.
En cambio, podríamos generar pseudo-elementos dentro del contenedor flexible y usar el
order
para moverlos a los lugares correctos.
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(3n) {
background: silver;
}
.container::before, .container::after {
content: '''';
width: 100%;
order: 1;
}
.item:nth-child(n + 4) {
order: 1;
}
.item:nth-child(n + 7) {
order: 2;
}
<div class="container">
<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>
Pero hay una limitación: el contenedor flexible solo puede tener un pseudo-elemento
::before
y a
::after
.
Eso significa que solo puedes forzar 2 saltos de línea.
Para resolver eso, puede generar los pseudoelementos dentro de los elementos flexibles en lugar de en el contenedor flexible. De esta forma, no estará limitado a 2. Pero esos pseudoelementos no serán elementos flexibles, por lo que no podrán forzar saltos de línea.
Pero afortunadamente,
CSS Display L3
ha introducido
display: contents
(actualmente solo es compatible con Firefox 37):
El elemento en sí no genera ningún cuadro, pero sus elementos secundarios y pseudoelementos aún generan cuadros de forma normal. A los efectos de la generación y el diseño de la caja, el elemento debe tratarse como si hubiera sido reemplazado por sus elementos secundarios y pseudoelementos en el árbol de documentos.
Por lo tanto, puede aplicar
display: contents
a los elementos secundarios del contenedor flexible y envolver el contenido de cada uno dentro de un contenedor adicional.
Entonces, los elementos flexibles serán esos envoltorios adicionales y los pseudo-elementos de los niños.
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
display: contents;
}
.item > div {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px;
}
.item:nth-child(3n) > div {
background: silver;
}
.item:nth-child(3n)::after {
content: '''';
width: 100%;
}
<div class="container">
<div class="item"><div>1</div></div>
<div class="item"><div>2</div></div>
<div class="item"><div>3</div></div>
<div class="item"><div>4</div></div>
<div class="item"><div>5</div></div>
<div class="item"><div>6</div></div>
<div class="item"><div>7</div></div>
<div class="item"><div>8</div></div>
<div class="item"><div>9</div></div>
<div class="item"><div>10</div></div>
</div>
Alternativamente, de acuerdo con
Fragmenting Flex Layout
y
CSS Fragmentation
, Flexbox permite interrupciones forzadas mediante el uso de
break-before
,
break-after
o sus alias CSS 2.1:
.item:nth-child(3n) {
page-break-after: always; /* CSS 2.1 syntax */
break-after: always; /* New syntax */
}
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(3n) {
page-break-after: always;
background: silver;
}
<div class="container">
<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 class="item">10</div>
</div>
Los saltos de línea forzados en flexbox aún no son ampliamente compatibles, pero funciona en Firefox.
Otra posible solución que no requiere agregar ningún marcado adicional es agregar un margen dinámico para separar los elementos.
En el caso del ejemplo, esto se puede hacer con la ayuda de
calc()
, simplemente agregando
margin-left
y
margin-right
al elemento 3n + 2 (2, 5, 8)
.item:nth-child(3n+2) {
background: silver;
margin: 10px calc(50% - 175px);
}
Ejemplo de fragmento
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
height: 100px;
background: gold;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px;
}
.item:nth-child(3n+2) {
background: silver;
margin: 10px calc(50% - 175px);
}
<div class="container">
<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 class="item">10</div>
</div>
Para futuras preguntas, también es posible hacerlo utilizando la propiedad
float
y borrándola en cada 3 elementos.
Aquí hay un ejemplo que hice.
.grid {
display: inline-block;
}
.cell {
display: inline-block;
position: relative;
float: left;
margin: 8px;
width: 48px;
height: 48px;
background-color: #bdbdbd;
font-family: ''Helvetica'', ''Arial'', sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-indent: 4px;
color: #fff;
}
.cell:nth-child(3n) + .cell {
clear: both;
}
<div class="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
<div class="cell">7</div>
<div class="cell">8</div>
<div class="cell">9</div>
<div class="cell">10</div>
</div>
.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
height: 100px;
background: gold;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px;
}
<div class="container">
<div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
<div class="item">10</div>
</div>
podría intentar envolver los elementos en un elemento dom como aquí. con esto no tienes que saber mucho css, solo tener una buena estructura resolverá el problema.