Как стилизовать и выровнять формы без таблиц?

Я привык использовать <table>s для идеального выравнивания полей формы. Вот как я обычно пишу свои формы:

<table border="0">
   <tr>
     <td><label for="f_name">First name:</label></td>
     <td><input type='text' id='f_name' name='f_name' /></td>
     <td class='error'><?=form_error('f_name');?></td>
   </tr>
</table>

Я знаю , что это плохая практика, и я хочу использовать CSS, <label>s, <div>s или метод фильтра. Однако на самом деле они <table>s очень хорошо работают с формами. Все ровно ровно, интервал идеальный, все погрешности ровно друг под другом и т. Д.

Недавно я попытался с помощью <dt> и <dd> теги для формы, но я в конечном итоге возвращаясь обратно к таблицам только потому , что они выглядели намного лучше.

Как я могу получить такой выровненный макет таблицы без использования <table> s?

Ответов (11)

Решение

Это может не получить большой поддержки, но вот мои два цента:

В некоторых ситуациях таблицы проще разметить; например, три столбца или формы (хотя здесь есть несколько отличных предложений по созданию макета чистой формы css, поэтому не игнорируйте и их.)

Из процессов и методологий можно сделать хороших слуг, но они плохие хозяева.
   - Марк Дауд, Джон Макдональд и Джастин Шу 
     в "Искусство оценки безопасности программного обеспечения"

Я считаю, что эта цитата очень сильно применима к данной ситуации. Если ваш макет таблицы работает на вас, не вызывает проблем с доступностью и не нарушен - не исправляйте это.

Такие фразы, как: «ты должен», «должен», «всегда» - пугают меня, потому что один размер не подходит всем! Относитесь к фанатикам с недоверием.

Если вы не пользуетесь таблицами, вам необходимо заранее знать ширину ваших этикеток. Это часто может быть проблемой для многоязычных сайтов (i18n).

В таблицах они растягиваются, чтобы соответствовать этикеткам разных размеров. Один только CSS пока не может сделать это хорошо поддерживаемым способом.

У меня тоже была эта проблема, но с кокидилом у меня было меню слева (также с float: left в нем).

Так. Мое решение было: html

<div class="new">
   <form>
     <label class="newlabel">Name</label>
     <input type="text" name="myTextBox" id="myTextBox" />
   </form>
</div>

css

.new {
    display:block;
}
.newlabel {
    min-width: 200px;
    float: left;
}

Я думаю, это сработало бы и в классе форм, но на самом деле у меня было больше форм в «новом» классе.

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

Но в CSS есть display: table по этой причине:

HTML

<div class="form-fields">
  <div class="form-field">
    <label class="form-field-label" for="firstNameInput">First Name</label>
    <div class="form-field-control"><input type="text" id="firstNameInput"></div>
    <div class="form-field-comment">Required</div>
  </div>
  <div class="form-field">
    <label class="form-field-label" for="lastNameInput">Last Name</label>
    <div class="form-field-control"><input type="text" id="lastNameInput"></div>
    <div class="form-field-comment">Required</div>
  </div>
</div>

CSS

.form-fields {
  display: table;
}

.form-field {
  display: table-row;
}

.form-field-label,
.form-field-control,
.form-field-comment {
  display: table-cell;
  padding: 3px 10px;
}

Простой.

Для этого не существует универсального решения. Тем не менее, пример таблицы, который вы использовали, можно улучшить:

<table>
  <tbody>
    <tr>
      <th scope="row"><label for="f_name">First name:</label></th>
      <td>
        <input type='text' id='f_name' name='f_name' />
        <?php form_error('f_name'); ?>
      </td>
    </tr>
    <!-- ... -->
  </tbody>
</table>

Не слишком уверен в части ошибки; Я думаю, что имеет больше смысла помещать его рядом с вводом, чем иметь для него отдельный столбец.

Почему вы не хотите использовать таблицы? Похоже, они теперь отлично работают на вас. Вас беспокоят проблемы с доступностью? То, что это таблица, не означает, что пострадает доступность.

Я хочу предостеречь вас от создания нового решения решенной проблемы только ради чистоты. Даже если вас беспокоит семантика, какая семантика все равно описывает форму?

Да, используйте метки и CSS:

<label class='FBLabel' for="FName">First Name</label>
<input value="something" name="FName" type="text" class='FBInput'>
<br>

css:

.FBLabel, .FBInput {
    display:block;
    width:150px;
    float:left;
    margin-bottom:10px;
}

См .: http://www.alistapart.com/articles/prettyaccessibleforms

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

Я довольно эффективно использовал это в прошлом:

HTML:

<fieldset>
  <p>
    <label for="myTextBox">Name</label>
    <span class="field"><input type="text" name="myTextBox" id="myTextBox" /></span>
    <span class="error">This a message place</span>
  </p>
</fieldset>

CSS:

<style type="text/css">
fieldset label, fieldset .field, fieldset .error { display: -moz-inline-box; display: inline-block; zoom: 1; vertical-align: top; }
fieldset p { margin: .5em 0; }
fieldset label { width: 10em;  text-align: right; line-height: 1.1; }
fieldset .field { width: 20em; }
</style>

Единственная проблема - это Firefox 2, который постепенно ухудшается. (см. -moz-inline-box, что немного взломано, но не так уж плохо)

Я использую следующий метод большую часть времени, и он позволяет мне настроить все мое выравнивание именно так, как мне нравится. Как видите, он дает мне множество ловушек для CSS и JS.

<form id="login-form" action="#" method="post">
 <fieldset>
  <label id="for-email" for="email">
   <span class="label-title">Email Address <em class="required">*</em></span>
   <input id="email" name="email" type="text" class="text-input" />
  </label>
  
  <label id="for-password" for="password">
   <span class="label-title">Password <em class="required">*</em></span>
   <input id="password" name="password" type="password" class="text-input" />
  </label>
 </fieldset>
 
 <ul class="form-buttons">
  <li><input type="submit" value="Log In" /></li>
 </ul>
</form><!-- /#login-form -->

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

Я также задокументировал метод, на котором остановился на прошлой неделе (фрагмент):

<form action="/signup" method="post">
<fieldset>
<legend>Basic Information</legend>
<ol>
<li><label for="name">Name <span class="error">*</span>
    </label><input type="text" id="name" name="name" size="30" /></li>
<li><label for="dob">Date of Birth <span class="error">*</span></label>
    <div class="inputWrapper">
    <input type="text" id="dob" name="dob" size="10" />
    <span class="note">YYYY-MM-DD</span></div></li>
<li><label for="gender">Gender <span class="error">*</span></label>
    <select id="gender" name="gender">
    <option value=""></option>
    <option value="female">Female</option>
    <option value="male">Male</option>
    </select></li>
</ol>
</fieldset>
</form>

И CSS:

fieldset { 
    margin: 0 0 20px 0; } 

fieldset legend { 
    font-weight: bold; 
    font-size: 16px; 
    padding: 0 0 10px 0; 
    color: #214062; } 

fieldset label { 
    width: 170px; 
    float: left; 
    margin-right:10px; 
    vertical-align: top; } 

fieldset ol { 
    list-style:none; 
    margin: 0;
    padding: 0;} 

fieldset ol li { 
    float:left; 
    width:100%; 
    padding-bottom:7px; 
    padding-left: 0; 
    margin-left: 0; } 

fieldset ol li input, 
fieldset ol li select, 
fieldset ol li textarea { 
    margin-bottom: 5px; } 

form fieldset div.inputWrapper { 
    margin-left: 180px; } 

.note { 
    font-size: 0.9em; color: #666; }

.error{ 
    color: #d00; }

jsFiddle