225 votes

<fieldset> se redimensionne mal ; semble avoir un `min-width : min-content` inamovible

Problème

J'ai un <select> où l'un de ses <option> Le texte des valeurs de l'entreprise est très long. Je veux que le <select> 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 charger cet exemple jsFiddle et redimensionnez la largeur du panneau "Résultat" pour qu'elle soit inférieure à celle de l'écran de l'utilisateur. <select> vous pouvez voir que la sélection à l'intérieur du <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, le page équivalente avec un <div> au lieu d'un <fieldset> se met à l'échelle correctement. Vous pouvez le voir et tester plus facilement vos modifications si vous avez a <fieldset> et un <div> à côté les uns des autres sur une même page . Et si vous supprimer l'environnement <fieldset> tags le redimensionnement fonctionne. Le site <fieldset> est en quelque sorte à l'origine de la rupture du redimensionnement horizontal.

El <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 fait pas déborder un enfant). Si je remplace le <fieldset> avec un <div> con min-width: min-content c'est exactement la même chose. Pourtant, il n'y a 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 dans la feuille de style par défaut du navigateur. <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é. Plus précisément, le remplacement de min-width y width n'a rien fait non plus.

Code

HTML du jeu de 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 ne fonctionne pas :

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

select {
    max-width: 100%;
}

Réinitialisation de la width les propriétés à les valeurs par défaut ne fait rien :

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

Autres CSS dans lesquels je essayer et échouer à résoudre le problème :

/* 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 cette exemple jsFiddle plus complet et plus compliqué qui est plus proche de la page web que j'essaie de corriger. Vous pouvez voir que le <select> n'est pas le problème - un bloc en ligne div ne parvient pas non plus à redimensionner. Bien que cet exemple soit plus compliqué, je suppose que la correction du cas simple ci-dessus résoudra également ce cas plus compliqué.

(voir les détails de la prise en charge 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 au moment où la taille réelle <select> aurait touché le bord de la fenêtre. Le redimensionnement se fait comme si le <select> a width: 100% même si le <select> On dirait qu'il a width: 50% .

after resize with 50%-width wrapper div

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

after resize with 50%-width select

Je ne comprends pas la raison de cette différence. Mais elle n'est peut-être pas pertinente.

J'ai également trouvé la question très similaire Le jeu de champs HTML permet aux enfants de s'étendre indéfiniment . Le demandeur ne trouvait pas de solution et devine qu'il n'y a pas de solution en dehors de la suppression de la <fieldset> . Mais je me demande, si c'est vraiment impossible de faire le <fieldset> affichage droit, pourquoi ça ? Qu'est-ce que <fieldset> 's spec o CSS par défaut ( à partir de cette question ) provoque ce comportement ? Ce comportement spécial est probablement documenté quelque part, puisque plusieurs navigateurs fonctionnent de cette manière.

Objectif et exigences de base

J'essaie de le faire dans le cadre de l'écriture de styles mobiles pour une page existante comportant un grand formulaire. Le formulaire comporte plusieurs sections, dont une partie est enveloppée dans un fichier de type <fieldset> . Sur un smartphone (ou si vous réduisez la taille de la fenêtre de votre navigateur), la partie de la page comportant le symbole <fieldset> est beaucoup plus large que le reste de la forme. La largeur de la plus grande partie du formulaire est bien limitée, mais la section avec l'icône <fieldset> ne le fait pas, ce qui oblige l'utilisateur à faire un zoom arrière ou un défilement vers la droite pour voir toute cette section.

Je me méfie de la suppression pure et simple de la <fieldset> Il est généré sur de nombreuses pages d'une grande application et je ne sais pas quels sélecteurs CSS ou JavaScript peuvent en dépendre.

Je peux utiliser JavaScript si j'en ai besoin, et une solution JavaScript est mieux que rien. Mais si JavaScript est le seul moyen de faire cela, je serais curieux d'entendre une explication sur la raison pour laquelle cela n'est pas possible en utilisant seulement CSS et HTML.


Modifier : support du navigateur

Sur le site, je dois prendre en charge Internet Explorer 8 et plus (nous venons d'abandonner la prise en charge d'IE7), la dernière version de Firefox et la dernière version de Chrome. Cette page particulière doit é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 refait le test mon brisé fieldset exemple sur différents navigateurs. En fait, il 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 ne fonctionne pas est Firefox (sur le bureau et sur le mobile). Si le code était corrigé pour fonctionner dans Firefox sans être cassé dans les autres navigateurs, cela résoudrait mon problème.

Le modèle HTML du site utilise les commentaires conditionnels d'Internet Explorer pour ajouter des classes telles que .ie8 y .oldie à la <html> élément. 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 .

42 votes

Félicitations pour cet excellent article

0 votes

Votre exemple simple : donner <fieldset> (ou div.wrapper ) la largeur dont il a besoin, et select { width:100% } . max-width semble donner à l'élément un certain % de la valeur de son parent. original n'est pas mis à l'échelle, alors que width s'adapte à son parent. Je pense que cela fera ce que vous voulez (mais je pourrais avoir mal compris). Dans votre manipulation plus complexe, essayez de donner aux champs de la colonne de gauche un % de largeur, et une largeur minimale en pixels. Puis donnez aux champs de droite 100 - (left-fields-%-width) % de largeur.

0 votes

Je viens d'avoir une autre idée : et si vous définissiez la largeur minimale du champ à 0 ? En soi, cela ne résoudra probablement pas le problème, mais cela vaut peut-être la peine d'essayer. Je suis en train de travailler sur un autre chemin, mais si ça ne marche pas, je vais aussi essayer.

354voto

Jordan Gray Points 5441

Mise à jour (25 septembre 2017)

El Bug de Firefox décrite ci-dessous est corrigée à partir de Firefox 53 et le lien vers cette réponse a finalement été supprimé. supprimé de la documentation de Bootstrap .

Par ailleurs, je présente mes sincères excuses aux contributeurs de Mozilla qui ont dû bloquer la suppression de la prise en charge de l'initiative -moz-document en partie grâce à cette réponse.

La solution

Dans WebKit et Firefox 53+, il suffit de mettre min-width: 0; sur le jeu de champs pour remplacer la valeur par défaut de l'option min-content

Pourtant, Firefox est un peu bizarre en ce qui concerne les jeux de champs. Pour que cela fonctionne dans les versions antérieures, vous devez modifier le champ display de l'ensemble de champs à 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 . Les deux sites table-row y table-row-group vous empêchent de changer de largeur, tandis que table-column y table-column-group vous empêcher de changer de hauteur.

Cela va (assez raisonnablement) casser le rendu dans IE. Puisque seul Gecko a besoin de cela, vous pouvez utiliser à juste titre @-moz-document -un des Les extensions CSS propriétaires de Mozilla -pour le cacher aux autres navigateurs :

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

(Voici un Démonstration de jsFiddle .)


Cela arrange les choses, mais si vous êtes comme moi, votre réaction a été quelque chose comme

Quoi.

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

La présentation par défaut de l'élément fieldset est absurde et essentiellement impossible à spécifier en CSS. Pensez-y : la bordure de l'élément fieldset disparaît lorsqu'elle est recouverte par un élément de légende, mais l'arrière-plan reste visible ! Il n'y a aucun moyen de reproduire ce phénomène avec une autre combinaison d'éléments.

Pour couronner le tout, les implémentations sont pleines de concessions au comportement hérité. Par exemple, la largeur minimale d'un champ n'est jamais inférieure à la largeur intrinsèque de son contenu. WebKit vous offre la possibilité de remplacer ce comportement en le spécifiant dans la feuille de style par défaut, mais Gecko² va plus loin et l'applique dans le moteur de rendu .

Toutefois, les éléments internes du tableau constituent un type de cadre spécial dans Gecko. Les contraintes dimensionnelles pour les éléments avec ces display Les valeurs fixées sont calculées dans un chemin de code séparé ce qui permet de contourner entièrement la largeur minimale imposée aux jeux de champs.

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

Est-ce que l'on utilise @-moz-document sûr ?

Pour cette question, oui. @-moz-document fonctionne comme prévu dans toutes les versions de Firefox jusqu'à la version 53, où ce bogue est corrigé.

Ce n'est pas un accident. En partie à cause de cette réponse, le bogue pour limite @-moz-document vers des feuilles de style utilisateur/UA a été rendu dépendant de la correction préalable du bogue sous-jacent du jeu de champs.

Au-delà de ça, ne pas utiliser @-moz-document pour cibler Firefox dans votre CSS en dépit d'autres ressources.


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

² Tous les liens vers la source Gecko dans cette réponse se réfèrent à la version 5065fdc12408 changeset engagé le 29 juillet 2013 ; vous pouvez comparer vos notes avec le document la révision la plus récente de Mozilla Central .

³ Voir par exemple SO #953491 : Cibler uniquement Firefox avec CSS y Trucs et astuces CSS : Astuces CSS pour Firefox pour des articles largement référencés sur des sites à forte notoriété.

5 votes

Je venais juste de remarquer que le correctif ne fonctionnait pas dans IE, pour venir ici et découvrir que vous aviez déjà édité la solution à ce problème. Merci ! La solution du Gecko hack fonctionne bien pour moi dans chaque navigateur.

0 votes

Je m'arrachais les cheveux sur ce problème, mais votre solution est parfaite - sauf qu'elle ne semble fonctionner que dans firefox. Des suggestions pour d'autres navigateurs, notamment les navigateurs mobiles ? Mon plus gros problème est le redimensionnement dû au changement d'orientation sur les appareils mobiles...

0 votes

@AdriaanNel Pour les navigateurs WebKit, essayez min-width: 0; qui remplacera la valeur par défaut de -webkit-min-content pour les fieldsets. Cela vous aide-t-il ? :)

11voto

boars Points 31

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

La réponse de Jordan Gray m'a paru particulièrement utile. Cependant, elle ne semble pas avoir résolu le problème sur Safari iOS pour moi.

Le problème pour moi est simplement que le jeu de champs ne peut pas avoir une largeur automatique si l'élément qu'il contient a une largeur maximale en %.

Correction du problème

Il suffit de définir le jeu de champs pour qu'il ait une largeur de 100% de son conteneur pour contourner ce problème.

Ejemplo

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

Veuillez vous référer aux exemples de fonctionnement ci-dessous. Si vous supprimez le % de largeur du champ ou le remplacez par auto, il ne continuera pas à fonctionner.

JSFiddle | Codepen

1 votes

C'est un excellent complément au problème général, je n'ai pas pensé à le tester dans iOS :) Je pense presque que cela pourrait valoir la peine que vous posiez et répondiez vous-même à une nouvelle question, aussi. J'essaierai de faire quelques tests supplémentaires cette semaine et je ferai un lien vers cette réponse si elle fonctionne.

3voto

phdj Points 65

J'ai passé de nombreuses heures à me débattre avec ce problème. En fait, le navigateur applique un style calculé que vous devez remplacer par votre CSS. J'ai oublié la propriété exacte qui est définie sur fieldset éléments contre div (peut-être min-width ?).

Mon meilleur conseil serait de changer votre élément pour un div copiez les styles calculés à partir de votre inspecteur, puis remettez votre élément dans l'ordre suivant fieldset et comparez les styles calculés pour trouver le coupable.

J'espère que cela vous aidera.

Mise à jour : Ajout de display: table-cell aide dans les navigateurs non-chromes.

0 votes

J'ai comparé chaque propriété CSS de la fieldset y div en cette page dans Firebug. Cela n'a pas aidé. Dans Firebug, les seules propriétés présentant des valeurs différentes sont les suivantes width y perspective-origin . El width était numériquement différent, mais le fieldset 's width était auto comme le div 's. Et le perspective-origin est juste une fonction de la width - 50% par défaut.

0 votes

Cependant, la comparaison a été utile d'une certaine manière dans Chrome Web Inspector. J'ai découvert juste après avoir ouvert mon exemple qu'il fonctionne dans Chrome ! J'avais ajouté le min-width: 0; à mon exemple après dans Chrome, mais il semble que cela ait résolu le problème dans Chrome. L'inspecteur Web m'indique que Chrome a le style min-width: -webkit-min-content; comme je l'avais supposé. Il ne me reste donc plus qu'à résoudre le problème dans Firefox et éventuellement dans d'autres navigateurs que je n'ai pas encore testés.

0 votes

Content que ça ait aidé un peu. J'ai pu résoudre mon problème dans d'autres navigateurs avec "display : table-cell". Je ne pense pas que ce soit la meilleure solution, mais j'espère que cela fonctionne pour vous.

2voto

Trojan Points 1531

.fake-select { white-space:nowrap; } a fait en sorte que le jeu de champs interprète le .fake-select par sa largeur originale, plutôt que par sa largeur forcée (même lorsque le débordement est masqué).

Supprimez cette règle, et changez .fake-select 's max-width:100% pour juste width:100% et tout s'adapte. L'inconvénient est que vous voyez tout le contenu du faux-sélectionneur, mais je ne pense pas que ce soit si grave, et il s'adapte horizontalement maintenant.

Mise à jour : Avec les règles actuelles de l'exemple suivant (qui ne contient que de vraies sélections), les enfants du jeu de champs sont contraints à des largeurs correctes. Outre la suppression des règles pour .fake-select et la correction des commentaires (de // comment a /* comment */ J'ai noté des changements dans le CSS du violon.

Je comprends mieux votre problème maintenant, et le bidule reflète un certain progrès. J'ai défini des règles par défaut pour tous les <select> et la réserve .xxlarge pour ceux dont vous savez qu'ils seront plus larges que 480px (et ceci ne fonctionne que parce que vous connaître la largeur de #viewport et peut ajouter manuellement la classe à ceux qui sont trop larges. Cela demande juste un peu de tests)

Preuve

0 votes

Quelle que soit la solution que vous utilisez, elle doit fonctionner sur un vrai <select> . Le site actuel n'a que <select> s. Le point de fake-select était d'avoir les règles de mise en page d'un <select> sans être réellement un <select> juste pour montrer que ce comportement n'est pas un bug du navigateur qui ne se produit qu'avec <select> éléments. Ainsi, la modification des styles de .fake-select pour être moins comme un <select> va à l'encontre du but recherché.

0 votes

J'ai remplacé le .fake-select boîte avec un <select> (identique à celui déjà présent) pour faire une démonstration. Les éléments sont tous contraints à la largeur du parent (sauf lorsque vous cliquez dessus, ce qui fait descendre les options, qui sont toutes affichées sur une seule ligne - mais je ne pense pas que vous puissiez contrôler cela). J'ai également supprimé toutes les règles pour .fake-select . Le violon actuel répond-il à vos besoins ?

0 votes

Ce n'est pas le cas. width: 100% fonctionne avec les longs menus de la page, mais ne fonctionne pas correctement avec les menus courts. Il étend les menus courts à toute la largeur de la page, mais je veux que les menus courts conservent leur largeur réduite. Les menus doivent avoir leur largeur naturelle s'il y a de la place, mais une largeur de 100 % s'ils sont trop grands pour leur parent. C'est pourquoi max-width est censé faire, mais ne le fait pas dans ce cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X