<fieldset> mengubah ukuran salah; tampaknya memiliki `min-width: min-content` yang tidak dapat dihapus

221

Masalah

Saya punya tempat di <select>mana salah satu <option>nilai teksnya sangat panjang. Saya ingin <select>mengubah ukuran sehingga tidak pernah lebih luas dari induknya, bahkan jika harus memotong teks yang ditampilkan. max-width: 100%harus melakukan itu.

Sebelum mengubah ukuran:

halaman sebelum mengubah ukuran, menampilkan seluruh <code> pilih </code>

Apa yang saya inginkan setelah mengubah ukuran:

halaman yang saya inginkan setelah mengubah ukuran, dengan <code> pilih </code> kliping isinya

Tetapi jika Anda memuat contoh jsFiddle ini dan mengubah ukuran lebar panel Hasil menjadi lebih kecil dari itu <select>, Anda dapat melihat bahwa pilih di dalam <fieldset>gagal untuk skala lebar ke bawah.

Apa yang sebenarnya saya lihat setelah mengubah ukuran:

halaman saya saat ini setelah mengubah ukuran, dengan bilah gulir

Namun, halaman yang setara dengan skala <div>bukannya<fieldset> skala yang benar. Anda dapat melihat itu dan menguji perubahan Anda lebih mudah jika Anda memiliki sebuah <fieldset>dan <div>di samping satu sama lain pada satu halaman . Dan jika Anda menghapus <fieldset>tag di sekitarnya , ukurannya berfungsi. The <fieldset>tag entah bagaimana menyebabkan Resize horisontal untuk istirahat.

The <fieldset>bertindak seolah-olah ada aturan CSS fieldset { min-width: min-content; }. ( min-contentBerarti, kira-kira, lebar terkecil yang tidak menyebabkan anak meluap.) Jika saya mengganti <fieldset>dengan <div>denganmin-width: min-content , tampilannya persis sama. Namun tidak ada aturan min-contentdalam style saya, di stylesheet default browser, atau terlihat di Firebug's CSS Inspector. Saya mencoba untuk mengesampingkan setiap gaya yang terlihat <fieldset>di Firebug's CSS Inspector dan di stylesheet forms.css default Firefox , tetapi itu tidak membantu. Khususnya mengesampingkan min-widthdan widthtidak melakukan apa pun juga.

Kode

HTML dari fieldset:

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

CSS saya yang seharusnya berfungsi tetapi tidak:

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

select {
    max-width: 100%;
}

Mengatur ulang widthproperti ke default tidak menghasilkan apa-apa:

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

CSS lebih lanjut di mana saya mencoba dan gagal untuk memperbaiki masalah :

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

Keterangan lebih lanjut

Masalahnya juga terjadi pada contoh jsFiddle yang lebih komprehensif dan lebih rumit ini , yang lebih mirip dengan halaman web yang sebenarnya saya coba perbaiki. Anda dapat melihat bahwa itu <select>bukan masalahnya - blok inline divjuga gagal untuk mengubah ukuran. Meskipun contoh ini lebih rumit, saya berasumsi bahwa perbaikan untuk kasus sederhana di atas juga akan memperbaiki kasus yang lebih rumit ini.

[Edit: lihat detail dukungan browser di bawah ini.]

Satu hal yang aneh tentang masalah ini adalah bahwa jika Anda mengaturdiv.wrapper { width: 50%; } , <fieldset>berhenti mengubah ukuran dirinya sendiri pada titik maka ukuran penuh <select>akan menyentuh tepi viewport. Mengubah ukuran terjadi seolah-olah <select>telah width: 100%, meskipun <select>sepertinya sudah width: 50%.

setelah mengubah ukuran dengan div pembungkus bandwidth 50%

Jika Anda memberikan <select>dirinya sendiriwidth: 50% , perilaku itu tidak terjadi; lebar hanya diatur dengan benar.

setelah diubah ukurannya dengan 50%-lebar pilih

Saya tidak mengerti alasan perbedaan itu. Tapi itu mungkin tidak relevan.

Saya juga menemukan pertanyaan HTML yang sangat mirip, memungkinkan anak-anak berkembang tanpa batas . Penanya tidak dapat menemukan solusi dan menebak bahwa tidak ada solusi selain menghapus <fieldset>. Tapi saya bertanya-tanya, jika benar-benar tidak mungkin membuat <fieldset>tampilan menjadi benar, mengapa begitu? Apa yang di <fieldset>'s spesifikasi atau standar CSS ( sebagai pertanyaan ini ) menyebabkan perilaku ini? Perilaku khusus ini mungkin didokumentasikan di suatu tempat, karena beberapa browser berfungsi seperti ini.

Tujuan dan persyaratan latar belakang

Alasan saya mencoba melakukan ini adalah sebagai bagian dari penulisan gaya seluler untuk halaman yang ada dengan bentuk besar. Formulir ini memiliki beberapa bagian, dan satu bagian dibungkus dengan a <fieldset>. Pada ponsel cerdas (atau jika Anda membuat jendela peramban Anda kecil), bagian halaman dengan jendela <fieldset>jauh lebih lebar daripada bagian lainnya. Sebagian besar bentuk membatasi lebar dengan baik, tetapi bagian dengan <fieldset>tidak, memaksa pengguna untuk memperkecil atau gulir ke kanan untuk melihat semua bagian itu.

Saya khawatir hanya menghapus <fieldset>, karena dihasilkan pada banyak halaman di aplikasi besar, dan saya tidak yakin apa yang pemilih tergantung pada CSS atau JavaScript.

Saya dapat menggunakan JavaScript jika perlu, dan solusi JavaScript lebih baik daripada tidak sama sekali. Tetapi jika JavaScript adalah satu-satunya cara untuk melakukan ini, saya ingin tahu penjelasan mengapa ini tidak mungkin hanya menggunakan CSS dan HTML.


Edit: dukungan browser

Di situs tersebut, saya perlu mendukung Internet Explorer 8 dan yang lebih baru (kami baru saja menjatuhkan dukungan untuk IE7), Firefox terbaru, dan Chrome terbaru. Halaman khusus ini juga dapat berfungsi di iOS dan Android smartphone. Perilaku yang sedikit terdegradasi tetapi masih dapat digunakan dapat diterima untuk Internet Explorer 8.

Saya menguji ulang contoh rusak sayafieldset di browser yang berbeda. Ini sebenarnya sudah berfungsi di browser ini:

  • Internet Explorer 8, 9, dan 10
  • Chrome
  • Chrome untuk Android

Itu rusak di browser ini:

  • Firefox
  • Firefox untuk Android
  • Internet Explorer 7

Jadi, satu-satunya peramban yang saya pedulikan tentang kode saat ini adalah Firefox (pada desktop dan seluler). Jika kodenya diperbaiki sehingga berfungsi di Firefox tanpa merusaknya di peramban lain, itu akan menyelesaikan masalah saya.

Templat HTML situs menggunakan komentar bersyarat Internet Explorer untuk menambahkan kelas tersebut .ie8dan .oldieke <html>elemen. Anda dapat menggunakan kelas-kelas itu di CSS Anda jika Anda perlu mengatasi perbedaan gaya dalam IE. Kelas yang ditambahkan sama dengan versi HTML5 Boilerplate yang lama ini .

Rory O'Kane
sumber
41
selamat untuk artikel yang bagus ini
Alp
Contoh sederhana Anda: berikan <fieldset>(atau div.wrapper) lebar apa pun yang dibutuhkan, dan select { width:100% }. max-widthtampaknya memberikan elemen beberapa% dari lebar asli induknya , kemudian tidak menskala, sedangkan widthskala dengan induknya. Saya pikir itu akan melakukan apa yang Anda inginkan (tapi saya bisa salah paham). Di biola yang lebih kompleks, coba beri bidang di kolom kiri% -width, dan lebar min-pixel. Kemudian berikan bidang di sebelah kanan 100 - (bidang kiri -% - lebar)% lebar.
Trojan
Saya hanya punya pemikiran lain: bagaimana jika Anda mengatur min-lebar fieldset ke 0? Itu dengan sendirinya mungkin tidak akan menyelesaikan masalah, tetapi mungkin layak untuk dicoba. Saya bekerja di jalur yang berbeda sekarang, tetapi jika tidak berhasil saya akan mencobanya juga
Trojan
Apakah Anda memerlukan label dan bidang untuk tetap di jalur yang sama? Untuk viewports kecil, mereka tumpang tindih. Mengapa tidak membuatnya agak responsif, dan memutuskan jalur baru jika perlu?
Trojan

Jawaban:

346

Pembaruan (25 September 2017)

The Firefox bug dijelaskan di bawah adalah tetap pada Firefox 53 dan link untuk jawaban ini akhirnya telah dihapus dari dokumentasi Bootstrap ini .

Juga, permintaan maaf tulus saya kepada kontributor Mozilla yang harus memblokir menghapus dukungan untuk -moz-documentsebagian karena jawaban ini.

Cara mengatasinya

Di WebKit dan Firefox 53+, Anda cukup mengatur min-width: 0;fieldset untuk mengganti nilai default min-content

Namun, Firefox agak ... aneh ketika datang ke bidang. Untuk membuat ini berfungsi di versi sebelumnya, Anda harus mengubah displayproperti fieldset ke salah satu nilai berikut:

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

Dari jumlah ini, saya sarankantable-cell . Keduanya table-rowdan table-row-groupmencegah Anda mengubah lebar, sementara table-columndan table-column-groupmencegah Anda mengubah tinggi.

Ini akan (agak masuk akal) merender rendering di IE. Karena hanya Gecko yang memerlukan ini, Anda dapat menggunakan @-moz-document—salah satu ekstensi CSS milik Mozilla — untuk menyembunyikannya dari browser lain:

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

(Ini demo jsFiddle .)


Itu memperbaiki banyak hal, tetapi jika Anda seperti saya, reaksi Anda adalah seperti ...

Apa.

Ada adalah alasan, tapi itu tidak cukup.

Presentasi default dari elemen fieldset tidak masuk akal dan pada dasarnya tidak mungkin untuk ditentukan dalam CSS. Pikirkan tentang hal ini: perbatasan fieldset menghilang di mana tumpang tindih oleh elemen legenda, tetapi latar belakang tetap terlihat! Tidak ada cara untuk mereproduksi ini dengan kombinasi elemen lainnya.

Di atas itu, implementasinya penuh dengan konsesi terhadap perilaku warisan. Salah satunya adalah bahwa lebar minimum fieldset tidak pernah kurang dari lebar intrinsik isinya. WebKit memberi Anda cara untuk mengesampingkan perilaku ini dengan menetapkannya di stylesheet default, tetapi Gecko² melangkah lebih jauh dan memaksanya dalam mesin rendering .

Namun, elemen tabel internal merupakan jenis bingkai khusus di Gecko. Batasan dimensi untuk elemen dengan displaynilai - nilai ini diatur dihitung dalam jalur kode yang terpisah , sepenuhnya menghindari lebar minimum yang diberlakukan yang dikenakan pada bidang.

Sekali lagi — bug untuk ini telah diperbaiki pada Firefox 53, jadi Anda tidak perlu meretas ini jika Anda hanya menargetkan versi yang lebih baru.

Apakah menggunakan @-moz-documentaman?

Untuk masalah yang satu ini, ya. @-moz-documentberfungsi sebagaimana dimaksud di semua versi Firefox hingga 53, di mana bug ini diperbaiki.

Ini bukan kecelakaan. Sebagian karena jawaban ini, bug untuk membatasi @-moz-documentke stylesheet pengguna / UA dibuat bergantung pada bug fieldset yang mendasarinya yang diperbaiki terlebih dahulu.

Selain itu, jangan gunakan @-moz-documentuntuk menargetkan Firefox di CSS Anda , meskipun ada sumber lain.³


¹ Nilai mungkin diawali. Menurut satu pembaca, ini tidak berpengaruh pada Android 4.1.2 Stock Browser dan mungkin versi lama lainnya; Saya belum punya waktu untuk memverifikasi ini.

² Semua tautan ke sumber Gecko dalam jawaban ini merujuk pada perubahan 5065fdc12408 , yang dilakukan 29ᵗʰ Juli 2013; Anda mungkin ingin membandingkan catatan dengan revisi terbaru dari Mozilla Central .

³ Lihat misalnya SO # 953491: Menargetkan hanya Firefox dengan CSS dan Trik CSS : Peretas CSS yang menargetkan Firefox untuk artikel yang banyak direferensikan di situs profil tinggi.

Jordan Gray
sumber
5
Saya baru saja memperhatikan bahwa perbaikannya rusak di IE, hanya untuk datang ke sini dan mengetahui bahwa Anda telah mengedit dalam solusi untuk itu. Terima kasih! Solusi hack Gecko berfungsi dengan baik untuk saya di setiap browser.
Rory O'Kane
Sudah mencabut rambut saya pada masalah ini, tetapi perbaikan Anda sempurna - kecuali tampaknya hanya bekerja di firefox. Ada saran untuk peramban lain, terutama peramban seluler? Masalah terbesar saya adalah mengubah ukuran karena perubahan orientasi pada perangkat seluler ...
Adriaan Nel
30
Ini adalah jawaban yang benar-benar luar biasa - teliti, diteliti dan ringkas. Terima kasih.
iamkeir
16
Tentu saja itu jawaban yang benar-benar luar biasa! Titik dokumentasi resmi Bootstrap di sini
Ranhiru Jude Cooray
1
Yah, saya tidak pernah tahu itu tentang bidang. Saya telah belajar sesuatu di sini hari ini.
superluminary
11

Safari pada masalah iOS dengan jawaban yang dipilih

Saya menemukan jawaban dari Jordan Gray sangat membantu. Namun sepertinya itu tidak menyelesaikan masalah pada Safari iOS untuk saya.

Masalahnya bagi saya hanyalah bahwa fieldset tidak dapat memiliki lebar otomatis jika elemen di dalamnya memiliki lebar maks sebagai% lebar.

Perbaiki untuk masalah

Cukup dengan mengatur fieldset untuk memiliki lebar 100% dari wadah itu tampaknya dapat mengatasi masalah ini.

Contoh

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

Silakan lihat di bawah ini untuk contoh-contoh yang berfungsi - jika Anda menghapus% lebar dari fieldset atau menggantinya dengan otomatis, itu tidak akan terus berfungsi.

JSFiddle | Codepen

babi hutan
sumber
1
Ini merupakan tambahan yang bagus untuk masalah umum, saya tidak berpikir untuk mengujinya di iOS. :) Saya hampir berpikir ini mungkin layak Anda tanyakan dan jawab sendiri sebagai pertanyaan baru juga. Saya akan mencoba melakukan beberapa pengujian tambahan minggu ini dan menautkan ke jawaban ini jika berhasil.
Jordan Grey
3

Saya telah berjuang selama berjam-jam dengan ini, dan pada dasarnya, browser menerapkan gaya komputasi yang perlu Anda timpa dalam CSS Anda. Saya lupa properti persis yang ditetapkan pada fieldsetelemen versus divs (mungkin min-width?).

Saran terbaik saya adalah mengubah elemen Anda menjadi div, menyalin gaya yang dihitung dari inspektur Anda, kemudian mengubah elemen Anda kembali fieldsetdan membandingkan gaya yang dihitung untuk menemukan pelakunya.

Semoga itu bisa membantu.

Pembaruan: Menambahkan display: table-cellbantuan di browser non-Chrome.

phdj
sumber
Saya membandingkan setiap properti CSS pada fieldsetdan divdi halaman ini di Firebug. Itu tidak membantu. Di Firebug, satu-satunya properti dengan nilai yang berbeda adalah widthdan perspective-origin. The widthadalah numerik yang berbeda, tetapi fieldset's widthitu auto, seperti div' s. Dan perspective-originini hanyalah fungsi dari width- 50% darinya secara default.
Rory O'Kane
Namun, perbandingan memang membantu dengan cara di Web Chrome Inspektur. Saya menemukan tepat setelah pembukaan contoh saya bahwa itu berfungsi di Chrome! Saya telah menambahkan min-width: 0;ke contoh saya setelah pengujian di Chrome, tetapi sepertinya itu menyelesaikan masalah di Chrome. Inspektur Web memberi tahu saya bahwa Chrome memiliki gaya min-width: -webkit-min-content;, sama seperti yang saya duga. Jadi sekarang saya hanya perlu menyelesaikan masalah di Firefox dan mungkin browser lain yang belum saya uji.
Rory O'Kane
Senang itu sedikit membantu. Saya dapat menyelesaikan masalah saya di browser lain dengan "display: table-cell". Saya tidak berpikir itu bukan solusi terbaik, tapi semoga itu berhasil untuk Anda.
phdj
2

.fake-select { white-space:nowrap; } menyebabkan fieldset untuk menginterpretasikan .fake-select elemen dengan lebar aslinya, bukan dari lebar paksa (bahkan ketika overflow disembunyikan).

Hapus aturan itu, dan perubahan .fake-select's max-width:100%hanyawidth:100% dan semuanya cocok. Peringatannya adalah Anda melihat semua konten dari pilihan-palsu, tetapi saya tidak berpikir ini semua yang buruk, dan itu cocok secara horizontal sekarang.

Pembaruan: dengan aturan saat ini dalam biola berikut (yang hanya berisi pilihan nyata), anak-anak fieldset dibatasi untuk mengoreksi lebar. Selain menghapus aturan untuk .fake-selectdan memperbaiki komentar (dari // commentke/* comment */ , saya telah mencatat perubahan pada CSS biola.

Saya mengerti masalah Anda lebih baik sekarang, dan biola mencerminkan beberapa kemajuan. Saya menetapkan aturan default untuk semua <select>s, dan mencadangkan .xxlargeuntuk yang Anda tahu akan lebih lebar dari 480px (dan ini hanya berfungsi karena Anda tahu lebar #viewport, dan secara manual dapat menambahkan kelas ke yang terlalu lebar. Hanya perlu sedikit pengujian )

Bukti

Trojan
sumber
Perbaikan apa pun yang Anda gunakan harus bekerja pada aktual <select>. Situs yang sebenarnya hanya memiliki <select>s. Intinya fake-selectadalah memiliki aturan tata letak <select>tanpa benar-benar menjadi <select>, hanya untuk menunjukkan bahwa perilaku ini bukan bug browser yang hanya terjadi pada <select>elemen. Jadi mengubah gaya .fake-selectmenjadi kurang seperti <select>mengalahkan tujuan.
Rory O'Kane
Saya mengganti .fake-selectkotak dengan <select>(identik dengan yang sudah ada) untuk menunjukkan. Semua elemen dibatasi oleh lebar induk (kecuali ketika Anda mengkliknya, menjatuhkan opsi, yang masing-masing ditampilkan pada satu baris - tapi saya tidak berpikir Anda bisa mengendalikannya). Saya juga menghapus semua aturan untuk .fake-select. Apakah biola saat ini melakukan apa yang Anda butuhkan?
Trojan
Itu tidak. width: 100%berfungsi dengan menu panjang pada halaman, tetapi tidak berfungsi dengan baik pada menu pendek. Ini memperluas menu pendek ke lebar penuh halaman, tapi saya ingin menu pendek untuk menjaga lebar pendeknya. Menu harus menjadi lebar alami mereka jika ada kamar, tetapi lebar 100% jika terlalu besar untuk orang tua mereka. Itulah yang max-widthseharusnya dilakukan, tetapi gagal dilakukan dalam kasus ini.
Rory O'Kane
Saya telah membuat beberapa perubahan lagi, memisahkan "all <select>s" dari "long <select>s", dan hanya mengerjakan lebar latar sekarang.
Trojan
#viewportjuga tidak memiliki lebar tetap. Itu sebabnya saya meletakkan tombol Ubah Ukuran Tampilan di halaman - sehingga Anda dapat menguji bahwa semuanya berfungsi tidak peduli berapa lebar viewport itu. Sama seperti .fake-selectpengganti nyata <select>untuk pengujian, #viewportadalah pengganti untuk viewport nyata. ("Viewport" pada dasarnya adalah jendela browser). Saya memasukkan #viewportpada halaman sehingga Anda dapat dengan mudah melihat elemen yang menonjol dari viewport, daripada harus menggulir untuk melihatnya.
Rory O'Kane