Как я могу сделать TextArea шириной 100% без переполнения, когда в CSS присутствует отступ?

426

У меня есть следующий CSS и HTML-фрагмент.

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>

Проблема в том, что текстовая область оказывается на 8px шире (2px для границы + 6px для отступа), чем родительская. Есть ли способ продолжать использовать границы и отступы, но ограничить общий размер textareaшириной родительского элемента?

Эрик Шуновер
источник
Кстати, для этого есть хорошая статья Джеффри Вея о tutsplus: net.tutsplus.com/tutorials/html-css-techniques/… Может, это кому-нибудь поможет;)
Кто-то

Ответы:

664

Почему бы не забыть хаки и просто сделать это с помощью CSS?

Один я часто использую:

.boxsizingBorder {
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
}

Смотрите поддержку браузера здесь .

Пит Биджл
источник
22
Я не могу поверить, что это сработало. Но это так. CSS никогда не бывает таким простым. :-)
Нейт Берд
1
Это должно быть одна из самых крутых вещей, которые я нашел за последнее время. Спасибо, есть ли шанс сделать это в IE7?
Джереми А. Вест
47
Обратите внимание, что вы все равно захотите использовать width: 100% в сочетании с рамкой границы.
Тайлер
3
Разве старые версии Internet Explorer не используют только поведение границ?
Питер Хедберг
3
Может кто-нибудь объяснить это, пожалуйста, где этот класс идет? Див, окружающий текстовую область?
koolaang
81

Ответ на многие проблемы форматирования CSS, кажется, «добавить еще один <div>!»

Итак, в этом духе, вы пытались добавить div-обертку, к которой применяются границы и отступы, а затем поместить текстовую область шириной 100% внутри этого? Что-то вроде (не проверено):

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>

Дейв Шерохман
источник
1
Я закончил тем, что отошел от использования% widths. Я считаю, что ваш подход будет работать так же хорошо, хотя. Спасибо!
Эрик Шуновер
5
Не забудьте добавить "." к классу textwrapper.
Крис Портер
3
@ Крис: Спасибо и исправил. Я слегка удивлен, что кому-то понадобилось почти полтора года, чтобы поймать это ...
Дейв Шерохман
2
Как будут выглядеть полосы прокрутки текстовой области в этом случае?
Даниэль ЛеЧеминант
1
В chrome, когда вы фокусируете элемент textarea, он автоматически подсвечивается, и если вы создаете заполнение для div-оболочки, это заполнение будет видно, и из-за этого будут видны две границы. Один от подсветки, а другой от границы .textwrapper: 1px solid # 999999;
Некто
22

давайте рассмотрим окончательный результат, представленный пользователю того, чего мы хотим достичь: текстовая область с отступами и с рамкой, и с отступом, характеристики которых заключаются в том, что при нажатии они передают фокус нашей текстовой области, и преимущество автоматической ширины 100% типично для блочных элементов.

На мой взгляд, наилучшим подходом является использование решений низкого уровня, насколько это возможно, для достижения максимальной поддержки браузеров. В этом случае единственный HTML может работать нормально, избегая использования Javascript (который так или иначе мы все любим).

Тег LABEL приходит в нашу помощь, потому что он имеет такое поведение и может содержать элементы ввода, к которым он должен обращаться. Его стиль по умолчанию - стиль встроенных элементов, поэтому, придав метке блочный стиль отображения, мы можем использовать автоматическую 100% ширину, включая отступы и границы, в то время как внутренняя текстовая область не имеет рамок, нет отступов и ширины 100%. ,

Взглянув на особенности W3C, мы можем заметить и другие преимущества:

  • атрибут «for» не требуется: когда тег LABEL содержит целевой ввод, он автоматически фокусирует дочерний ввод при нажатии;
  • если внешняя метка для текстовой области уже разработана, конфликты не возникают, поскольку для заданного ввода может быть одна или несколько меток.

См. Особенности W3C для более подробной информации.

Простой пример:

.container { 
  width: 400px; 
  border: 3px 
  solid #f7c; 
  }
.textareaContainer {
	display: block;
	border: 3px solid #38c;
	padding: 10px;
  }
textarea { 
  width: 100%; 
  margin: 0; 
  padding: 0; 
  border-width: 0; 
  }
<body>
<div class="container">
	I am the container
	<label class="textareaContainer">
		<textarea name="text">I am the padded textarea with a styled border...</textarea>
	</label>
</div>
</body>

Заполнение и граница элементов .textareaContainer - это те, которые мы хотим дать текстовой области. Попробуйте отредактировать их так, чтобы они соответствовали вашему стилю. Я дал большие и видимые отступы и границы для элемента .textareaContainer, чтобы вы могли видеть их поведение при нажатии.

Эмануэле Дель Гранде
источник
Не уверен, что кросс-браузер попал сюда, но мне понравился подход. +1
HRJ
15

Если вы не слишком беспокоитесь о ширине заполнения, это решение на самом деле также сохранит заполнение в процентах.

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

Не идеально, но вы получите некоторые отступы, а ширина увеличивается до 100%, так что все хорошо

Квай
источник
12

Я наткнулся на другое решение здесь , что это так просто: добавить отступ-право контейнера TEXTAREA в. Это сохраняет поля, границы и отступы для текстовой области, что позволяет избежать проблемы, на которую Бек указал в отношении выделения фокуса, которое хром и сафари помещают вокруг текстовой области.

Право отступа контейнера должно быть суммой эффективного поля, границы и отступа по обеим сторонам текстовой области, а также любого отступа, который вы можете использовать для контейнера. Итак, для случая в оригинальном вопросе:

textarea{
    border:1px solid #999999;
    width:100%;
    margin:5px 0;
    padding:3px;
}
.textareacontainer{
    padding-right: 8px; /* 1 + 3 + 3 + 1 */
}

<div class="textareacontainer">
    <textarea></textarea>
</div>
Брайан
источник
1
+1 Это будет работать в большем количестве браузеров, чем операторы CSS3. Печальная истина заключается в том, что миру все еще нужны упаковщики.
BenSwayne
Мне очень нравится этот ответ. Это делает текстовое поле привязанным без каких-либо магических процентов менее 100%. Вы можете использовать отступы со всех сторон в оболочке, чтобы заставить текстовую область перемещаться и оставаться внутри родительского элемента. Минимальная высота и высота также должны быть 100% на обертке. Затем текстовое поле может быть установлено на 100% с тем же заполнением, чтобы все идеально подходило.
justdan23
9

Этот код работает для меня с IE8 и Firefox

<td>
    <textarea style="width:100%" rows=3 name="abc">Modify width:% accordingly</textarea>
</td>
Джефф Гест
источник
Работал в Chrome тоже.
Санджив
5

Вы можете использовать свойство box-sizing, оно поддерживается всеми основными стандартными браузерами и IE8 +. Вам все еще потребуется обходной путь для IE7, хотя. Узнайте больше здесь .

jzfgo
источник
@DavidJohnstone: И так как вы больше не разрабатываете сайты для IE7 или старше, это
РЕШЕНИЕ
2

Нет, вы не можете сделать это с помощью CSS. По этой причине Microsoft изначально представила другую, и, возможно, более практичную блочную модель . Модель коробки, которая в конечном счете победила, делает непрактичным смешивать проценты и единицы.

Я не думаю, что с вами нормально выражать отступы и ширину границы в процентах от родителя.

Бути-окса
источник
2

Я искал решение для inline-стилей вместо CSS, и это лучшее, что я могу сделать для адаптивного текстового пространства:

<div style="width: 100%; max-width: 500px;">
  <textarea style="width: 100%;"></textarea>
</div>
Джи Мок
источник
1

Если вы добавите и сместите его так:

textarea
{
    border:1px solid #999999;
    width:100%;
    padding: 7px 0 7px 7px; 
    position:relative; left:-8px; /* 1px border, too */
}

правая сторона текстовой области идеально совпадает с правой стороной контейнера, а текст внутри текстовой области идеально совпадает с основным текстом в контейнере ... и левая сторона текстовой области немного выпирает. это иногда красивее.

commonpike
источник
1

Для тех, кто использует Bootstrap, textarea.form-control также может привести к проблемам с размерами textarea. Похоже, что Chrome и Firefox используют разные высоты с помощью следующего загрузочного CSS:

textarea.form-conrtol{
    height:auto;
}
Gwi7d31
источник
1

Я часто решаю эту проблему с calc(). Вы просто даете текстовой области ширину 100% и определенное количество отступов, но вы должны вычесть общее левое и правое заполнение из 100% ширины, которую вы дали текстовой области:

textarea {
    border: 0px;
    width: calc(100% -10px);
    padding: 5px; 
}

Или, если вы хотите дать текстовой области границу:

textarea {
    border: 1px;
    width: calc(100% -12px); /* plus the total left and right border */
    padding: 5px; 
}
Йерун Беллеманс
источник
0

Как насчет отрицательных полей?

textarea {
    border:1px solid #999999;
    width:100%;
    margin:5px -4px; /* 4px = border+padding on one side */
    padding:3px;
}
meustrus
источник
0

* {
    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>

antelove
источник