Чи можете ви зробити цей HTML макет без використання таблиць?


102

Гаразд, у мене була проста проблема з компонуванням тиждень-два тому. А саме розділи сторінки потребували заголовка:

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

Досить прості речі. Справа в тому, що ненависть до таблиці, здається, перейняла у Веб-світі, про що мені нагадали, коли я запитав Навіщо використовувати теги списків визначення (DL, DD, DT) для форм HTML замість таблиць? Тепер загальна тема таблиць проти divs / 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;
  • Розумно послідовні: у різних браузерах;
  • Вертикально по центру: кнопка та назва мають різну висоту; і
  • Гнучкі: дозволяють досить точно контролювати позиціонування (накладення та / або запас) та стилізацію.

У бічній записці я сьогодні натрапив на пару цікавих статей:

EDIT: Дозвольте детальніше розглянути питання про поплавці. Цей вид робіт:

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

яка прекрасно працює.


11
Добре, що має сенс "Який колір я повинен використовувати для vim?" отримує перевагу, моя конкретна проблема компонування CSS стає усуненою.
клетус


ви можете робити все, що завгодно, без столу в будь-яких випадках. Також чому в пеклі @SamB зіткнувся з цим питанням 2 роки? DOH +
динамічний

3
@ yes123: ну, підкреслення синтаксису було неправильним ...
SamB

Відповіді:


50

Немає нічого поганого в тому, щоб використовувати доступні інструменти, щоб швидко та правильно виконати роботу.

У цьому випадку стіл працював чудово.

Я особисто використав би для цього таблицю.

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


21
За винятком випадків, коли ви використовуєте таблицю для макетів презентацій, а не табличних даних, тільки тому, що це спочатку легше блідіше;
Один олівець

9
Навіть Amazon використовує таблиці в певних випадках. І stackoverflow.com теж. Я все за рішення css, коли вони насправді працюють добре.
Nosredna

11
Ні амазонка, нині stackoverflow не є вершиною веб-дизайну.
Боббі Джек

31
Їх може не бути, але вони працюють рішеннями, які обслуговують десятки тисяч користувачів.
17 з 26

22
Цей анти-настільний мем - просто старий дурний. Єдиний двовимірний диспетчер макетів для гнучких обмежень на основі обмежень - це таблиця; і чи це лише одна складна (з безліччю col / rowspans), або вкладені, це мало має значення. Але реальність і факти не завжди є достатньо гарною зброєю проти завзяття.
StaxMan

28

Просто пливіть вліво і вправо і встановіть, щоб очистити і те, і ви закінчили. Не потрібно таблиць.

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

Edit2: Оскільки старі браузери вже не такі цікаві, я використовую завантажувальний інструмент Twitter для нових проектів. Він чудово підходить для більшості потреб у компонуванні та використовує CSS.


2
Не справляється з вертикальним центруванням, тому -1.
СамБ

1
У мене була аналогічна проблема, коли у мене був логотип зліва та деякі текстові меню праворуч. Меню потрібно було вирівняти за базовою лінією логотипу. Використання float: правильно для меню не вийшло. Це відправило їх у верхній правий кут, і вони вже не були вертикально вирівняні з базовою лінією логотипу.
Жан-Франсуа Бошан

1
Я думаю, що ви можете вирішити вертикальне центрування, встановивши висоту рядка заголовка таким же, як висота кнопки.
ігорі

1
@igors, +1, ти маєш рацію. Зверніть увагу, що це питання з 2009 року;)
Мілан Бабушков

17

Це свого роду хитромудрі питання: це виглядає жахливо просто, поки не дістанешся

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

Я хочу зафіксувати, що так, вертикальне центрування важко в CSS. Коли люди розміщують повідомлення, і це здається нескінченним на SO, "чи можете ви зробити X у CSS", відповідь майже завжди є "так", і їхні розмахування здаються невиправданими. У цьому випадку, так, одна конкретна річ є важкою.

Хтось повинен просто відредагувати все питання до "чи проблематичне вертикальне центрування в CSS?".


11
Ось така моя проблема з аргументом "ненависників таблиці": CSS може робити все, що може зробити таблиця ... крім деяких досить простих, поширених і розумних випадків (наприклад, вертикальне центрування). CSS просто здається, що передвиборні обіцянки пішли поганими.
клент

4
Моя думка полягала в тому, що вертикальне центрування - це лише ТІЛЬКА річ, яка справді важка.
AmbroseChapel

3
CSS не призначений для заміни таблиць; це просто призначене для вирішення більшості поширених проблем із компонуванням без таблиць. Якщо стіл працює, використовуйте стіл так само, як ви б застосували ручку для малювання замість кувалди.
Аарон Дігулла

16

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

Це все-таки повинно уникати проблеми z-index. Якщо це не працює, і вам справді потрібна підтримка IE5, продовжуйте користуватися таблицею.


+1 Whoa, що з переливом приховано? Це має значення. Не маю ідеї, хоча все-таки.
клент

Якщо чесно, я також не розумію цього, і не могла знайти жодної згадки про нього в специфікації. Хтось сказав мені, що це "правильний" спосіб, хоча я відповів на інше запитання, пропонуючи використати очищений елемент для цього. Здається, це гарна ідея для мене.

Плаваючі елементи все ще потрібно очистити, щоб вміст, що слідує за ними, належним чином перетікав. переповнення: приховано; стосується лише висоти контейнера.
Зак Людина

2
"overflow: hidden" - це злом для досягнення висоти "розширення" та очищення висоти. Наступні елементи БУДУТЬ зрозуміли це поле (принаймні, у браузерах, які правильно реалізують цю частину характеристики).
Боббі Джек

1
-1 для не вертикального центрування, але +2 для overflow:hidden.
СамБ

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: право для другого стовпця. (Натомість, ми повинні зробити перший стовпчик досить широким, щоб просунути його.)

<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: Ми додаємо .валіgn обгортки навколо кожного стовпця. (Дайте їм більш "семантичне" ім'я, якщо це зробить вас щасливішими.) Їх потрібно зберігати без пробілів між ними, або текстові пробіли розсунуть їх. (Я знаю, що це відстійно, але це ви отримуєте за те, що ви "чисті" з розміткою та відокремлюєте її від презентаційного шару ... Га!)

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

Виправлення IE: Internet Explorer відображає лише вбудований блок для вбудованих елементів (наприклад, span, не div). Але, якщо ми дамо div hasLayout, а потім покажемо його inline, він буде вести себе так само, як inline-block. Регулювання поля полягає у виправлення розриву в 1 піксель вгорі (спробуйте додати кольори фону до .group-заголовка, щоб побачити).


1
Хм дисплей: начебто теги table-X мають мету робити компонування за допомогою таблиць, тільки без використання тегів таблиць?
Дунайський матрос

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-індексу, якщо він доходить до цього.

Зауважте, що вам не потрібно width: 100%в діві, оскільки це елемент на рівні блоку, і zoom: 1змушує дів вести себе так, як він має чіткий виправлення в IE (інші браузери підбирають фактичний виправлення). Також вам не потрібні всі ці сторонні класи, якщо ви орієнтуєтесь на речі трохи конкретніше, хоча вам може знадобитися оболонка з розгорнутим або переключитися на кнопку, щоб полегшити позиціонування.


Ваше рішення не працює на IE6, хоча через: після псевдокласу.
Себастьян Хойц

1
Це працює в IE 6, завдяки zoom: 1in .group-header, який запускає hasLayout і змушує IE 6 вести себе так само, як якщо б у ньому був елемент: after.
Один олівець

2

Виконайте подвійне плавання в діві та використовуйте 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>

У мене є вимога до вертикального центрування (і трохи додаткової прокладки). Думаю, я уточнив, що після того, як ви опублікували.
клент


1

Я вирішив використовувати Flexbox, тому що це значно спростило.

В основному вам потрібно перейти до батьків дітей, яких ви хочете вирівняти і додати display:box(звичайно, з префіксом). Щоб змусити їх сидіти в сторони, використовуйте виправдання-зміст . Простір між собою - це правильна річ, коли у вас є елементи, які потрібно вирівняти до кінця, як у цьому випадку (див. Посилання) ...

Потім питання вертикального вирівнювання. Оскільки я зробив батьківський з двох елементів, ви хочете вирівняти Flexbox. Зараз це легко використовувати align-items: center.

Потім я додав потрібні раніше стилі, вилучив поплавок із заголовка та кнопки в заголовку та додав вкладку:

.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

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

Функція кнопки та будь-які додаткові деталі можна стилізувати з цієї основної форми. Вибачення за погані теги.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.