Input with display:block is not a block, why not?
HtmlCssHtml Problem Overview
Why does display:block;width:auto;
on my text input not behave like a div and fill the container width?
I was under the impression that a div is simply a block element with auto width. In the following code shouldn't the div and the input have identical dimensions?
How do I get the input to fill the width? 100% width won't work, because the input has padding and a border (causing a final width of 1 pixel + 5 pixels + 100% + 5 pixels + 1 pixels). Fixed widths aren't an option, and I'm looking for something more flexible.
I'd prefer a direct answer to a workaround. This seems like a CSS quirk and understanding it may be useful later.
<!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>
I should point out I can already do this with wrapper workarounds. Apart from this screwing with the page semantics and CSS selector relationships I'm trying to understand the nature of the problem and whether it can be overcome by changing the nature of the INPUT itself.
Ok, this is TRULY strange! I've found that the solution is to simply add max-width:100%
to an input with width:100%;padding:5px;
. However this raises even more questions (which I'll ask in a separate question), but it seems that width uses the normal CSS box model and max-width uses the Internet Explorer border-box model. How very odd.
Ok, that last one appears to be a bug in Firefox 3. Internet Explorer 8 and Safari 4 limit the max-width to 100% + padding + border which is what the spec says to do. Finally, Internet Explorer got something right.
Oh my god, this is awesome! In the process of playing with this, and with much help from the venerable gurus Dean Edwards and Erik Arvidsson, I managed to piece together three separate solutions to make a true cross-browser 100% width on elements with arbitrary padding and borders. See answer below. This solution does not require any extra HTML markup, just a class (or selector) and an optional behaviour for legacy Internet Explorer.
Html Solutions
Solution 1 - Html
Check out what I came up with, a solution using the relatively unknown box-sizing:border-box
style from CSS 3. This allows a 'true' 100% width on any element regardless of that elements' padding and/or borders.
<!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>
This solution supports Internet Explorer 6 and Internet Explorer 7 via a behaviour written by Erik Arvidsson with some tweaks from Dean Edwards to support percentage and other non-pixel widths.
Solution 2 - Html
The reason this happens is that a text input's size is determined by its size attribute. add size="50" inside the <input> tag. Then change it to size="100" -- see what I mean?
I suspect there's a better solution, but the only one that comes to mind is something I found on the "Hidden features of HTML" question on SO: Use a content-editable div, instead of an input. Passing the user input to the enclosing form (if that's what you need to) might be a little tricky.
https://stackoverflow.com/questions/954327/hidden-features-of-html/954904#954904
Solution 3 - Html
Your best bet is to wrap the input in a div with your border, margins, etc., and have the input inside with width 100% and no border, no margins, etc.
For example,
<!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>
Solution 4 - Html
Add this to your style:
box-sizing: border-box;
Solution 5 - Html
You could fake it, like this:
<!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>
Solution 6 - Html
Also you could fake it, like this:
<!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>
Solution 7 - Html
Try this:
form { padding-right: 12px; overflow: visible; }
input { display: block; width: 100%; }