it-swarm.com.ru

Можете ли вы сделать этот макет HTML без использования таблиц?

Хорошо, у меня была простая проблема макета неделю или две назад. А именно разделам страницы нужен заголовок:

+---------------------------------------------------------+
| Title                                            Button |
+---------------------------------------------------------+

Довольно простые вещи. Дело в том, что ненависть к таблицам, похоже, перешла в мир Интернета, о чем мне напомнили, когда я спросил Зачем использовать теги списков определений (DL, DD, DT) для форм HTML вместо таблиц? Теперь общая тема таблиц против divs/CSS ранее обсуждалась, например:

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

  • Плавающее право для кнопки или div, содержащего кнопку;
  • Относительное положение для кнопки; а также
  • Положение относительное + абсолютное.

Ни одно из этих решений не было удовлетворительным по разным причинам. Например, относительное позиционирование привело к проблеме z-index, когда мое содержимое появилось под содержимым.

Итак, я вернулся к:

<style type="text/css">
.group-header { background-color: yellow; width: 100%; }
.group-header td { padding: 8px; }
.group-title { text-align: left; font-weight: bold; }
.group-buttons { text-align: right; }
</style>
<table class="group-header">
<tr>
  <td class="group-title">Title</td>
  <td class="group-buttons"><input type="button" name="Button"></td>
</tr>
</table>

И это работает отлично. Это просто, с обратной совместимостью (это будет работать, вероятно, даже на IE5), и это просто работает. Не возиться с позиционированием или поплавками.

Так может кто-нибудь сделать эквивалент без таблиц?

Требования следующие:

  • Обратная совместимость: с FF2 и IE6;
  • Разумно согласовано: в разных браузерах;
  • Вертикально по центру: кнопка и заголовок имеют разную высоту; а также
  • Гибкий: позволяет достаточно точно контролировать позиционирование (отступы и/или поля) и стиль.

Кстати, сегодня я наткнулся на пару интересных статей:

РЕДАКТИРОВАТЬ: Позвольте мне подробнее остановиться на проблеме с плавающей точкой. Этот вид работ:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { float: left; padding: 8px; }
      .group-buttons { float: right; padding: 8px; }
    </style>
  </head>
  <body>
    <div class="group-header">
      <div class="group-title">This is my title</div>
      <div class="group-buttons"><input type="button" value="Collapse"></div>
    </div>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

Спасибо Ant P за часть overflow: hidden (хотя до сих пор не понимаю, почему). Вот в чем проблема. Скажем, я хочу, чтобы заголовок и кнопка располагались вертикально по центру. Это проблематично, потому что элементы имеют разную высоту. Сравните это с:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-header td { vertical-align: middle; }
      .group-title { padding: 8px; }
      .group-buttons { text-align: right; }
    </style>
  </head>
  <body>
    <table class="group-header">
    <tr>
      <td class="group-title">This is my title</td>
      <td class="group-buttons"><input type="button" value="Collapse"></td>
    </tr>
    </table>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

который работает отлично.

99
cletus

Нет ничего плохого в том, чтобы использовать инструменты, доступные вам, чтобы выполнять работу быстро и правильно.

В этом случае стол работал отлично.

Я лично использовал бы таблицу для этого.

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

49
Gregor Brandt

Просто плавайте влево и вправо и установите, чтобы очистить оба, и все готово. Нет необходимости в таблицах.

Редактировать: Я знаю, что получил много голосов за это, и я считал, что был прав. Но есть случаи, когда вам просто нужно иметь таблицы. Вы можете попробовать сделать все с помощью CSS, и это будет работать в современных браузерах, но если вы хотите поддерживать старые ... Не повторюсь, здесь связанный поток переполнения стека и rant в моем блоге .

Edit2: Поскольку старые браузеры больше не так интересны, я использую Twitter bootstrap для новых проектов. Это отлично подходит для большинства макетов и использует CSS.

27
Milan Babuškov

Это вопрос с подвохом: он выглядит ужасно простым, пока вы не доберетесь до

Скажем, я хочу, чтобы заголовок и кнопка располагались вертикально по центру.

Я хочу заявить для записи, что да, вертикальное центрирование сложно в CSS. Когда люди пишут, и это кажется бесконечным на SO, "можете ли вы сделать X в CSS", ответ почти всегда "да", и их порыв кажется неоправданным. В этом случае, да, эта конкретная вещь сложна.

Кто-то должен просто отредактировать весь вопрос так: "Неужели вертикальное центрирование проблематично в CSS?".

17
AmbroseChapel

Название с плавающей точкой слева, кнопка с плавающей точкой справа и (вот часть, которую я никогда не знал до недавнего времени) - сделайте контейнер из них обоих {overflow:hidden}.

В любом случае, это должно избежать проблемы z-index. Если это не работает, и вам действительно нужна поддержка IE5, продолжайте и используйте таблицу.

16
user42092

В чистом CSS рабочим ответом будет однажды просто использовать "display:table-cell". К сожалению, это не работает в современных браузерах А-класса, так что для всего этого вы могли бы также использовать таблицу, если вы все равно хотите добиться того же результата. По крайней мере, вы будете уверены, что это работает достаточно далеко в прошлое.

Честно говоря, просто используйте таблицу, если это проще. Это не повредит.

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

http://www.w3.org/TR/wai-aria/#presentation

Я думаю, что для этого требуется специальный DTD, выходящий за рамки XHTML 1.1, который бы просто вызвал все споры text/htmls application/xml, поэтому давайте не будем идти туда.

Итак, к вашей нерешенной проблеме CSS ...

Выровнять по вертикали два элемента по их центру: это можно сделать несколькими разными способами, с помощью некоторой тупой хакерской CSS.

Если вы можете вписаться в следующие ограничения, то есть относительно простой способ:

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

Тогда вы можете использовать абсолютное позиционирование с отрицательными полями:

.group-header { height: 50px; position: relative; }
.group-title, .group-buttons { position: absolute; top: 50%; }
# Assuming the height of .group-title is a known 34px
.group-title { left: 0; margin-top: -17px; }
# Assuming the height of .group-buttons is a known 38px
.group-buttons { right: 0; margin-top: -19px; }

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

Вот еще один метод, который использует базовую линию текста для вертикального выравнивания двух столбцов в виде встроенных блоков. Недостатком здесь является то, что вам нужно установить фиксированную ширину для столбцов, чтобы заполнить ширину от левого края. Поскольку нам нужно сохранить элементы привязанными к базовой строке текста, мы не можем просто использовать float: right для второго столбца. (Вместо этого мы должны сделать первый столбец достаточно широким, чтобы переместить его.)

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; }
      .valign { display: inline-block; vertical-align: middle; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { padding: 8px; width: 384px; }
      .group-buttons { padding: 8px; width: 84px; text-align: right; }
    </style>
    <!--[if lt IE 8]>
    <style type="text/css">
      .valign { display: inline; margin-top: -2px; padding-top: 1px; }
    </style>
    <![endif]-->
  </head>
  <body>
    <div class="group-header">
      <div class="valign">
        <div class="group-title">This is my title.</div>
      </div><!-- avoid whitespace between these! --><div class="valign">
        <div class="group-buttons"><input type="button" value="Collapse"></div>
      </div>
    </div>
    <div class="group-content">
      <p>And it works perfectly, but mind the hacks.</p>
    </div>
  </body>
</html>

HTML: Мы добавляем обертки .valign вокруг каждого столбца. (Дайте им более "семантическое" имя, если это сделает вас счастливее.) Они должны храниться без пробелов между ними, иначе текстовые пробелы раздвинут их. (Я знаю, что это отстой, но это то, что вы получаете за то, что вы "чисты" с разметкой и отделяете ее от уровня представления ... Ха!)

CSS: Мы используем vertical-align:middle, чтобы выровнять блоки по текстовой базовой линии элемента заголовка группы. Различные высоты каждого блока останутся по центру и вытолкнут высоту их контейнера. Ширина элементов должна быть рассчитана, чтобы соответствовать ширине. Здесь их 400 и 100 минус их горизонтальное заполнение.

IE исправляет: Internet Explorer отображает встроенный блок только для встроенных элементов (например, span, а не div). Но если мы передадим div hasLayout, а затем отобразим его как встроенный, он будет вести себя как встроенный блок. Корректировка поля должна исправить зазор в 1 пиксель сверху (попробуйте добавить цвета фона в заголовок .group, чтобы увидеть).

7
Andrew Vit

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

<style>
  .group-header { background: yellow; zoom: 1; padding: 8px; }
  .group-header:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  /* set width appropriately to allow room for button */
  .group-header h3 { float: left; width: 300px; }
  /* set line-height or margins to align with h3 baseline or middle */
  .group-header input { float: right; }
</style>

<div class="group-header">
  <h3>This is my title</h3>
  <input type="button" value="Collapse"/>
</div>

Если вы хотите истинное вертикальное выравнивание по центру (т. Е. Если текст оборачивает кнопку по-прежнему по центру относительно обеих строк текста), то вам нужно либо составить таблицу, либо что-то поработать с position: absolute и полями. Вы можете добавить position: relative в ваше раскрывающееся меню (или, скорее, его родителя), чтобы вывести его на тот же уровень упорядочения, что и кнопки, позволяя вам поднять его над ними с помощью z-index, если это произойдет.

Обратите внимание, что вам не нужно width: 100% в div, потому что это элемент уровня блока, и zoom: 1 заставляет div вести себя так, как будто он имеет явное исправление в IE (другие браузеры выбирают фактическое исправление). Вам также не нужны все эти посторонние классы, если вы нацеливаетесь на вещи более конкретно, хотя вам может понадобиться обертка div или span для кнопки, чтобы упростить позиционирование.

3
One Crayon

Сделайте двойной float в div и используйте clearfix. http://www.webtoolkit.info/css-clearfix.html Есть ли у вас какие-либо ограничения на отступы/поля?

<div class="clearfix">
   <div style="float:left">Title</div>
   <input type="button" value="Button" style="float:right" />
</div>
2
bendewey
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>
2
Omer Bokhari

Я решил использовать гибкую коробку, потому что она сделала вещи намного проще.
В основном вам нужно перейти к родителю дочерних элементов, которые вы хотите выровнять, и добавить display: box (с префиксом, конечно). чтобы заставить их сидеть по сторонам, используйте justify-content . пробел между ними является правильным, когда у вас есть элементы, которые должны быть выровнены до конца, как в этом случае (см. ссылку) ...
тогда вопрос выравнивания по вертикали. Поскольку я создал родительский элемент для двух элементов, которые вы хотите выровнять по гибкому блоку, теперь легко использовать align-items: center. Затем я добавил стили, которые вы хотели раньше, удалил float из заголовка и кнопки в заголовке и добавил отступы.

   .group-header, .group-content {
      width: 500px;
      margin: 0 auto;
    }
    .group-header{
      border: 1px solid red;
      background: yellow;
      overflow: hidden;
      display: -webkit-box;
      display: -moz-box;
      display: box;
      display: -webkit-flex;
      display: -moz-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-justify-content: space-between;
      -moz-justify-content: space-between;
      -ms-justify-content: space-between;
      -o-justify-content: space-between;
      justify-content: space-between;
      webkit-align-items: center;
      -moz-align-items: center;
      -ms-align-items: center;
      -o-align-items: center;
      align-items: center;
      padding: 8px 0;
    }
 .group-content{
      border: 1px solid black;
      background: #DDD;
 }
    .group-title {
      padding-left: 8px;
    }
    .group-buttons {
      padding-right: 8px
    }

см. Демонстрацию

1
user3522940

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

<html><head><title>stack header</title>
<style type="text/css">
#stackheader {
 background-color: #666;
 color: #FFF;
 width: 410px;
 height: 50px;
}
#title {
 color: #FFF;
 float: left;
 padding: 15px 0 0 15px; 
}
#button {
 color: #FFF;
 float: right;
 padding: 15px 15px 0 0;
}
</style></head><body>
<div id="stackheader">
<div id="title">Title</div>
<div id="button">Button</div>
</div>
</body></html>

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

1
Galen777