Можете ли вы сделать этот макет 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 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 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>

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Я думаю, что для этого требуется специальный DTD за XHTML 1.1, который просто возбудит все обсуждения text/html vs 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: справа для второго столбца. (Вместо этого мы должны сделать первый столбец достаточно широким, чтобы перетащить его.)

<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, а затем отобразим его в строке, он будет вести себя точно так же, как inline-block. Корректировка поля - это установить 1px-зазор вверху (попробуйте добавить цвета фона в заголовок группы.)

Ответ 6

Я бы рекомендовал не использовать таблицу в этом экземпляре, потому что это не табличные данные; это чисто презентация, чтобы кнопка находилась в крайнем правом углу. Это то, что я сделал бы, чтобы дублировать структуру вашей таблицы (измените ее на другой 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 есть clearfix (другие браузеры принимают фактическое clearfix). Вам также не нужны все эти посторонние классы, если вы ориентируетесь на вещи немного более конкретно, хотя вам может понадобиться обертка div или span на кнопке, чтобы упростить позиционирование.

Ответ 7

Сделайте двойной 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>

Ответ 8

<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>

Ответ 9

Я согласен с тем, что на самом деле следует использовать таблицы только для табличных данных, по той простой причине, что таблицы не отображаются, пока они не завершат загрузку (независимо от того, насколько быстро это происходит; это медленнее, чем метод 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>

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

Ответ 10

Я решил использовать Flexbox, потому что он сделал все намного проще.

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

Тогда вопрос вертикального выравнивания. Поскольку я сделал родителем этих двух элементов, вы хотите выровнять Flexbox. Теперь легко использовать 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
}

Посмотреть демо