The problem
When styling text <input> elements, it’s fairly common to run into a serious problem: they don’t behave like block-level elements.
Note: In all of the examples, the container element is filled with blue, and the <input> itself is filled with red and has an opacity of 50% so that you can see it under- or over-flowing the container.
<div style="background: blue; width:200px;"> <input style="display:block; padding:4px; background: red; opacity:0.5; border:0;" type="text" value="text input"/> </div>
You can see how the input doesn’t automatically flow to full width, as the “display: block” style suggests it should. The kneejerk response is to set the width to 100%:
<div style="background: blue; width:200px;"> <input style="display:block; padding:4px; background: red; opacity:0.5; width:100%; border:0;" type="text" value="text input"/> </div>
But notice now how the input overflows its container’s boundaries because of the left padding. At this point, people may resort to non-semantic markup (removing the padding on the <input> and putting it inside a padded <div>) or JavaScript solutions that set the pixel width whenever the container’s width changes (by the addition of scrollbars, for example).
The (semantic) solution
But wait! There is a way to achieve this effect without resorting to an extra <div> or JavaScript:
<div style="background: blue; width:200px;"> <input style="display:block; padding:4px 0; background: red; opacity:0.5; width:100%; border:0; text-indent:4px;" type="text" value="text input"/> </div>
Do you see what I did there? I removed the horizontal padding on the <input>, so the 100% width now works correctly, and replaced it with “text-indent”. To the user, this looks no different, and it has the advantage of requiring no extraneous markup or tedious scripting.
Drawbacks
- Should the user enter a long string, their text will bump up against the right edge. But I think that that’s a boundary condition that I can live with.
- Any vertical borders on the <input> will cause it to overflow its container. Personally, if I want a full-width <input>, though, I generally don’t want any borders on its left or right other than those of its container.