<fieldset> cambia de tamaño incorrectamente; parece tener un `min-width: min-content` inamovible

Resuelto Rory O'Kane asked hace 11 años • 4 respuestas

Problema

Tengo un <select>problema en el que uno de sus <option>valores de texto es muy largo. Quiero <select>cambiar el tamaño para que nunca sea más ancho que su padre, incluso si tiene que cortar el texto mostrado. max-width: 100%debería hacer eso.

Antes de cambiar el tamaño:

la página antes de cambiar el tamaño, mostrando el <code>select</code> completo

Lo que quiero después de cambiar el tamaño:

mi página deseada después de cambiar el tamaño, con <code>select</code> recortando su contenido

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 de <fieldset>no logra reducir su ancho.

Lo que realmente veo después de cambiar el tamaño:

mi página actual después de cambiar el tamaño, con una barra de desplazamiento

Sin embargo, la página equivalente con a <div>en lugar de a<fieldset> se escala correctamente. Puede verlo y probar sus cambios más fácilmente si tiene a <fieldset>y a uno <div>al lado del otro en una página . Y si elimina las etiquetas circundantes<fieldset> , el cambio de tamaño funciona. De alguna manera, la <fieldset>etiqueta está provocando que se rompa el cambio de tamaño horizontal.

Los <fieldset>actos son como si hubiera una regla CSS fieldset { min-width: min-content; }. ( min-contentsignifica, aproximadamente, el ancho más pequeño que no hace que un niño se desborde). Si reemplazo <fieldset>con a <div>withmin-width: min-content , se ve exactamente igual. Sin embargo, no hay ninguna regla min-contenten mis estilos, en la hoja de estilos predeterminada del navegador o visible en el Inspector CSS de Firebug. Intenté anular todos los estilos visibles en el <fieldset>inspector CSS de Firebug y en la hoja de estilo predeterminada de Firefox Forms.css , pero eso no ayudó. Específicamente anulando min-widthy widthtampoco hizo 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 lo está:

fieldset {
    /* hide fieldset-specific visual features: */
    margin: 0;
    padding: 0;
    border: none;
}

select {
    max-width: 100%;
}

Restablecer las widthpropiedades a los valores predeterminados no hace nada:

fieldset {
    width: auto;
    min-width: 0;
    max-width: none;
}

Más CSS en el que intento y no logro 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 ocurre en este ejemplo de jsFiddle más completo y complicado , que es más similar a la página web que en realidad estoy tratando de arreglar. Puede ver a partir de eso que ese <select>no es el problema: un bloque en línea divtampoco cambia de tamaño. Aunque este ejemplo es más complicado, supongo que la solución para el caso simple anterior también solucionará este caso más complicado.

[Editar: consulte los detalles de compatibilidad del navegador a continuación.]

Una cosa curiosa acerca de este problema es que si configuradiv.wrapper { width: 50%; } , el <fieldset>tamaño se detiene en el punto en el que el tamaño completo <select>habría llegado al borde de la ventana gráfica. El cambio de tamaño ocurre como si lo <select>tuviera width: 100%, aunque <select>parezca que sí width: 50%.

después de cambiar el tamaño con un div contenedor de 50% de ancho

Si le das a <select>selfwidth: 50% , ese comportamiento no ocurre; el ancho simplemente está configurado correctamente.

después de cambiar el tamaño con una selección del 50% de ancho

No entiendo el motivo de esa diferencia. Pero puede que no sea relevante.

También encontré una pregunta muy similar : El conjunto de campos HTML permite a los niños expandirse indefinidamente . El autor de la pregunta no pudo encontrar una solución y supone que no hay otra solución aparte de eliminar el archivo <fieldset>. Pero me pregunto, si realmente es imposible hacer la <fieldset>visualización correcta, ¿por qué? ¿Qué en <fieldset>las especificaciones de o CSS predeterminado ( a partir de esta pregunta ) causa este comportamiento? Este comportamiento especial probablemente esté documentado en alguna parte, ya que varios navegadores funcionan así.

Objetivo y requisitos previos

La razón por la que intento hacer esto es como parte de la escritura de estilos móviles para una página existente con un formulario grande. El formulario tiene varias secciones y una parte está envuelta en un archivo <fieldset>. En un teléfono inteligente (o si hace que la ventana de su navegador sea pequeña), la parte de la página con <fieldset>es mucho más ancha que el resto del formulario. La mayor parte del formulario limita bien su ancho, pero la sección con <fieldset>no lo hace, lo que obliga al usuario a alejarse o desplazarse hacia la derecha para ver toda esa sección.

Soy cauteloso a la hora de eliminar simplemente el archivo <fieldset>, ya que se genera en muchas páginas de una aplicación grande y no estoy seguro de qué selectores en CSS o JavaScript podrían 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 usando solo CSS y HTML.


Editar: soporte del navegador

En el sitio, necesito ser compatible con Internet Explorer 8 y versiones posteriores (acabamos de dejar de admitir 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. Un comportamiento ligeramente degradado pero todavía utilizable es aceptable para Internet Explorer 8.

Volví a probar mi ejemplo rotofieldset en diferentes navegadores. De hecho, 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 y que incluye el código actual es Firefox (tanto en escritorio como en dispositivos móviles). Si el código se arreglara para que funcionara en Firefox sin romperlo en ningún otro navegador, eso resolvería mi problema.

La plantilla HTML del sitio utiliza comentarios condicionales de Internet Explorer para agregar clases .ie8al .oldieelemento <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 .

Rory O'Kane avatar Jul 01 '13 23:07 Rory O'Kane
Aceptado

Actualización (25 de septiembre de 2017)

El error de Firefox que se describe a continuación se solucionó a partir de Firefox 53 y el enlace a esta respuesta finalmente se eliminó de la documentación de Bootstrap .

Además, mis más sinceras disculpas a los contribuyentes de Mozilla que tuvieron que bloquear la eliminación del soporte en -moz-documentparte debido a esta respuesta.

La solución

En WebKit y Firefox 53+, simplemente configura min-width: 0;el conjunto de campos para anular el valor predeterminado de min-content

Aún así, Firefox es un poco... extraño cuando se trata de conjuntos de campos. Para que esto funcione en versiones anteriores, debe cambiar la displaypropiedad del conjunto de campos 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, recomiendotable-cell . Ambos table-rowy table-row-grouple impiden cambiar el ancho, mientras que table-columny table-column-grouple impiden cambiar la altura.

Esto (de manera algo razonable) interrumpirá el procesamiento en IE. Dado que solo Gecko necesita esto, puedes usar justificadamente @-moz-documentuna de las extensiones CSS patentadas 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 como...

Qué.

Hay una razón, pero no es bonita.

La presentación predeterminada del elemento de conjunto de campos 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 conjunto de campos 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 internos de la mesa constituyen un tipo de marco especial en Gecko. Las restricciones dimensionales para elementos con estos displayvalores establecidos se calculan en una ruta de código separada , evitando por completo el ancho mínimo impuesto en los conjuntos de campos.

Nuevamente, el error de esto se solucionó a partir de Firefox 53, por lo que no necesita este truco si solo apunta a versiones más nuevas.

@-moz-document¿Es seguro usarlo ?

Para este tema, sí. @-moz-documentfunciona según lo previsto en todas las versiones de Firefox hasta la 53, donde se solucionó este error.

Esto no es un accidente. Debido en parte a esta respuesta, el error para limitar @-moz-documenta las hojas de estilo del usuario/UA dependía de que el error subyacente del conjunto de campos se solucionara primero.

Más allá de esto, no lo utilices @-moz-documentpara apuntar a Firefox en tu CSS , independientemente de otros recursos.³


¹ El valor puede tener un prefijo. Según un lector, esto no tiene ningún efecto en Android 4.1.2 Stock Browser y posiblemente en otras versiones antiguas; No he tenido tiempo de comprobar esto.

² Todos los enlaces a la fuente de Gecko en esta respuesta se refieren al conjunto de cambios 5065fdc12408 , confirmado el 29ᵗʰ de julio de 2013; es posible que desee comparar notas con la revisión más reciente de Mozilla Central .

³ Consulte, por ejemplo, SO #953491: Dirigirse solo a Firefox con CSS y Trucos de CSS: Trucos de CSS dirigidos a Firefox para obtener artículos ampliamente referenciados en sitios de alto perfil.

Jordan Gray avatar Jul 25 '2013 16:07 Jordan Gray

Problema de Safari en iOS con la respuesta seleccionada

La respuesta de Jordan Gray me pareció particularmente útil. Sin embargo, no pareció resolver este problema en Safari iOS.

El problema para mí es simplemente que el conjunto de campos no puede tener un ancho automático si el elemento dentro tiene un ancho máximo como% de ancho.

Solución al problema

Simplemente configurar el conjunto de campos para que tenga un ancho del 100% de su contenedor parece solucionar este problema.

Ejemplo

fieldset {
    min-width: 0; 
    width: 100%; 
}

Consulte lo siguiente para ver ejemplos prácticos: si elimina el % de ancho del conjunto de campos o lo reemplaza con automático, no seguirá funcionando.

JSFiddle | codepen

boars avatar Apr 23 '2014 08:04 boars

He luchado durante muchas horas con esto y, básicamente, el navegador está aplicando un estilo computarizado que debes anular en tu CSS. Olvidé la propiedad exacta que se establece en fieldsetelementos versus divs (¿quizás min-width?).

Mi mejor consejo sería cambiar su elemento a div, copiar los estilos calculados de su inspector, luego volver a cambiar su elemento fieldsety comparar los estilos calculados para encontrar al culpable.

Espero que ayude.

Actualización: agregar display: table-cellayudas en navegadores que no son Chrome.

phdj avatar Jul 23 '2013 23:07 phdj