具有100% 溢出表单元格宽度的 HTML 输入文本框

有人知道为什么宽度为100% 的输入元素会越过表格的单元格边界吗。

在下面这个简单的例子中,输入框越过了表格的单元格边框,结果非常糟糕。我们在火狐、 IE7和 Safari 上测试过,结果都是一样的。

这对你有意义吗? 我是不是漏掉了什么,你知道有什么可能的解决办法吗?

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <!-- don't use closing slash in meta tag, it breaks HTML4.01 transitional -->
<title>Test input text in table</title>
<style type="text/css">
table {border-top: 1px solid #ff0000; border-left: 1px solid #ff0000;}
table td {border-right: 1px solid #00ff00; border-bottom: 1px solid #00ff00;}
input[type="text"] {width: 100%;} /* removing this would make input not to go over cells border, but they would be too short, I want them to fit cells size */
</style>
</head><body>


<table cellpadding="0" cellspacing="0">
<tr>
<td><p>column one hello babe babe babe</p></td>
<td><p>column two hello babe more</p></td>
<td><p>column three hello babe more and more</p></td>
</tr>
<tr>
<td><input type="text" value="test"></td>
<td><input type="text" value="test"></td>
<td><input type="text" value="test"></td>
</tr>
</table>


</body></html>
217112 次浏览

Width value doesn't take into account border or padding:

http://www.htmldog.com/reference/cssproperties/width/

You get 2px of padding in each side, plus 1px of border in each side.
100% + 2*(2px +1px) = 100% + 6px, which is more than the 100% child-content the parent td has.

You have the option of:

  • Either setting box-sizing: border-box; as per @pricco's answer;
  • Or using 0 margin and padding (avoiding the extra size).

The problem lies in border-width of input element. Shortly, try setting the margin-left of the input element to -2px.

table input {
margin-left: -2px;
}

The problem has been explained previously so I will only reiterate: width doesn't take into account border and padding. One possible answer to this not discussed but which I have found helped me out a bunch is to wrap your inputs. Here's the code, and I'll explain how this helps in a second:

<table>
<tr>
<td><div style="overflow:hidden"><input style="width:100%" type="text" name="name" value="hello world" /></div></td>
</tr>
</table>

The DIV wrapping the INPUT has no padding nor does it have a border. This is the solution. A DIV will expand to its container's size, but it will also respect border and padding. Now, the INPUT will have no issue expanding to the size of its container since it is border-less and pad-less. Also note that the DIV has its overflow set to hidden. It seems that by default items can fall outside of their container with the default overflow of visible. This just ensures that the input stays inside its container and doesn't attempt to poke through.

I've tested this in Chrome and in Fire Fox. Both seem to respect this solution well.

UPDATE: Since I just got a random downvote, I would like to say that a better way to deal with overflow is with the CSS3 box-sizing attribute as described by pricco:

.myinput {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}

This seems to be pretty well supported by the major browsers and isn't "hacky" like the overflow trick. There are, however, some minor issues on current browsers with this approach (see http://caniuse.com/#search=box-sizing Known Issues).

I usually set the width of my inputs to 99% to fix this:

input {
width: 99%;
}

You can also remove the default styles, but that will make it less obvious that it is a text box. However, I will show the code for that anyway:

input {
width: 100%;
border-width: 0;
margin: 0;
padding: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}

Ad@m

The problem with things like width:95%; is that they don't look right in wide flexible layouts (because 5% can then be like 30 pixels).

The following solutions works very well for me (tested in Firefox, IE 9, Safari):

<table style="background-color: blue; width: 100%;" cellpadding="0" cellspacing="0">
<tr>
<td style="background-color: red;   padding: 3px;">
<div style="margin-right: 3px;">
<div style="padding-right: 3px;">
<input type="text" style="width:100%;">
</div>
</div>
</td>
<td style="background-color: purple;   padding: 3px;">
<div style="margin-right: 3px;">
<div style="padding-right: 3px;">
<input type="text" style="width:100%;">
</div>
</div>
</td>
<td style="background-color: green;   padding: 3px;">
<div style="margin-right: 3px;">
<div style="padding-right: 3px;">
<input type="text" style="width:100%;">
</div>
</div>
</td>
</tr>
</table>

(added the colors to make it easier to notice the correct padding)

The trick is to wrap the input with two divs, the outer has a 3px margin (which makes it 3px smaller than the td), the inner has a 3px padding. This makes the input 6px smaller than the td, which is what you wanted to begin with.

I am not sure about the mechanics of this, but it works.

In this simple example, it also works with just a single div with right margin 6. However, in the case of my web application, only the above solution works.

<table style="background-color: blue; width: 100%;" cellpadding="0" cellspacing="0">
<tr>
<td style="background-color: red;   padding: 3px;">
<div style="margin-right: 6px;">
<input type="text" style="width:100%;">
</div>
</td>
<td style="background-color: purple;   padding: 3px;">
<div style="margin-right: 6px;">
<input type="text" style="width:100%;">
</div>
</td>
<td style="background-color: green;   padding: 3px;">
<div style="margin-right: 6px;">
<input type="text" style="width:100%;">
</div>
</td>
</tr>
</table>

Take out the "http://www.w3.org/TR/html4/loose.dtd" from the DOCTYPE declaration and it fix your problem.

Cheers! :)

The problem is due to the input element box model. I just recently found a nice solution to the issue when trying to keep my input at 100% for mobile devices.

Wrap your input with another element, a div for example. Then apply the styling you want for your input to that the wrapper div. For example:

<div class="input-wrapper">
<input type="text" />
</div>


.input-wrapper {
border-raius:5px;
padding:10px;
}
.input-wrapper input[type=text] {
width:100%;
font-size:16px;
}

Give .input-wrapper rounded corner padding etc, whatever you want for your input, then give the input width 100%. You have your input padded nicely with a border etc but without the annoying overflow!

You could use the CSS3 box-sizing property to include the external padding and border:

input[type="text"] {
width: 100%;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
}

I fixed this issue starting with @hallodom's answer. All my inputs were contained within li's, so all I had to do was set the li overflow:hidden for it to remove that excess input overflow.

.ie7 form li {
width:100%;
overflow:hidden;
}


.ie7 input {
width:100%;
}

With some Javascript you can get the exact width of the containing TD and then assign that directly to the input element.

The following is raw javascript but jQuery would make it cleaner...

var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++)
{
var el = inputs[i];
if (el.style.width == '100%')
{
var pEl = el.parentNode;  // Assumes the parent node is the TD...
el.style.width = pEl.offsetWidth;
}
}

The issues with this solution are:

1) If you have your inputs contained in another element such as a SPAN then you will need loop up and find the TD because elements like SPANs will wrap the input and show its size rather then being limited to the size of the TD.

2) If you have padding or margins added at different levels then you might have to explicitly subtract that from [pEl.offsetWidth]. Depending on your HTML structure that can be calculated.

3) If the table columns are sized dynamically then changing the size of one element will cause the table to reflow in some browsers and you might get a stepped effect as you sequentially "fix" the input sizes. The solution is to assign specific widths to the column either as percentages or pixels OR collect the new widths and set them after. See the code below..

var inputs = document.getElementsByTagName('input');
var newSizes = [];
for (var i = 0; i < inputs.length; i++)
{
var el = inputs[i];
if (el.style.width == '100%')
{
var pEl = el.parentNode;  // Assumes the parent node is the TD...
newSizes.push( { el: el, width: pEl.offsetWidth });
}
}


// Set the sizes AFTER to avoid stepping...
for (var i = 0; i < newSizes.length; i++)
{
newSizes[i].el.style.width = newSizes[i].width;
}

I know that this question is 3 years old but the problem still persists for current browsers and folks are still coming here. The solution for now is calc():

input {
width: calc(100% - 12px); /* IE 9,10 , Chrome, Firefox */
width: -webkit-calc(100% - 12px); /*For safari 6.0*/
}

It is supported by most modern browsers.

I solved the problem by applying box-sizing:border-box; to the table cells themselves, besides doing the same with the input and the wrapper.

instead of this margin struggle just do

input{
width:100%;
background:transparent !important;
}

this way the cell border is visible and you can control row background color

I solved the problem by using this

tr td input[type=text] {
width: 100%;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
background:transparent !important;
border: 0px;
}