html - bootstrap - <fieldset> cambia el tamaño de mal; Parece tener un `min-width: min-content` inamovible
ionic fieldset (4)
Problema
Tengo un <select>
donde uno de los valores de texto de su <option>
es muy largo. Quiero que la <select>
cambie de tamaño para que nunca sea más ancha que su padre, incluso si tiene que cortar el texto que se muestra. max-width: 100%
debe hacer eso.
Antes de redimensionar:
Lo que quiero después de cambiar el tamaño:
Pero si carga este ejemplo de jsFiddle y cambia el tamaño del ancho del panel de resultados para que sea más pequeño que el de <select>
, puede ver que la selección dentro del <fieldset>
falla al reducir su ancho.
Lo que realmente estoy viendo después de cambiar el tamaño:
Sin embargo, la página equivalente con un <div>
lugar de un <fieldset>
se escala correctamente. Puede ver eso y probar sus cambios más fácilmente si tiene un <fieldset>
y un <div>
junto al otro en una página . Y si elimina las etiquetas <fieldset>
los alrededores , el cambio de tamaño funciona. La etiqueta <fieldset>
alguna manera está causando que el cambio de tamaño horizontal se rompa.
El <fieldset>
actúa es como si hubiera un fieldset { min-width: min-content; }
regla CSS fieldset { min-width: min-content; }
fieldset { min-width: min-content; }
. ( min-content
significa, aproximadamente, el ancho más pequeño que no hace que un niño se desborde). Si sustituyo el <fieldset>
por un <div>
con min-width: min-content
, se ve exactamente igual. Sin embargo, no hay ninguna regla con min-content
en mis estilos, en la hoja de estilo predeterminada del navegador, o visible en el Inspector CSS de Firebug. Intenté anular todos los estilos visibles en <fieldset>
en el Inspector de CSS de Firebug y en la hoja de estilo predeterminada de Firefox, forms.css , pero eso no ayudó. Anular específicamente el min-width
y el width
tampoco hicieron nada.
Código
HTML del conjunto de campos:
<fieldset>
<div class="wrapper">
<select id="section" name="section">
<option value="-1"></option>
<option value="1501" selected="selected">Sphinx of black quartz, judge my vow. The quick brown fox jumps over the lazy dog.</option>
<option value="1480">Subcontractor</option>
<option value="3181">Valley</option>
<option value="3180">Ventura</option>
<option value="3220">Very Newest Section</option>
<option value="1481">Visitor</option>
<option value="3200">N/A</option>
</select>
</div>
</fieldset>
Mi CSS que debería estar funcionando pero no es:
fieldset {
/* hide fieldset-specific visual features: */
margin: 0;
padding: 0;
border: none;
}
select {
max-width: 100%;
}
Restablecer las propiedades de width
a los valores predeterminados no hace nada:
fieldset {
width: auto;
min-width: 0;
max-width: none;
}
Más CSS en el que trato y no puedo solucionar el problema :
/* try lots of things to fix the width, with no success: */
fieldset {
display: block;
min-width: 0;
max-width: 100%;
width: 100%;
text-overflow: clip;
}
div.wrapper {
width: 100%;
}
select {
overflow: hidden;
}
Más detalles
El problema también se produce en este ejemplo más completo y más complicado de jsFiddle , que es más similar a la página web que estoy tratando de solucionar. Puede ver que el <select>
no es el problema: un div
bloque en línea también falla en el cambio de tamaño. Aunque este ejemplo es más complicado, asumo que la solución para el caso simple de arriba también solucionará este caso más complicado.
[Editar: ver detalles de soporte del navegador a continuación.]
Una cosa curiosa sobre este problema es que si configura div.wrapper { width: 50%; }
div.wrapper { width: 50%; }
, <fieldset>
deja de redimensionarse en el punto, entonces el <select>
tamaño completo habría golpeado el borde de la ventana gráfica. El cambio de tamaño ocurre como si <select>
tiene un width: 100%
, aunque parece que <select>
tiene un width: 50%
.
Si le da al <select>
mismo width: 50%
, ese comportamiento no ocurre; el ancho simplemente se establece correctamente.
No entiendo la razón de esa diferencia. Pero puede que no sea relevante.
También encontré que el campo de campo HTML de la pregunta muy similar permite a los niños expandirse indefinidamente . El autor de la pregunta no pudo encontrar una solución y adivina que no hay una solución aparte de eliminar el <fieldset>
. Pero me pregunto, si realmente es imposible hacer que se muestre correctamente <fieldset>
, ¿por qué? ¿Qué causa este comportamiento en la spec <fieldset>
o en el CSS predeterminado (a partir de esta pregunta )? Este comportamiento especial probablemente se documente en algún lugar, ya que varios navegadores funcionan así.
Fondo objetivo y requisitos
La razón por la que estoy tratando de hacer esto es como parte de escribir estilos móviles para una página existente con un gran formato. El formulario tiene varias secciones, y una parte del mismo está envuelta en un <fieldset>
. En un teléfono inteligente (o si hace pequeña la ventana de su navegador), la parte de la página con <fieldset>
es mucho más ancha que el resto del formulario. La mayor parte del formulario limita su ancho muy bien, pero la sección con <fieldset>
no lo hace, lo que obliga al usuario a alejarse o desplazarse a la derecha para ver toda esa sección.
Desconfío de simplemente eliminar el <fieldset>
, ya que se genera en muchas páginas en una aplicación grande, y no estoy seguro de qué selectores en CSS o JavaScript pueden depender de ello.
Puedo usar JavaScript si lo necesito, y una solución de JavaScript es mejor que nada. Pero si JavaScript es la única forma de hacer esto, me gustaría escuchar una explicación de por qué esto no es posible utilizando solo CSS y HTML.
Edición: soporte del navegador
En el sitio, necesito compatibilidad con Internet Explorer 8 y versiones posteriores (solo eliminamos la compatibilidad con IE7), la última versión de Firefox y la última versión de Chrome. Esta página en particular también debería funcionar en teléfonos inteligentes iOS y Android. El comportamiento ligeramente degradado pero aún utilizable es aceptable para Internet Explorer 8.
Volví a probar mi ejemplo de fieldset
roto en diferentes navegadores. En realidad ya funciona en estos navegadores:
- Internet Explorer 8, 9 y 10
- Cromo
- Chrome para Android
Se rompe en estos navegadores:
- Firefox
- Firefox para Android
- Internet Explorer 7
Por lo tanto, el único navegador que me importa en el que se rompe el código actual es Firefox (tanto en el escritorio como en el móvil). Si el código se arreglara de modo que funcionara en Firefox sin romperlo en ningún otro navegador, eso resolvería mi problema.
La plantilla HTML del sitio utiliza los comentarios condicionales de Internet Explorer para agregar clases como .ie8
y .oldie
al elemento <html>
. Puede usar esas clases en su CSS si necesita solucionar las diferencias de estilo en IE. Las clases agregadas son las mismas que en esta versión anterior de HTML5 Boilerplate .
Actualización (25 de septiembre de 2017)
Para mi gran alivio, el error de Firefox que se describe a continuación se corrigió a partir de Firefox 53 y el enlace a esta respuesta finalmente se eliminó de la documentación de Bootstrap .
La solución
En WebKit y Firefox 53+, solo establece min-width: 0;
en el fieldset para anular el valor predeterminado de min-content
.¹
Aún así, Firefox es un poco ... extraño cuando se trata de campos. Para hacer que esto funcione en versiones anteriores, debe cambiar la propiedad de display
del fieldset a uno de los siguientes valores:
-
table-cell
(recomendado) -
table-column
-
table-column-group
-
table-footer-group
-
table-header-group
-
table-row
-
table-row-group
De estos, recomiendo table-cell
. Tanto table-row
como table-row-group
impiden cambiar el ancho, mientras que table-column
y table-column-group
impiden cambiar la altura.
Esto romperá (de manera bastante razonable) la representación en IE. Como solo Gecko necesita esto, puede usar justificadamente @-moz-document
—una de las extensiones de CSS propietarias de Mozilla— para ocultarlo de otros navegadores:
@-moz-document url-prefix() {
fieldset {
display: table-cell;
}
}
(Aquí hay una demostración de jsFiddle .)
Eso arregla las cosas, pero si eres como yo, tu reacción fue algo así como ...
What.
Hay una razón, pero no es bonita.
La presentación predeterminada del elemento fieldset es absurda y esencialmente imposible de especificar en CSS. Piénselo: el borde del conjunto de campos desaparece donde se superpone con un elemento de leyenda, ¡pero el fondo permanece visible! No hay forma de reproducir esto con ninguna otra combinación de elementos.
Para colmo, las implementaciones están llenas de concesiones al comportamiento heredado. Una de ellas es que el ancho mínimo de un fieldset nunca es menor que el ancho intrínseco de su contenido. WebKit le ofrece una forma de anular este comportamiento especificándolo en la hoja de estilo predeterminada, pero Gecko² va un paso más allá y lo aplica en el motor de renderizado .
Sin embargo, los elementos de la tabla interna constituyen un tipo de marco especial en Gecko. Las restricciones dimensionales para los elementos con estos valores de display
establecidos se calculan en una ruta de código separada , evitando por completo el ancho mínimo impuesto impuesto en los conjuntos de campos.
Nuevamente, el error para esto se corrigió en Firefox 53, por lo que no necesita este truco si solo está apuntando a versiones más nuevas.
¿Es seguro usar @-moz-document
?
Para este único problema, sí. @-moz-document
funciona según lo previsto en todas las versiones de Firefox hasta 53, donde se corrige este error.
Esto no es un accidente. Debido en parte a esta respuesta, el error para limitar @-moz-document
al usuario / UA hojas de estilo se hizo dependiente de que el error de conjunto de campo subyacente se corrigiera primero.
Más allá de esto, ya no recomiendo usar @-moz-document
para apuntar exclusivamente a Firefox en tu CSS, a pesar de otros recursos.
¹ El valor puede ser prefijado. De acuerdo con un lector, esto no tiene ningún efecto en el navegador de stock de Android 4.1.2 y posiblemente en otras versiones antiguas; No he tenido tiempo de verificar esto.
² Todos los enlaces a la fuente de Gecko en esta respuesta se refieren al conjunto de cambios 5065fdc12408 , comprometido el 29 de julio de 2013; es posible que desee comparar las notas con la revisión más reciente de Mozilla Central .
³ Ver, por ejemplo, SO # 953491: Dirigirse solo a Firefox con CSS y trucos CSS: hacks CSS dirigidos a Firefox para artículos ampliamente referenciados en sitios de alto perfil.
He luchado durante muchas horas con esto y, básicamente, el navegador está aplicando un estilo computarizado que necesitas anular en tu CSS. Olvidé la propiedad exacta que se está configurando en los elementos de conjunto de fieldset
frente a div
s (¿tal vez min-width
?).
Mi mejor consejo sería cambiar su elemento a un div
, copiar los estilos computados de su inspector, luego cambiar su elemento de nuevo a fieldset
y comparar los estilos computados para encontrar al culpable.
Espero que ayude.
Actualización: Agregar display: table-cell
ayuda de display: table-cell
en navegadores que no sean de Chrome.
.fake-select { white-space:nowrap; }
.fake-select { white-space:nowrap; }
hizo que el fieldset interpretara el elemento .fake-select
por su ancho original, en lugar de su ancho forzado (incluso cuando el desbordamiento está oculto).
Elimine esa regla y cambie el .fake-select
max-width:100%
a solo width:100%
y todo se ajusta. La advertencia es que ves todo el contenido de la selección falsa, pero no creo que esto sea tan malo, y ahora encaja horizontalmente.
Actualización: con las reglas actuales en el siguiente violín (que contiene solo selecciones reales), los hijos del conjunto de campos están restringidos a los anchos correctos. Además de eliminar las reglas para .fake-select
y corregir los comentarios (desde // comment
hasta /* comment */
, he notado cambios en el CSS del violín.
Ahora entiendo mejor tu problema, y el violín refleja algún progreso. Configuro las reglas predeterminadas para todas las <select>
s, y reservo .xxlarge
para las que sabes que serán más anchas que 480px (y esto solo funciona porque conoces el ancho de #viewport
, y puedes agregar la clase manualmente a las demasiado anchas). Solo requiere un poco de prueba)
Safari en iOS problema con respuesta seleccionada
Me pareció que la respuesta de Jordan Gray era particularmente útil. Sin embargo, no parece resolver este problema en Safari iOS para mí.
El problema para mí es simplemente que el fieldset no puede tener un ancho automático si el elemento tiene un ancho máximo como% de ancho.
Solución para el problema
El simple hecho de configurar el fieldset para que tenga un ancho del 100% de su contenedor parece solucionar este problema.
Ejemplo
fieldset {
min-width: 0;
width: 100%;
}
Consulte los ejemplos de trabajo a continuación: si elimina el% de ancho del conjunto de campos o lo reemplaza con automático, no continuará funcionando.