Input dengan tampilan: blok bukan blok, mengapa tidak?

153

Mengapa display:block;width:auto;pada input teks saya tidak berperilaku seperti div dan mengisi lebar kontainer?

Saya mendapat kesan bahwa div hanyalah elemen blok dengan lebar otomatis. Dalam kode berikut tidak boleh div dan input memiliki dimensi yang identik?

Bagaimana saya mendapatkan input untuk mengisi lebar? Lebar 100% tidak akan berfungsi, karena input memiliki bantalan dan batas (menyebabkan lebar akhir 1 piksel + 5 piksel + 100% + 5 piksel + 1 piksel). Memperbaiki lebar bukan pilihan, dan saya mencari sesuatu yang lebih fleksibel.

Saya lebih suka jawaban langsung untuk solusi. Ini tampak seperti kekhasan CSS dan memahaminya mungkin berguna nantinya.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>width:auto</title>

        <style>
        div, input {
            border: 1px solid red;
            height: 5px;
            padding: 5px;
        }
        input, form {
            display: block;
            width: auto;
        }
        </style>
    </head>

    <body>
        <div></div>
        <form>
            <input type="text" name="foo" />
        </form>
    </body>
</html>

Saya harus menunjukkan saya sudah bisa melakukan ini dengan solusi pembungkus. Terlepas dari mengacaukan dengan semantik halaman dan hubungan pemilih CSS, saya mencoba memahami sifat masalah dan apakah itu dapat diatasi dengan mengubah sifat INPUT itu sendiri.

Ok, ini SANGAT aneh! Saya telah menemukan bahwa solusinya adalah dengan menambahkan max-width:100%ke input width:100%;padding:5px;. Namun ini menimbulkan lebih banyak pertanyaan (yang akan saya tanyakan dalam pertanyaan terpisah), tetapi tampaknya lebar menggunakan model kotak CSS normal dan lebar maksimum menggunakan model kotak batas Internet Explorer. Aneh sekali.

Oke, yang terakhir itu sepertinya adalah bug di Firefox 3. Internet Explorer 8 dan Safari 4 membatasi lebar max hingga 100% + padding + border yang menurut spesifikasi harus dilakukan. Akhirnya, Internet Explorer melakukan sesuatu yang benar.

Ya Tuhan, ini luar biasa! Dalam proses bermain dengan ini, dan dengan banyak bantuan dari guru terhormat Dean Edwards dan Erik Arvidsson , saya berhasil menyatukan tiga solusi terpisah untuk membuat cross-browser sejati 100% lebar pada elemen dengan padding dan border sewenang-wenang. Lihat jawaban di bawah ini. Solusi ini tidak memerlukan markup HTML tambahan, hanya kelas (atau pemilih) dan perilaku opsional untuk warisan Internet Explorer.

SPIFF
sumber
7
@ SleepyCod itu bukan duplikat yang tepat. Pertanyaan ini berkaitan dengan masalah inputelemen yang tampaknya tidak sesuai dengan spesifikasi CSS 2.1, sementara pertanyaan yang Anda tautkan menanyakan bagaimana mencegah kotak berlebih yang terjadi dengan sempurna dalam batas-batas spesifikasi CSS 2.1. Baik pertanyaan dan solusinya tumpang tindih tetapi menyebutnya duplikat yang tepat sama sekali salah.
amn

Jawaban:

130

Lihat apa yang saya temukan, solusi menggunakan gaya yang relatif tidak diketahui box-sizing:border-boxdari CSS 3. Ini memungkinkan lebar 100% 'benar' pada elemen apa pun terlepas dari padding dan / atau batas elemen tersebut.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">

        <title>Cross-browser CSS box-sizing:border-box</title>

        <style type="text/css">
            form {display:block; margin:0; padding:0; width:50%; border:1px solid green; overflow:visible}
            div, input {display:block; border:1px solid red; padding:5px; width:100%; font:normal 12px Arial}

            /* The voodoo starts here */
            .bb {
                box-sizing: border-box; /* CSS 3 rec */
                -moz-box-sizing: border-box; /* Firefox 2 */
                -ms-box-sizing: border-box; /* Internet Explorer 8 */
                -webkit-box-sizing: border-box; /* Safari 3 */
                -khtml-box-sizing: border-box; /* Konqueror */
            }
        </style>

        <!-- The voodoo gets scary. Force Internet Explorer 6 and Internet Explorer 7 to support Internet Explorer 5's box model -->
        <!--[if lt IE 8]><style>.bb {behavior:url("boxsizing.htc");}</style><![endif]-->
    </head>

    <body>
        <form name="foo" action="#">
            <div class="bb">div</div>
            <input class="bb" size="20" name="bar" value="field">
        </form>
    </body>
</html>

Solusi ini mendukung Internet Explorer 6 dan Internet Explorer 7 melalui perilaku yang ditulis oleh Erik Arvidsson dengan beberapa penyesuaian dari Dean Edwards untuk mendukung persentase dan lebar non-pixel lainnya.

Contoh kerja
Behavior (boxsizing.htc)

SPIFF
sumber
Ini terlihat seperti solusi yang luar biasa, tetapi tidak berfungsi di IE8 (kotak div & field tidak cukup lebar). Apakah Anda tahu jika ada pembaruan pada metode ini? Terima kasih!
rocketmonkeys
2
Polyfill ini oleh Schepp memperbarui polyfill IE6 / 7 untuk menangani lebih banyak case edge dan bekerja dengan IE8 di github: github.com/Schepp/box-sizing-polyfill
nicjohnson
Terima kasih! Saya tidak tahu mengapa <input type = text> dan <input type = submit> memiliki lebar yang berbeda ketika saya mengatur keduanya menjadi 300px lebar. Ini menyelesaikannya! Perhatikan bahwa dua tahun kemudian Anda masih perlu menggunakan awalan -moz- untuk versi terbaru Firefox. caniuse.com/#feat=css3-boxsizing
Darren Cook
4
Sayangnya, pendekatan ini tidak dapat digunakan untuk menghilangkan div pembungkus jika Anda juga perlu menambahkan margin (karena margin tidak berfungsi dengan baik pada elemen apa pun jika Anda menggunakan lebar: 100%)
SystemParadox
6
Itu tidak memperbaiki masalah sekalipun. Ya itu bekerja jika Anda menggunakan width:100%tetapi tidak jika Anda menggunakan width:auto, lihat di sini: jsfiddle.net/hGuzE
Nimrod
8

Alasan ini terjadi adalah bahwa ukuran input teks ditentukan oleh atribut ukurannya. tambahkan size = "50" di dalam tag <input>. Kemudian ubah ke size = "100" - lihat apa yang saya maksud?

Saya menduga ada solusi yang lebih baik, tetapi satu-satunya yang terlintas dalam pikiran adalah sesuatu yang saya temukan pada pertanyaan "Fitur tersembunyi HTML" pada SO: Gunakan div yang dapat diedit konten, alih-alih input. Melewati input pengguna ke formulir terlampir (jika itu yang Anda butuhkan) mungkin sedikit rumit.

Fitur tersembunyi dari HTML

MatrixFrog
sumber
8
Saya ingin tahu bagaimana orang-orang CSS membenarkan hal ini. Jika lebar dapat menimpa ukuran secara eksplisit dengan piksel / persentase, saya tidak melihat mengapa itu harus terus menghormatinya ketika elemen adalah blok.
SpliFF
1
Namun hal yang sama juga terjadi pada buttonyang tidak memiliki sizeatribut?
Zanona
1
Sebuah pertanyaan yang lebih berfokus pada bagian "mengapa standar seperti ini" seperti jawaban ini: stackoverflow.com/questions/4567988/... Klaim teratas adalah bahwa itu karena inputelemen yang diganti.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
7

Taruhan terbaik Anda adalah untuk membungkus input dalam div dengan batas, margin, dll., Dan masukkan input dengan lebar 100% dan tanpa batas, tanpa margin, dll.

Sebagai contoh,

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>width:auto</title>

        <style>
            div {
                border: 1px solid red;
                padding: 5px;
            }
            input, form {
                display: block;
                width: 100%;
            }
        </style>
    </head>

    <body>
        <form>
            <div><input type="text" name="foo" /></div>
        </form>
    </body>
</html>
Jonathan Fingland
sumber
1
Ya, itu akan berhasil tetapi itu lebih merupakan solusi daripada jawaban. Saya mencoba menentukan mengapa input tampaknya mengabaikan perilaku blok.
SpliFF
2
Jonathan, tolong maafkan kekasaran saya yang nyata di sini, tetapi saya datang ke sini untuk mencari jawaban yang tepat, dan juga dengan senang hati membaca bagian di mana @SpliFF secara khusus menyebutkan dia akan lebih memilih "jawaban langsung untuk solusi, namun Anda masih menambahkan berlebihan (seperti dalam, berulang kali berkali-kali di SO dan di tempat lain di Internet) menjawab, tampaknya mengabaikan kontrak pertanyaan. Bolehkah saya bertanya - mengapa? Terima kasih sebelumnya. -Benar-benar Anda.
amn
1

Anda bisa memalsukannya, seperti ini:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>width:auto</title>

        <style>
        div, #inputWrapper {
            border: 1px solid red;
        }
        #topDiv {
            padding: 5px;
            height: 5px;
        }
        form {
            display: block;
        }
        #inputWrapper {
            overflow: hidden;
            height: 15px;
        }
        input {
            display: block;
            width: 100%;
            border-style: none;
            padding-left: 5px;
            padding-right: 5px;
            height: 15px;
        }
        </style>
    </head>

    <body>
        <div id="topDiv"></div>
        <form>
          <div id="inputWrapper">
            <input type="text" name="foo" />
          </div>
        </form>
    </body>
</html>
Yakub
sumber
1
Saya telah melakukan pendekatan palsu di masa lalu tetapi sejujurnya saya muak dengan itu. Saya berakhir dengan segala macam retarded hacks seperti menggunakan lebar 99% untuk mendapatkan input dan memilih untuk mencocokkan. Saya benar-benar ingin cara memperlakukan input seperti div dan saya berharap saya hanya mengabaikan sesuatu.
SpliFF
2
juga input Anda akan meluap inputWrapper karena masih memiliki lebar: 100% dengan bantalan internal.
SpliFF
1

Coba ini:

form { padding-right: 12px; overflow: visible; }
input { display: block; width: 100%; }
Mike
sumber
1
Anda meninggalkan padding input dan batas. Aku akan mengatakan kamu salah sampai aku menyadari apa yang kamu lakukan. Sekarang saya mendapatkan apa yang coba dilakukan oleh merkuro (kodenya masih salah, tetapi konsepnya hampir ada). Padding-right mengubah arti 100% sebesar 12px (batas plus bantalan input). Namun kelemahan dari pendekatan ini adalah bahwa semua anak-anak lain dari bentuk dipengaruhi oleh padding juga dan perlu memberikan kompensasi juga.
SpliFF
1

Anda juga bisa memalsukannya, seperti ini:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>width:auto</title>

        <style>

            .container {
                width:90%;
            }

            .container div{
                border: 1px solid red;
                padding: 5px;
                font-size:12px;
                width:100%;
            }

            input{
                  width:100%;
                border: 1px solid red;
                font-size:12px;
                padding: 5px;
            }

            form {

                margin:0px;
                padding:0px;
            }

        </style>
    </head>

    <body>
        <div class="container">
            <div>
                asdasd
            </div>
            <form action="">
                <input type="text" name="foo" />
            </form>
        </div>
    </body>
</html>
AlexC
sumber
1
masalah yang sama seperti di atas, Anda memiliki bantalan internal pada lebar 100%. Itu akan meluap.
SpliFF
Anda dapat melakukan ini dengan javascript
AlexC
1

Tambahkan ini ke gaya Anda:

box-sizing: border-box;
John Porter
sumber