How can I make a TextArea 100% width without overflowing when padding is present in CSS?

Viewed 489993

I have the following CSS and HTML snippet being rendered.

textarea
{
  border:1px solid #999999;
  width:100%;
  margin:5px 0;
  padding:3px;
}
<div style="display: block;" id="rulesformitem" class="formitem">
  <label for="rules" id="ruleslabel">Rules:</label>
  <textarea cols="2" rows="10" id="rules"/>
</div>

Is the problem is that the text area ends up being 8px wider (2px for border + 6px for padding) than the parent. Is there a way to continue to use border and padding but constrain the total size of the textarea to the width of the parent?

17 Answers

The answer to many CSS formatting problems seems to be "add another <div>!"

So, in that spirit, have you tried adding a wrapper div to which the border/padding are applied and then putting the 100% width textarea inside of that? Something like (untested):

textarea
{
  width:100%;
}
.textwrapper
{
  border:1px solid #999999;
  margin:5px 0;
  padding:3px;
}
<div style="display: block;" id="rulesformitem" class="formitem">
  <label for="rules" id="ruleslabel">Rules:</label>
  <div class="textwrapper"><textarea cols="2" rows="10" id="rules"/></div>
</div>

If you're not too bothered about the width of the padding, this solution will actually keep the padding in percentages too..

textarea
{
    border:1px solid #999999;
    width:98%;
    margin:5px 0;
    padding:1%;
}

Not perfect, but you'll get some padding and the width adds up to 100% so its all good

This code works for me with IE8 and Firefox

<td>
    <textarea style="width:100%" rows=3 name="abc">Modify width:% accordingly</textarea>
</td>

I was looking for an inline-styling solution instead of CSS solution, and this is the best I can go for a responsive textarea:

<div style="width: 100%; max-width: 500px;">
  <textarea style="width: 100%;"></textarea>
</div>

The problem lies in the box-sizing property. By default, the initial value of the box-sizing property is content-box. so you have something like this under the hood:

textarea {
  border:1px solid #999999;
  width:100%;
  margin:5px 0;
  padding:3px;
  box-sizing: content-box;
}

box-sizing: content-box; means that the width of the actual element is equal to the width of the element's content box. so when you add padding (in this case padding-right and padding-left --> because we are talking about width) and border (in this case border-right and border-left --> because we are talking about width), these values get added to the final width. so your element will be wider than you want.

set it to box-sizing: border-box;. so the width will be calculated like so:

horizontal border + horizontal padding + width of content box = width

in this case, when you add horizontal border and horizontal padding, the final width of element does not change, in fact, the content box will shrink to satisfy the equation.

No, you cannot do that with CSS. That is the reason Microsoft initially introduced another, and maybe more practical box model. The box model that eventually won, makes it inpractical to mix percentages and units.

I don't think it is OK with you to express padding and border widths in percentage of the parent too.

* {
    box-sizing: border-box;
}

.container {
    border-radius: 5px;
    background-color: #f2f2f2;
    padding: 20px;
}

/* Clear floats after the columns */
.row:after {
    content: "";
    display: table;
    clear: both;
}

input[type=text], select, textarea{
    width: 100%;
    padding: 12px;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
    resize: vertical;
}
<div class="container">
  <div class="row">
    <label for="name">Name</label>
    <input type="text" id="name" name="name" placeholder="Your name..">
  </div>
  <div class="row">
    <label for="country">Country</label>
    <select id="country" name="country">
      <option value="australia">UK</option>
      <option value="canada">USA</option>
      <option value="usa">RU</option>
    </select>
  </div>    
  <div class="row">
    <label for="subject">Subject</label>
    <textarea id="subject" name="subject" placeholder="Write something.." style="height:200px"></textarea>
  </div>
</div>

Below is a more complete CSS design. As already mentioned, the new box-sizing:border-box; setting pushes the border and padding into the width calculation so when you use min-width:100% everything fits inside the parent container and expands.

<style type="text/css">
    body textarea,
    body textarea:visited,
    body textarea:hover,
    body textarea:focus,
    body textarea:active {
    display: block;
    width: auto;
    height: auto;
    min-width: 100%;
    min-height: 10em;
    padding: 1em;
    margin: 0;
    -webkit-appearance: textarea;
    -moz-appearance: textfield-multiline;
    cursor: text;
    overflow: auto;
    resize: both;
    background-color: #eee;
    word-wrap: normal;
    border: 2px solid #bbb;
    border-radius: .2em;
    font-family:inherit;
    line-height: normal;
}

div {
    border:2px solid blue;
}

textarea,div {
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
}
</style>

<div>
    <textarea>Some test text...</textarea>
</div>

The div parent has a blue border and contains the child textarea in grey.

enter image description here

Related