html - start - flex-wrap
El tamaño de Flexbox no funciona correctamente cuando se utiliza FontAwesome (4)
Estoy enfrentando un comportamiento muy extraño de flexbox para el diseño de mi página. Estoy usando FontAwesome para representar ciertos símbolos.
Básicamente, tengo 2 elementos de flexbox dentro de otro elemento de flexbox, y estos elementos secundarios se representan más que el elemento principal.
1) Tengo un objeto .content__header
, que se representa como un objeto flexbox dentro de otra serie de objetos flexbox.
2) El objeto .content__header
contiene 2 objetos secundarios: .breadcrumb
y .page_tools
. Estos objetos secundarios también se representan como elementos flexibles.
3) Dentro del objeto .breadcrumb
, tengo algunos objetos span
( .breadcrumb__test
) cuyo contenido se reemplaza por un ícono FontAwesome . La sustitución se realiza mediante el posicionamiento absoluto del ::after
pseudo-elemento.
4) Cuando .breadcrumb__text
todos los elementos HTML de .breadcrumb__text
o simplemente .breadcrumb__text::after
definition de mi hoja de estilo, que define el uso de la fuente FontAwesome, los objetos secundarios ( .breadcrumb
y .page_tools
) se .page_tools
en su ancho correcto. Así que supongo que tiene algo que ver con el reemplazo por un ícono de FontAwesome.
.breadcrumb__text::after {
font-family: "FontAwesome";
font-weight: 400;
}
Representación visual del tema.
La línea verde indica la diferencia entre el ancho principal y su contenido real.
Código y violín a continuación.
Navegador: Google Chrome 47.0.2526.106 m
Violín:
https://jsfiddle.net/44gymmw2/6/
Actualizar
Cuando elimino text-indent: 100%;
a partir de la definición de CSS de .breadcrumb__text
, el .breadcrumb
procesa según lo previsto. Sin embargo, cuando dejo la text-indent
en su lugar y .breadcrumb__text::after
el .breadcrumb__text::after
definición en la parte superior de la hoja de estilo (como se describe anteriormente), también se procesa correctamente.
¿Podría este problema tener algo que ver con FontAwesome o text-indent
y flexbox?
Código
HTML
<body>
<div class="layout_wrapper">
<div class="layout_container__content">
<div class="content">
<header class="content__header">
<div class="breadcrumb">
<span class="breadcrumb__text breadcrumb__text--first">From </span><a class="breadcrumb__link" href="#">Dashboard</a><span class="breadcrumb__text"> to </span><a class="breadcrumb__link" href="#">Find records</a><span class="breadcrumb__text"> to </span>
<h1 class="breadcrumb__current">Kylo Ren’s Command Shuttle™</h1>
</div>
<ul class="page_tools">
<li class="page_tools__item">
<button type="button" class="button button--primary">Save</button>
</li>
<li class="page_tools__item">
<button type="button" class="button">Cancel</button>
</li>
</ul>
</header>
</div>
</div>
<div class="layout_container__sidebar">
<div class="sidebar">
<article class="widget">
<h2 class="widget__title">Widget</h2>
</article>
</div>
</div>
</div>
</body>
CSS
/* Removing this makes it work */
.breadcrumb__text::after {
font-family: "FontAwesome";
font-weight: 400;
}
/* Don''t remove anything below */
.breadcrumb__text--first {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
* {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
html, body {
padding: 0;
margin: 0;
}
body {
display: flex;
flex-flow: column nowrap;
align-items: stretch;
}
.layout_wrapper {
flex: 1 1 auto;
display: flex;
flex-flow: row nowrap;
align-items: stretch;
}
.layout_container__content {
flex: 0 0 75vw;
}
.layout_container__sidebar {
flex: 0 0 25vw;
}
.content {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: stretch;
}
.content__header {
outline: 1px solid blue;
background-color: #434649;
color: #ffffff;
flex: 0 0 100%;
display: flex;
flex-flow: row nowrap;
}
.breadcrumb {
outline: 3px dashed purple;
flex: 1 1 auto;
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
}
.breadcrumb__text {
flex: 0 0 2em;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
position: relative;
text-align: center;
}
.breadcrumb__text::after {
content: ''/f105'';
padding: 0;
text-indent: 0;
position: absolute;
top: 0;
right: 0;
width: 100%;
}
.breadcrumb__text--first {
flex: 0 0 0;
}
.breadcrumb__text--first::after {
content: none;
}
.breadcrumb__link {
flex: 0 0 auto;
display: inline-block;
font-size: 0.8571rem;
}
.breadcrumb__current {
flex: 0 0 100%;
margin: 0;
}
.page_tools {
outline: 3px dashed red;
flex: 0 0 auto;
display: flex;
flex-flow: row nowrap;
list-style: none outside none;
}
Acabo de terminar de revisar su código y noté lo siguiente:
- Hay contenedores de flexión innecesarios (anidados) (causados por el uso de
display: flex;
). - Hay declaraciones innecesarias relacionadas con flexión (solo se declara el comportamiento predeterminado, como
flex-flow: row no-wrap;
yalign-items: stretch
). - Hay varias declaraciones innecesarias en el contexto de varios selectores no relacionados. Probablemente las declaraciones de sobra durante la prueba / depuración.
Dicho esto, continuemos con su problema. No es obvio, por lo que necesita una introducción.
Pangloss introduce un ingrediente importante de su problema, que afecta el uso text-indent
. Desde W3 :
El cuadro está sangrado con respecto al borde izquierdo (o derecho, para el diseño de derecha a izquierda) del cuadro de línea. Los agentes de usuario deben representar esta sangría como espacio en blanco.
[...]
Si el valor de
text-indent
detext-indent
es negativo o supera el ancho del bloque, ese primer cuadro, descrito anteriormente, puede desbordar el bloque. El valor deoverflow
afectará si dicho texto que desborda el bloque es visible.
En otras palabras: text-indent
afecta a las dimensiones del cuadro al que se aplica.
Has declarado overflow: hidden;
en .breadcrumb__text
. Obviamente, para que esa declaración tenga el efecto deseado, la caja a la que lo aplicaste necesita un width
, o de lo contrario no tendría un borde de recorte.
.breadcrumb__text
debe obtener su ancho a partir de la declaración de flex-basis
(específicamente flex: 0 0 2em;
) que se le aplica. Bueno ... eso no está sucediendo, al menos, no del todo como cabría esperar. A pesar de que su ancho parece ser 2em
, por alguna razón no desencadena el comportamiento de desbordamiento como debería. Esto parece ser un error en la versión específica de Chrome que usas, ya que se corrigió en Canary (por ejemplo, la versión 49 y superior).
Entonces: esto parece ser un problema con la implementación de flexbox en Chrome. Dicho esto, con este conocimiento, su problema se puede solucionar de múltiples maneras. Algunos ejemplos:
text-indent: -100%
Usando text-indent: -100%
soluciona su problema porque quita el espacio en blanco adicional en el lado derecho de los elementos afectados. (→ jsfiddle )
width: 2em
Podría agregar el width: 2em
la declaración width: 2em
a .breadcrumb__text
. Eso arreglaría el comportamiento inesperado de la declaración de flex-basis
. (→ jsfiddle )
overflow: hidden;
en el contenedor de los padres
Adición de overflow: hidden;
en .breadcrumbs
corrige su problema. Ahora el contenedor principal tiene un borde de recorte y maneja los espacios en blanco causados por el uso de text-indent: 100%
. (→ jsfiddle )
Observaciones finales
Flexbox es un modo de diseño potente y seguro que es genial para experimentar. Pero, los algoritmos son complejos y las implementaciones del navegador aún no están libres de problemas. Asegúrese de tener esto en cuenta al utilizar flexbox.
Otra preocupación al mirar su código es la forma en que usa flexbox. Flexbox está ahí para que lo use, pero no necesariamente tiene que reemplazar todas las otras formas de tratar con el diseño. display: inline-block;
o display: table;
, o incluso float
podría hacer el trabajo sin introducir la complejidad de los contenedores flexibles anidados.
Creo que el problema se debe a la regla de text-indent:100%
, que agrega espacio extra en la mano derecha.
La propiedad
text-indent
especifica cuánto espacio horizontal debe quedar antes del comienzo de la primera línea del contenido de texto de un elemento.<percentage>
valor relativo al ancho del bloque que contiene . - MDN
Vea esta simple demostración:
body {
width: 200px;
border: 1px solid red;
}
span {
text-indent: 100%;
display: inline-block;
}
<span>text</span>
En su ejemplo, solo puede cambiar text-indent:100%
a text-indent:-9999px
, funciona de manera similar, y no creará el desbordamiento.
El tipo de letra FontAwesome no es la causa raíz. Es la definición de diseño del "bloque" H1 establecida de forma predeterminada en su navegador. Agregue este estilo a su clase breadcrumb__current. Ver https://jsfiddle.net/44gymmw2/9/
word-wrap:break-word
La etiqueta H1 es un elemento de nivel de bloque, lo que hará que empuje el contenido de ese bloque en toda la página. Otra solución sería cambiar eso de bloque a en línea, así:
h1 { display: inline; }
O podrías envolver ese texto en otro elemento, como un tramo.
Pruebe con la propiedad de bloque en línea que está funcionando bien.
.content {
display:inline-block;
flex-flow: row wrap;
justify-content: space-between;
align-items: stretch;
}