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

102

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

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

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

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

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

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

В итоге я вернулся к:

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

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

Cletus
источник
11
Хорошо, это имеет смысл "Какой цвет мне использовать для vim?" получает голос "за", моя конкретная проблема с макетом CSS отклоняется.
cletus
Вы можете делать все, что хотите, без таблицы в любом случае. И почему, черт возьми, @SamB наткнулся на этот вопрос двухлетней давности? DOH +
динамичный
3
@ yes123: ну, подсветка синтаксиса была неправильной ...
SamB

Ответы:

50

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

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

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

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

Грегор Брандт
источник
21
За исключением случаев, когда вы используете таблицу для презентационного макета, а не табличные данные только потому, что сначала это легче бледнеет, и в этом случае вы идете по темному и опасному пути.
One Crayon
9
Даже Amazon в определенных случаях использует таблицы. И stackoverflow.com тоже. Я за решения css, хотя они действительно работают хорошо.
Nosredna 07
11
Ни Amazon, ни теперь stackoverflow не являются вершиной веб-дизайна.
Бобби Джек,
31
Может, и нет, но это рабочие решения, которые обслуживают десятки тысяч пользователей.
17 из 26,
22
Этот мем-антистол - просто старый идиот. Единственным менеджером двухмерного макета для гибкого макета на основе ограничений является таблица; и будет ли это всего лишь один сложный (с множеством столбцов / строк) или вложенные, не имеет большого значения. Но кажется, что реальность и факты не всегда являются достаточно хорошим оружием против фанатизма.
StaxMan
28

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

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

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

Милан Бабушков
источник
2
Не обрабатывает вертикальное центрирование, поэтому -1.
SamB
1
У меня была аналогичная проблема, когда у меня был логотип слева и некоторые текстовые меню справа. Меню необходимо было выровнять по базовой линии логотипа. Использование float: right для меню не помогло. Он отправил их в верхний правый угол, и они больше не были выровнены по вертикали с базовой линией логотипа.
Жан-Франсуа Бошан
1
Я думаю, вы можете решить проблему вертикального центрирования, установив высоту строки заголовка такой же, как высота кнопки.
igors
1
@igors, +1, ты прав. Учтите, что это вопрос из 2009 года.;)
Милан Бабушков
17

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

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

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

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

АмвросийЧасовня
источник
11
Это своего рода моя проблема с аргументом «ненавистников таблиц»: CSS может делать все, что могут делать таблицы ... за исключением некоторых довольно простых, распространенных и разумных случаев (например, вертикальное центрирование). CSS просто кажется испорченным предвыборным обещанием.
cletus
4
Я хотел сказать, что вертикальное центрирование - это ЕДИНСТВЕННАЯ вещь, которая действительно трудна.
Амвросий Чапел,
3
CSS не предназначен для замены таблиц; он просто предназначен для того, чтобы позволить вам решить большинство распространенных проблем макета без таблиц. Если стол работает, используйте стол, как если бы вы рисовали ручкой вместо кувалды.
Аарон Дигулла, 06
16

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

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


источник
+1 Ого, что там за переполнение спрятано? Это действительно имеет значение. Хотя не знаю почему.
cletus
Если честно, я этого тоже не понимаю, да и упоминания об этом в спецификации не нашел. Кто-то сказал мне, что это «правильный» путь, после того как я ответил на другой вопрос, предлагая использовать для этого очищенный элемент. Мне кажется, это хорошая идея.
Плавающие элементы все еще необходимо очистить, чтобы контент, следующий за ними, работал правильно. переполнение: скрыто; относится только к высоте контейнера.
Zack The Human
2
"overflow: hidden" - это хитрость для достижения ОБЕИХ высоты "расширения" и "очистки". Следующие элементы БУДУТ очистить это поле (по крайней мере, в браузерах, которые правильно реализуют эту часть спецификации).
Бобби Джек,
1
-1 для не обработки вертикального центрирования, но +2 для overflow:hidden.
SamB
7

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

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

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

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

Я думаю , что это требует специального DTD вне XHTML 1.1, который бы просто замутить все text/htmlпротив 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чтобы выровнять блоки по базовой линии текста элемента group-header. Разная высота каждого блока будет оставаться по центру по вертикали и увеличивать высоту своего контейнера. Ширину элементов необходимо рассчитать по ширине. Здесь они 400 и 100 без горизонтального отступа.

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

Эндрю Вит
источник
1
Хм, теги display: table-X, похоже, предназначены для создания макета с использованием таблиц, только без использования тегов таблиц?
Danubian Sailor
3

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

Один мелок
источник
Ваше решение не работает в IE6 из-за псевдокласса: after.
Себастьян Хойц,
1
Он работает в IE 6 благодаря zoom: 1in .group-header, который запускает hasLayout и заставляет IE 6 вести себя так же, как если бы у него был активен элемент: after.
One Crayon
2

Сделайте двойной 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>
Bendewey
источник
У меня есть требование к вертикальному центру (и небольшая дополнительная прокладка). Я думаю, что пояснил это после того, как вы разместили.
cletus
2
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>
Омер Бохари
источник
1

Я решил использовать 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
}

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

user3522940
источник
1

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

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

Galen777
источник