web-dev-qa-db-fra.com

<fieldset> redimensionne mal; semble avoir non-amovible `min-width: min-content`

Problème

J'ai un <select> où l’une des valeurs textuelles de son <option> est très longue. Je veux que le <select> redimensionne pour qu'il ne soit jamais plus large que son parent, même s'il doit couper le texte affiché. max-width: 100% devrait le faire.

Avant de redimensionner:

the page before resize, showing the whole <code>select</code>

Ce que je veux après le redimensionnement:

my desired page after resize, with the <code>select</code> clipping its contents

Mais si vous chargez cet exemple jsFiddle et redimensionnez la largeur du panneau de résultats pour qu'elle soit plus petite que celle du <select>, vous pouvez voir que la sélection dans le <fieldset> ne parvient pas à réduire sa largeur.

Ce que je vois réellement après le redimensionnement:

my current page after resize, with a scroll bar

Cependant, la page équivalente avec un <div> au lieu d'un <fieldset> est correctement mise à l'échelle. Vous pouvez voir cela et tester vos modifications plus facilement si vous avez n <fieldset> et un <div> à côté de chaque autre sur une page . Et si vous supprimez les balises <fieldset> environnantes , le redimensionnement fonctionne. La balise <fieldset> provoque en quelque sorte le redimensionnement horizontal.

Le <fieldset> agit comme s'il existait une règle CSS fieldset { min-width: min-content; }. ( min-content signifie, en gros, la plus petite largeur qui ne provoque pas de débordement d'un enfant.) Si je remplace le <fieldset> par un <div> AVEC min-width: min-content , il est exactement le même . Pourtant, il n’existe pas de règle avec min-content dans mes styles, dans la feuille de style par défaut du navigateur ou visible dans l’inspecteur CSS de Firebug. J’ai essayé de remplacer tous les styles visibles sur le <fieldset> dans l’inspecteur CSS de Firebug et dans la feuille de style par défaut de Firefox forms.css , mais cela n’a pas aidé. Remplacer spécifiquement min-width et width n’a rien fait non plus.

Code

HTML du champs:

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

Mon CSS qui devrait fonctionner mais n’est pas:

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

select {
    max-width: 100%;
}

Réinitialiser les propriétés width à les valeurs par défaut ​​ne fait rien:

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

Autres CSS dans lesquels je essaie de résoudre le problème sans succès :

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

Plus de détails

Le problème se pose également dans cet exemple plus complet, plus compliqué de jsFiddle , qui est plus similaire à la page Web que je tente actuellement de corriger. Vous pouvez voir à partir de là que le <select> n'est pas le problème - un inline-block div ne parvient pas non plus à être redimensionné. Bien que cet exemple soit plus compliqué, je suppose que le correctif pour le cas simple ci-dessus résoudra également ce cas plus compliqué.

[Modifier: voir les détails de l'assistance du navigateur ci-dessous.]

Une chose curieuse à propos de ce problème est que si vous définissez div.wrapper { width: 50%; } , le <fieldset> arrête de se redimensionner lui-même au point; le <select> en taille réelle aurait atteint le bord de la fenêtre d'affichage. Le redimensionnement se passe comme si le <select> avait le width: 100%, même si le <select> semble avoir le width: 50%.

after resize with 50%-width wrapper div

Si vous donnez le <select> lui-même width: 50% , ce problème ne se produit pas; la largeur est simplement définie correctement.

after resize with 50%-width select

Je ne comprends pas la raison de cette différence. Mais cela peut ne pas être pertinent.

J'ai également trouvé la question très similaire HTML fieldset permet aux enfants de se développer indéfiniment . Le demandeur n'a pas pu trouver de solution et suppose qu'il n'y a pas de solution mis à part le retrait du <fieldset>. Mais je me demande s’il est vraiment impossible de faire afficher correctement le <fieldset>, pourquoi? Qu'est-ce que <fieldset> est s spec ou CSS par défaut ​​( à cause de cette question ) provoque ce comportement? Ce comportement spécial est probablement documenté quelque part, car plusieurs navigateurs fonctionnent de la sorte.

Objectif et exigences de base

J’essaie de faire cela dans le cadre de l’écriture de styles mobiles pour une page existante avec un grand formulaire. Le formulaire comporte plusieurs sections, dont une partie est entourée d'un <fieldset>. Sur un smartphone (ou si vous réduisez la fenêtre de votre navigateur), la partie de la page comportant le <fieldset> est beaucoup plus large que le reste du formulaire. La plupart du formulaire limite parfaitement sa largeur, mais la section avec le <fieldset> ne le fait pas, ce qui oblige l'utilisateur à effectuer un zoom arrière ou à faire défiler vers la droite pour voir l'ensemble de cette section.

Je me méfie simplement de supprimer le <fieldset>, car il est généré sur de nombreuses pages dans une grosse application, et je ne suis pas sûr du choix des sélecteurs en CSS ou en JavaScript.

Je peux utiliser JavaScript si besoin est, et une solution JavaScript vaut mieux que rien. Mais si JavaScript est le seul moyen de le faire, je serais curieux de savoir pourquoi cela n’est pas possible en utilisant uniquement CSS et HTML.


Edit: support du navigateur

Sur le site, je dois prendre en charge Internet Explorer 8 et les versions ultérieures (nous venons de supprimer le support pour IE7), le dernier Firefox et le dernier Chrome. Cette page particulière devrait également fonctionner sur les smartphones iOS et Android. Un comportement légèrement dégradé mais toujours utilisable est acceptable pour Internet Explorer 8.

J'ai retesté mon exemple cassé fieldset sur différents navigateurs. Cela fonctionne déjà dans ces navigateurs:

  • Internet Explorer 8, 9 et 10
  • Chrome
  • Chrome pour Android

Il se casse dans ces navigateurs:

  • Firefox
  • Firefox pour Android
  • Internet Explorer 7

Ainsi, le seul navigateur qui m'intéresse et dans lequel le code actuel s'introduit est Firefox (sur les ordinateurs de bureau comme sur les mobiles). Si le code était corrigé pour qu'il fonctionne dans Firefox sans le casser dans aucun autre navigateur, cela résoudrait mon problème.

Le modèle HTML de site utilise des commentaires conditionnels Internet Explorer pour ajouter des classes telles que .ie8 et .oldie à l'élément <html>. Vous pouvez utiliser ces classes dans votre CSS si vous devez contourner les différences de style dans IE. Les classes ajoutées sont les mêmes que dans cette ancienne version de HTML5 Boilerplate .

214
Rory O'Kane

Mise à jour (25 septembre 2017)

À mon grand soulagement, le bug de Firefox décrit ci-dessous est corrigé à partir de Firefox 53 et le lien vers cette réponse a finalement été retiré de la documentation de Bootstrap .

Le correctif

Dans WebKit et Firefox 53+, vous venez de définir _min-width: 0;_ sur le jeu de champs pour remplacer la valeur par défaut de _min-content_. ¹

Pourtant, Firefox est un peu… étrange en ce qui concerne les champs. Pour que cela fonctionne dans les versions antérieures, vous devez remplacer la propriété display de l'ensemble de champs par l'une des valeurs suivantes:

  • _table-cell_ (recommandé)
  • _table-column_
  • _table-column-group_
  • _table-footer-group_
  • _table-header-group_
  • _table-row_
  • _table-row-group_

Parmi ceux-ci, je recommande _table-cell_ . _table-row_ et _table-row-group_ vous empêchent tous deux de changer de largeur, tandis que _table-column_ et _table-column-group_ vous empêchent de changer de hauteur.

Cela va (assez raisonnablement) interrompre le rendu dans IE. Etant donné que seul Gecko en a besoin, vous pouvez à juste titre utiliser @-moz-document - une des extensions CSS propriétaires de Mozilla - pour le masquer aux autres navigateurs:

_@-moz-document url-prefix() {
    fieldset {
        display: table-cell;
    }
}
_

(Voici une démonstration de jsFiddle .)


Cela corrige les choses, mais si vous êtes un peu comme moi, votre réaction a ressemblé à…

Quoi.

il y a une raison, mais ce n'est pas joli.

La présentation par défaut de l’élément fieldset est absurde et pratiquement impossible à spécifier en CSS. Pensez-y: la bordure de la parcelle disparaît là où elle se superpose à un élément de légende, mais l'arrière-plan reste visible! Il n'y a aucun moyen de reproduire cela avec une autre combinaison d'éléments.

Pour couronner le tout, les implémentations sont pleines de concessions sur les comportements hérités. L'une d'elles est que la largeur minimale d'un ensemble de champs n'est jamais inférieure à la largeur intrinsèque de son contenu. WebKit vous donne un moyen de remplacer ce comportement en le spécifiant dans la feuille de style par défaut, mais Gecko² va encore plus loin et l'applique dans le moteur de rend .

Cependant, les éléments internes de la table constituent un type de trame spécial dans Gecko. Les contraintes dimensionnelles pour les éléments avec ces display valeurs définies sont calculées dans un chemin de code séparé , contournant entièrement la largeur minimale imposée imposée aux ensembles de champs.

Encore une fois, le bug pour ceci a été corrigé à partir de Firefox 53, vous n'avez donc pas besoin de ce hack si vous ne ciblez que des versions plus récentes.

L'utilisation de _@-moz-document_ est-elle sûre?

Pour ce seul problème, oui. _@-moz-document_ fonctionne comme prévu dans toutes les versions de Firefox jusqu’à la version 53 où ce bogue a été corrigé.

Ce n'est pas un hasard. En partie à cause de cette réponse, le bogue à limiter _@-moz-document_ aux feuilles de style utilisateur/UA a été rendu dépendant du bogue du jeu de champs sous-jacent qui a été corrigé en premier.

Au-delà de cela, je ne recommande plus d'utiliser _@-moz-document_ pour cibler exclusivement Firefox dans votre CSS, autres ressources nonobstant .³


¹ La valeur peut être préfixée. Selon un lecteur, cela n’a aucun effet dans Android 4.1.2 Stock Browser et éventuellement d’autres anciennes versions; Je n'ai pas eu le temps de vérifier cela.

² Tous les liens vers la source Gecko dans cette réponse font référence au 5065fdc12408 changeset , engagé le 29 juillet 2013; vous souhaiterez peut-être comparer les notes avec le dernière révision de Mozilla Central .

³ Voir par exemple SO # 953491: ciblant uniquement Firefox avec CSS et astuces CSS: les hacks CSS ciblant Firefox pour des articles largement référencés sur des sites de premier plan.

340
Jordan Gray

Safari sur un problème iOS avec réponse sélectionnée

J'ai trouvé la réponse de Jordan Grey particulièrement utile. Cependant, cela ne semblait pas résoudre le problème sur Safari iOS pour moi.

Le problème pour moi est simplement que le fieldset ne peut pas avoir une largeur automatique si l'élément à l'intérieur a une largeur max en% width.

Correction du problème

Régler simplement le groupe de champs pour qu'il ait 100% de la largeur de son conteneur semble résoudre ce problème.

Exemple

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

Reportez-vous à la section ci-dessous pour des exemples concrets. Si vous supprimez le% width du groupe de champs ou si vous le remplacez par auto, il ne fonctionnera plus.

JSFiddle | Codepen

11
boars

J'ai eu beaucoup de difficulté avec cela pendant de nombreuses heures, et en gros, le navigateur applique un style calculé que vous devez remplacer dans votre CSS. J'oublie la propriété exacte définie sur fieldset éléments par rapport à divs (peut-être min-width?).

Mon meilleur conseil serait de changer votre élément en un div, de copier les styles calculés à partir de votre inspecteur, puis de reconvertir votre élément en fieldset et de comparer les styles calculés pour trouver le coupable.

J'espère que ça t'as aidé.

Mise à jour: Ajouter display: table-cell aide dans les navigateurs non-Chrome.

3
phdj

.fake-select { white-space:nowrap; } a amené le fieldset à interpréter l'élément .fake-select par sa largeur d'origine plutôt que par sa largeur forcée (même lorsque le débordement est masqué).

Supprimez cette règle et remplacez .fake-select par max-width:100% par width:100% et tout ira bien. La mise en garde est que vous voyez tout le contenu de la fausse sélection, mais je ne pense pas que ce soit si mauvais, et cela correspond maintenant horizontalement.

Mise à jour: avec les règles en vigueur dans le violon suivant (qui ne contient que des sélections réelles), les enfants du fieldset sont contraints de corriger les largeurs. Outre la suppression des règles pour .fake-select et la correction des commentaires (de // comment à /* comment */, j'ai noté des modifications dans le code CSS du violon.

Je comprends mieux votre problème maintenant, et le violon reflète certains progrès. Je règle les règles par défaut pour tous les <select>s et je réserve .xxlarge pour ceux dont vous savez qu'ils auront une largeur supérieure à 480px (et cela ne fonctionne que parce que vous connaissez la largeur de #viewport, et peut ajouter manuellement la classe à ceux qui sont trop larges (nécessite juste un peu de test)

preuve

2
Trojan