<fieldset> ändert die Größe falsch; scheint nicht entfernbare "min-width: min-content" zu haben

221

Problem

Ich habe einen, <select>bei dem einer der <option>Textwerte sehr lang ist. Ich möchte, dass die <select>Größe geändert wird, damit sie niemals breiter als das übergeordnete Element ist, auch wenn der angezeigte Text abgeschnitten werden muss. max-width: 100%sollte das tun.

Vor dem Ändern der Größe:

Die Seite vor der Größenänderung zeigt den gesamten <code> select </ code> an

Was ich nach der Größenänderung möchte:

Meine gewünschte Seite nach der Größenänderung, wobei der Inhalt mit <code> select </ code> abgeschnitten wird

Wenn Sie dieses jsFiddle-Beispiel laden und die Breite des Ergebnisbedienfelds so ändern, dass sie kleiner als die des ist <select>, können Sie feststellen, dass die Auswahl innerhalb des Beispiels <fieldset>die Breite nicht verkleinert.

Was ich nach der Größenänderung tatsächlich sehe:

meine aktuelle Seite nach Größenänderung mit einer Bildlaufleiste

Die entsprechende Seite mit a <div>anstelle von a wird<fieldset> jedoch ordnungsgemäß skaliert. Sie können dies sehen und Ihre Änderungen einfacher testen, wenn Sie auf einer Seite ein <fieldset>und ein <div>nebeneinander haben . Wenn Sie die umgebenden <fieldset>Tags löschen , funktioniert die Größenänderung. Das <fieldset>Tag führt irgendwie dazu, dass die horizontale Größenänderung unterbrochen wird.

Das <fieldset>Verhalten ist so, als ob es eine CSS-Regel gibt fieldset { min-width: min-content; }. ( min-contentbedeutet ungefähr die kleinste Breite, die kein Kind zum Überlaufen bringt.) Wenn ich die <fieldset>durch eine <div>mitmin-width: min-content ersetze , sieht sie genauso aus. Es gibt jedoch keine Regel min-contentin meinen Stilen, im Standard-Stylesheet des Browsers oder im CSS-Inspektor von Firebug. Ich habe versucht, jeden Stil zu überschreiben, der <fieldset>im CSS-Inspektor von Firebug und im Standard-Stylesheet forms.css von Firefox angezeigt wird , aber das hat nicht geholfen. Speziell überschrieben min-widthund widthauch nichts getan.

Code

HTML des Feldsatzes:

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

Mein CSS, das funktionieren sollte, aber nicht:

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

select {
    max-width: 100%;
}

Das Zurücksetzen der widthEigenschaften auf die Standardeinstellungen bewirkt nichts:

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

Weiteres CSS, in dem ich versuche, das Problem nicht zu beheben :

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

Mehr Details

Das Problem tritt auch in diesem umfassenderen, komplizierteren jsFiddle-Beispiel auf , das der Webseite, die ich tatsächlich zu beheben versuche, ähnlicher ist. Sie können daran erkennen, dass dies <select>nicht das Problem ist - ein Inline-Block kann divauch nicht in der Größe geändert werden. Obwohl dieses Beispiel komplizierter ist, gehe ich davon aus, dass die Korrektur für den obigen einfachen Fall auch diesen komplizierteren Fall behebt.

[Bearbeiten: siehe Details zur Browserunterstützung unten.]

Eine merkwürdige Sache bei diesem Problem ist, dass wenn Sie festlegendiv.wrapper { width: 50%; } , dass sich die <fieldset>Größe an dem Punkt ändert, an dem die volle Größe <select>den Rand des Ansichtsfensters erreicht hätte. Die Größenänderung erfolgt so, als ob das <select>hat width: 100%, obwohl das so <select>aussieht , als ob es hat width: 50%.

nach Größenänderung mit 50% -Breite Wrapper div

Wenn Sie das <select>selbst gebenwidth: 50% , tritt dieses Verhalten nicht auf; Die Breite ist einfach richtig eingestellt.

Nach Größenänderung mit 50% Breite auswählen

Ich verstehe den Grund für diesen Unterschied nicht. Aber es kann nicht relevant sein.

Ich fand auch die sehr ähnliche Frage HTML-Feldset ermöglicht es Kindern, unbegrenzt zu erweitern . Der Fragesteller konnte keine Lösung finden und vermutet, dass es keine andere Lösung gibt, als die zu entfernen <fieldset>. Aber ich frage mich, wenn es wirklich unmöglich ist, die <fieldset>Anzeige richtig zu machen , warum ist das so? Was in <fieldset>der Spezifikation oder im Standard-CSS ( ab dieser Frage ) verursacht dieses Verhalten? Dieses spezielle Verhalten wird wahrscheinlich irgendwo dokumentiert, da mehrere Browser so funktionieren.

Hintergrundziel und Anforderungen

Der Grund, warum ich dies versuche, ist das Schreiben mobiler Stile für eine vorhandene Seite mit einer großen Form. Das Formular besteht aus mehreren Abschnitten, und ein Teil davon ist in a eingeschlossen <fieldset>. Auf einem Smartphone (oder wenn Sie Ihr Browserfenster klein machen) ist der Teil der Seite mit dem <fieldset>viel breiter als der Rest des Formulars. Der größte Teil des Formulars beschränkt seine Breite in Ordnung, der Abschnitt mit dem <fieldset>jedoch nicht. Dies zwingt den Benutzer, herauszuzoomen oder nach rechts zu scrollen, um den gesamten Abschnitt anzuzeigen.

Ich bin vorsichtig <fieldset>, wenn ich das einfach entferne , da es auf vielen Seiten in einer großen App generiert wird, und ich bin mir nicht sicher, welche Selektoren in CSS oder JavaScript davon abhängen könnten.

Ich kann JavaScript verwenden, wenn ich muss, und eine JavaScript-Lösung ist besser als nichts. Aber wenn JavaScript der einzige Weg ist, dies zu tun, wäre ich gespannt auf eine Erklärung, warum dies nicht nur mit CSS und HTML möglich ist.


Bearbeiten: Browser-Unterstützung

Auf der Website muss ich Internet Explorer 8 und höher (wir haben gerade die Unterstützung für IE7 eingestellt), den neuesten Firefox und das neueste Chrome unterstützen. Diese spezielle Seite sollte auch auf iOS- und Android-Smartphones funktionieren. Für Internet Explorer 8 ist ein leicht verschlechtertes, aber immer noch verwendbares Verhalten akzeptabel.

Ich habe mein kaputtes fieldsetBeispiel in verschiedenen Browsern erneut getestet . In diesen Browsern funktioniert es tatsächlich bereits:

  • Internet Explorer 8, 9 und 10
  • Chrom
  • Chrome für Android

Es bricht in diesen Browsern:

  • Feuerfuchs
  • Firefox für Android
  • Internet Explorer 7

Daher ist Firefox (sowohl auf dem Desktop als auch auf dem Handy) der einzige Browser, der mir wichtig ist, dass der aktuelle Code einbricht. Wenn der Code so repariert würde, dass er in Firefox funktioniert, ohne ihn in anderen Browsern zu beschädigen, würde dies mein Problem lösen.

Die Site-HTML-Vorlage verwendet bedingte Internet Explorer-Kommentare, um Klassen wie .ie8und .oldiezum <html>Element hinzuzufügen . Sie können diese Klassen in Ihrem CSS verwenden, wenn Sie Stylingunterschiede im IE umgehen müssen. Die hinzugefügten Klassen sind dieselben wie in dieser alten Version von HTML5 Boilerplate .

Rory O'Kane
quelle
41
Herzlichen Glückwunsch zu diesem ausgezeichneten Artikel
Alp
Ihr einfaches Beispiel: Geben Sie <fieldset>(oder div.wrapper) die Breite an, die es benötigt, und select { width:100% }. max-widthscheint dem Element einige% der ursprünglichen Breite des übergeordneten Elements zu geben , skaliert dann nicht, wohingegen widthes mit dem übergeordneten Element skaliert. Ich denke, das wird tun, was Sie wollen (aber ich hätte es falsch verstehen können). Versuchen Sie in Ihrer komplexeren Geige, den Feldern in der linken Spalte eine% -Breite und eine Min-Pixel-Breite zuzuweisen. Geben Sie dann die Felder rechts 100 - (linke Felder -% - Breite)% Breite an.
Trojaner
Ich hatte gerade einen anderen Gedanken: Was ist, wenn Sie die minimale Breite des Feldsatzes auf 0 setzen? Das allein wird das Problem wahrscheinlich nicht lösen, aber es lohnt sich möglicherweise, es herauszufinden. Ich arbeite jetzt einen anderen Weg, aber wenn es nicht funktioniert, werde ich das auch ausprobieren
Trojaner
Benötigen Sie die Bezeichnung und das Feld, um in derselben Zeile zu bleiben? Bei kleinen Ansichtsfenstern überlappen sie sich. Warum nicht etwas reaktionsschneller machen und bei Bedarf in eine neue Zeile wechseln?
Trojaner

Antworten:

346

Update (25. September 2017)

Der unten beschriebene Firefox-Fehler wurde ab Firefox 53 behoben und der Link zu dieser Antwort wurde endgültig aus der Bootstrap-Dokumentation entfernt .

Ich entschuldige mich auch aufrichtig bei den Mozilla-Mitwirkenden, die das Entfernen der Unterstützung -moz-documentteilweise aufgrund dieser Antwort blockieren mussten .

Die Reparatur

In WebKit und Firefox 53+, die Sie gerade eingestellt min-width: 0;auf der Fieldset den Standardwert außer Kraft zu setzen min-content

Trotzdem ist Firefox ein bisschen… seltsam, wenn es um Feldsätze geht. Damit dies in früheren Versionen funktioniert, müssen Sie die displayEigenschaft des Feldsatzes in einen der folgenden Werte ändern :

  • table-cell (empfohlen)
  • table-column
  • table-column-group
  • table-footer-group
  • table-header-group
  • table-row
  • table-row-group

Davon empfehle ichtable-cell . Beides table-rowund table-row-groupverhindern, dass Sie die Breite ändern, während table-columnund table-column-groupverhindern , dass Sie die Höhe ändern.

Dies wird (etwas vernünftigerweise) das Rendern im IE unterbrechen. Da dies nur von Gecko benötigt wird, können Sie zu Recht eine der proprietären CSS-Erweiterungen@-moz-document von Mozilla verwenden , um sie vor anderen Browsern zu verbergen:

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

(Hier ist eine jsFiddle-Demo .)


Das behebt Dinge, aber wenn Sie so etwas wie ich sind, war Ihre Reaktion so etwas wie ...

Was.

Es gibt einen Grund, aber es ist nicht schön.

Die Standarddarstellung des Feldsatzelements ist absurd und in CSS im Wesentlichen nicht anzugeben. Denken Sie darüber nach: Der Rand des Feldsatzes verschwindet dort, wo er von einem Legendenelement überlappt wird, aber der Hintergrund bleibt sichtbar! Es gibt keine Möglichkeit, dies mit einer anderen Kombination von Elementen zu reproduzieren.

Um das Ganze abzurunden, sind Implementierungen voller Zugeständnisse an das bisherige Verhalten. Eine davon ist, dass die minimale Breite eines Feldsatzes niemals kleiner ist als die intrinsische Breite seines Inhalts. Mit WebKit können Sie dieses Verhalten überschreiben, indem Sie es im Standard-Stylesheet angeben. Gecko² geht jedoch noch einen Schritt weiter und erzwingt es in der Rendering-Engine .

Interne Tabellenelemente bilden jedoch einen speziellen Rahmentyp in Gecko. Dimensionsbeschränkungen für Elemente mit diesen festgelegten displayWerten werden in einem separaten Codepfad berechnet , wobei die erzwungene Mindestbreite für Feldsätze vollständig umgangen wird.

Wiederum - der Fehler hierfür wurde ab Firefox 53 behoben, sodass Sie diesen Hack nicht benötigen, wenn Sie nur auf neuere Versionen abzielen.

Ist die Verwendung @-moz-documentsicher?

Für diese eine Ausgabe ja. @-moz-documentfunktioniert wie vorgesehen in allen Versionen von Firefox bis 53, wo dieser Fehler behoben ist.

Das ist kein Zufall. Aufgrund dieser Antwort teilweise die Fehler zu begrenzen , @-moz-documentum Benutzer / UA Sheets wurde abhängig von den zugrunde liegenden Fieldset Fehlern gemacht wird zunächst festgelegt.

Darüber hinaus, verwenden Sie nicht @-moz-documentzu Firefox in Ihrem CSS Ziel , andere Ressourcen notwithstanding.³


¹ Wert kann vorangestellt werden. Laut einem Leser hat dies keine Auswirkungen auf Android 4.1.2 Stock Browser und möglicherweise andere alte Versionen. Ich hatte keine Zeit, dies zu überprüfen.

² Alle Links zur Gecko-Quelle in dieser Antwort beziehen sich auf den Änderungssatz 5065fdc12408 , der am 29. Juli 2013 zugesagt wurde. Möglicherweise möchten Sie Notizen mit der neuesten Version von Mozilla Central vergleichen .

³ Siehe z. B. SO # 953491: Nur Firefox mit CSS und CSS-Tricks ausrichten: CSS-Hacks, die auf Firefox abzielen, finden Artikel mit häufigem Bezug auf hochkarätige Websites.

Jordan Gray
quelle
5
Ich hatte gerade bemerkt, dass das Update im IE kaputt gegangen ist, nur um hierher zu kommen und herauszufinden, dass Sie die Lösung dafür bereits bearbeitet haben. Vielen Dank! Die Gecko-Hack-Lösung funktioniert für mich in jedem Browser einwandfrei.
Rory O'Kane
Ich habe mir bei diesem Problem die Haare ausgezogen, aber Ihre Lösung ist perfekt - außer es scheint nur in Firefox zu funktionieren. Irgendwelche Vorschläge für andere Browser, insbesondere für mobile Browser? Mein größtes Problem ist die Größenänderung aufgrund von Orientierungsänderungen auf Mobilgeräten ...
Adriaan Nel
30
Dies ist eine absolut hervorragende Antwort - gründlich, recherchiert und prägnant. Vielen Dank.
Iamkeir
16
Natürlich ist es eine absolut hervorragende Antwort! Bootstrap offizielle Dokumentation Punkte hier
Ranhiru Jude Cooray
1
Nun, das wusste ich nie über Feldsätze. Ich habe heute hier etwas gelernt.
Superluminary
11

Safari unter iOS Problem mit ausgewählter Antwort

Ich fand die Antwort von Jordan Gray besonders hilfreich. Allerdings schien es dieses Problem unter Safari iOS für mich nicht zu lösen.

Das Problem für mich ist einfach, dass die Feldmenge keine automatische Breite haben kann, wenn das Element darin eine maximale Breite als% Breite hat.

Problem behoben

Das einfache Einstellen des Feldsatzes auf eine Breite von 100% des Containers scheint dieses Problem zu umgehen.

Beispiel

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

Arbeitsbeispiele finden Sie unten. Wenn Sie die% width aus dem Feldset entfernen oder durch auto ersetzen, funktioniert sie nicht weiter.

JSFiddle | Codepen

Eber
quelle
1
Dies ist eine großartige Ergänzung zum allgemeinen Problem. Ich habe nicht daran gedacht, es unter iOS zu testen. :) Ich denke fast, das könnte es wert sein, dass du es auch als neue Frage stellst und selbst beantwortest. Ich werde versuchen, diese Woche einige zusätzliche Tests durchzuführen und auf diese Antwort zu verlinken, wenn es funktioniert.
Jordan Gray
3

Ich habe viele Stunden damit zu kämpfen, und im Grunde wendet der Browser das berechnete Styling an, das Sie in Ihrem CSS überschreiben müssen. Ich vergesse die genaue Eigenschaft, die für fieldsetElemente gegenüber divs festgelegt wird (vielleicht min-width?).

Mein bester Rat wäre, Ihr Element in a zu ändern div, die berechneten Stile von Ihrem Inspektor zu kopieren, dann Ihr Element wieder in zu ändern fieldsetund die berechneten Stile zu vergleichen, um den Schuldigen zu finden.

Hoffentlich hilft das.

Update: Hinzufügen von display: table-cellHilfen in Nicht-Chrome-Browsern.

phdj
quelle
Ich habe jede CSS-Eigenschaft von fieldsetund divauf dieser Seite in Firebug verglichen . Es hat nicht geholfen. In Firebug waren die einzigen Eigenschaften mit unterschiedlichen Werten widthund perspective-origin. Das widthwar numerisch verschieden, aber die fieldset‚s widthwar auto, wie die div‘ s. Und das perspective-originist nur eine Funktion der width- 50% davon standardmäßig.
Rory O'Kane
In Chrome Web Inspector hat der Vergleich jedoch in gewisser Weise geholfen. Ich habe gleich nach dem Öffnen meines Beispiels herausgefunden, dass es in Chrome funktioniert! Ich hatte das min-width: 0;zu meinem Beispiel nach dem Testen in Chrome hinzugefügt , aber es scheint, dass das Problem in Chrome dadurch gelöst wurde. Der Web Inspector sagt mir, dass Chrome den Stil hat min-width: -webkit-min-content;, genau wie ich angenommen habe. Jetzt muss ich nur noch das Problem in Firefox und möglicherweise anderen Browsern lösen, in denen ich noch nicht getestet habe.
Rory O'Kane
Ich bin froh, dass es ein bisschen geholfen hat. Ich konnte mein Problem in anderen Browsern mit "display: table-cell" lösen. Ich denke nicht, dass es nicht die beste Lösung ist, aber hoffentlich funktioniert das für Sie.
Phdj
2

.fake-select { white-space:nowrap; }veranlasste die Feldmenge, das .fake-selectElement anhand seiner ursprünglichen Breite und nicht anhand seiner erzwungenen Breite zu interpretieren (selbst wenn der Überlauf ausgeblendet ist).

Entfernen Sie die Regel, und ändern Sie .fake-select‚s max-width:100%einfach width:100%und alles passt. Die Einschränkung ist, dass Sie den gesamten Inhalt der Fake-Select sehen, aber ich denke nicht, dass dies alles so schlimm ist, und es passt jetzt horizontal.

Update: Mit den aktuellen Regeln in der folgenden Geige (die nur echte Auswahlen enthält) sind die untergeordneten Elemente des Feldsatzes auf die korrekte Breite beschränkt. Abgesehen vom Entfernen von Regeln für .fake-selectund Korrigieren von Kommentaren (von // commentbis /* comment */habe ich Änderungen im CSS der Geige festgestellt.

Ich verstehe Ihr Problem jetzt besser und die Geige spiegelt einige Fortschritte wider. Ich setze Standardregeln für alle <select>s, und Reserve .xxlargefür die , die Sie wissen , wird breiter als 480px (und das funktioniert nur , weil Sie wissen , die Breite #viewportund die Klasse zu denen zu breit manuell hinzufügen können. Nur erfordert ein wenig Test )

Beweis

Trojaner
quelle
Welchen Fix Sie auch verwenden, er muss an einem tatsächlichen arbeiten <select>. Die eigentliche Seite hat nur <select>s. Der Punkt von fake-selectwar, die Layoutregeln von a zu haben, <select>ohne tatsächlich ein zu sein <select>, nur um zu zeigen, dass dieses Verhalten kein Browserfehler ist, der nur bei <select>Elementen auftritt. Das Ändern der Stile .fake-select, um weniger wie eine <select>Niederlage zu sein, besiegt den Zweck.
Rory O'Kane
Ich habe die .fake-selectBox durch eine <select>(identisch mit der bereits vorhandenen) ersetzt, um dies zu demonstrieren. Die Elemente sind alle auf die Breite des übergeordneten Elements beschränkt (außer wenn Sie darauf klicken und die Optionen ablegen, die jeweils in einer einzelnen Zeile angezeigt werden - aber ich glaube nicht, dass Sie dies steuern können). Ich habe auch alle Regeln für entfernt .fake-select. Tut die aktuelle Geige, was Sie brauchen?
Trojaner
Es tut nicht. width: 100%funktioniert mit den langen Menüs auf der Seite, funktioniert aber nicht richtig mit kurzen Menüs. Es erweitert kurze Menüs auf die volle Breite der Seite, aber ich möchte, dass kurze Menüs ihre kurze Breite behalten. Menüs sollten ihre natürliche Breite haben, wenn Platz vorhanden ist, aber 100% Breite, wenn sie für ihre Eltern zu groß sind. Das max-widthsoll man tun, aber in diesem Fall nicht.
Rory O'Kane
Ich habe einige weitere Änderungen vorgenommen, "alle <select>s" von "langen <select>s" getrennt und jetzt nur an der Hintergrundbreite gearbeitet.
Trojaner
#viewporthat auch keine feste Breite. Aus diesem Grund habe ich die Schaltfläche "Ansichtsfenstergröße ändern" auf der Seite platziert, damit Sie testen können, ob alles funktioniert, unabhängig von der Breite des Ansichtsfensters. So wie .fake-selectein Ersatz für ein reales <select>zum Testen ist, #viewportist es ein Ersatz für ein echtes Ansichtsfenster. (Ein "Ansichtsfenster" ist im Grunde ein Browserfenster). Ich habe es #viewportauf der Seite eingefügt, damit Sie leicht Elemente sehen können, die aus dem Ansichtsfenster herausragen, anstatt scrollen zu müssen, um sie zu sehen.
Rory O'Kane