CSS Hell, имитирующий TABLE с помощью DIV

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

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

Макет с таблицей/CSS и таблицей/CSS

HTML/CSS

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <title>Teste</title>
    <style type="text/css">
        table{
            table-layout:fixed;
            width: 333px;
            border-width: 1px;
            border-spacing: 2px;
            border-style: solid;
            border-color: black;
            border-collapse: collapse;
        }
    
        table th, table td
        {
            border-width: 1px;
            padding: 1px;
            border-style: solid;
            border-color: black;
            border-collapse: collapse;
        }
    
        table th.column1, table td.column1{
            width:60px;
            background-color:#CCD9FF;
        }
    
        table th.column2, table td.column2{
            width:100px;
            background-color:#ECFFE5;
        }
    
        table th.column3, table td.column3{
            width:60px;
            background-color:#FFEBE5;
        }
    
        table th.column4, table td.column4{
            width:100px;
            background-color: #FFFFCC;
        }
    
        div#tablecontainer
        {
            width: 328px;
        }
    
        div.tablecontainerrow
        {
            clear:both;
        }
    
        div#tablecontainer div div.column1
        {
            width: 60px;
            float:left;
            border: 1px solid black;
            background-color:#CCD9FF;            
        }
    
        div#tablecontainer div div.column2
        {
            width: 100px;
            float:left;
            border: 1px solid black;
            background-color:#ECFFE5;            
        }

        div#tablecontainer div div.column3
        {
            width: 60px;
            float:left;
            border: 1px solid black;
            background-color:#FFEBE5;            
        }
    
        div#tablecontainer div div.column4
        {
            width: 100px;
            float:left;
            border: 1px solid black;
            background-color:#FFFFCC;            
        }
    
    
    </style>
</head>
<body>
    <h1>CSS and TABLE</h1>
    <table>
        <tr>
            <th class="column1">Header 1</th>
            <th class="column2">Header 2</th>
            <th class="column3">Header 3</th>
            <th class="column4">Header 4</th>
        </tr>
        <tr>
            <td class="column1">line 1 column 1</td>
            <td class="column2">line 1 column 2</td>
            <td class="column3">line 1 column 3</td>
            <td class="column4">line 2 column 4</td>
        </tr>
        <tr>
            <td class="column1">line 2 column 1</td>
            <td class="column2">line 2 column 2</td>
            <td class="column3">line 2 column 3</td>
            <td class="column4">line 2 column 4</td>
        </tr>
        <tr>
            <td class="column1">line 3 column 1</td>
            <td class="column2">line 3 column 2</td>
            <td class="column3">line 3 column 3 (more content)</td>
            <td class="column4">line 3 column 4</td>
        </tr>
    </table>
    <h1>CSS and DIV</h1>
    <div id="tablecontainer">
        <div class="tablecontainerrow">
            <div class="column1">Header 1</div>
            <div class="column2">Header 2</div>
            <div class="column3">Header 3</div>
            <div class="column4">Header 4</div>
            <div class="clear" />
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 1 column 1</div>
            <div class="column2">line 1 column 2</div>
            <div class="column3">line 1 column 3</div>
            <div class="column4">line 1 column 4</div>
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 2 column 1</div>
            <div class="column2">line 2 column 2</div>
            <div class="column3">line 2 column 3</div>
            <div class="column4">line 2 column 4</div>
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 3 column 1</div>
            <div class="column2">line 3 column 2</div>
            <div class="column3">line 3 column 3 (more content)</div>
            <div class="column4">line 3 column 4</div>
        </div>
    </div>
</body>
</html>

Что я могу изменить, чтобы макет CSS/DIV напоминал CSS/таблицу?

Некоторая дополнительная информация

  • Думайте об этом как об упражнении (вызове). Поэтому, пожалуйста, не отвечайте мне, говоря, что использование таблицы - лучшее решение для этой ситуации.
  • На самом деле мне интересно решение, которое может полностью изменить табличное расположение данных на другое, просто изменив CSS. В этом случае об использовании <table> не может быть и речи.
  • Мне нужна совместимость с IE 7+, FF3+, Chrome 4+.

Спасибо!


css
person outlookrperson    schedule 09.06.2011    source источник
comment
Это то, что вы пытаетесь отобразить в виде таблицы? В таком случае воспользуйтесь таблицей.   -  person Michael Mior    schedule 10.06.2011
comment
Зачем? семантическое использование таблицы для табличных данных считается лучшей практикой.   -  person matchew    schedule 10.06.2011
comment
Соглашаясь с постерами выше, таблица имеет смысл, если вы отображаете таблицу.   -  person Jeremy B.    schedule 10.06.2011
comment
Просто используйте таблицу. Но на вопрос: проверить на display: table display: table-row и так далее...   -  person BrunoLM    schedule 10.06.2011
comment
"I´m trying to simulate a table using only CSS and DIV." - почему?   -  person thirtydot    schedule 10.06.2011
comment
@BrunoLM, @Michael, @matchew, @Jeremy, @thirtydot, Чтобы объяснить, почему использовать CSS вместо таблицы, см. дополнительную информацию, которую я добавил в свой вопрос.   -  person outlookrperson    schedule 10.06.2011
comment
@rperson: Хорошо, я понимаю, о чем ты говоришь. Два вопроса: приемлемо ли решение, предоставленное @Richard JP Le Guen? И вы сказали "For the sake of compatibility I want to use CSS 2.1.", но какие фактические браузеры/версии вам нужно поддерживать?   -  person thirtydot    schedule 10.06.2011
comment
@thirtydot, решение, предоставленное @Richard JP, на данный момент является лучшим. Я просто жду, чтобы увидеть, будет ли представлен еще один хороший ответ, прежде чем проголосовать за него как за правильный. Мне нужна совместимость с IE 7+, FF3+, Chrome 4+. Думаю, я понял вашу мысль: если мне нужна совместимость с IE7, CSS 2.0 не поддерживается полностью. Итак, я обновляю файл complementary information. Спасибо.   -  person outlookrperson    schedule 10.06.2011
comment
@rperson: В другом комментарии вы сказали: "what about the situation in which a tabular data view is only one among several other presentation layouts that can be choosen" - как изменился макет презентации? Это что-то на стороне сервера или вы используете JavaScript для изменения представления на стороне клиента? Я спрашиваю, потому что если вы используете JavaScript, то его также можно использовать для исправления height ваших div.   -  person thirtydot    schedule 10.06.2011
comment
@thirtydot, скажите, что пользователь может выбрать один из нескольких вариантов макетов / скинов в области администрирования вашего профиля, затем его параметры сохраняются и используются для определения CSS, который загружается при отображении страницы. Это серверная вещь.   -  person outlookrperson    schedule 10.06.2011
comment
@rperson: В этом случае правильное решение состоит в том, чтобы правильно абстрагировать вывод данных, чтобы вы также могли выводить разные HTML (например, настоящий table) для каждого макета/скина. Либо сделайте это, либо откажитесь от поддержки IE7 и используйте свойства display: table-cell.   -  person thirtydot    schedule 10.06.2011


Ответы (8)


Опять же, вы должны использовать таблицу.

Но если это просто упражнение в CSS, для пинков...

  • Откажитесь от <div class="clear" />.
  • Откажитесь от фоновых цветов и используйте вместо них фальшивые столбцы.
  • Не устанавливайте границы вокруг отдельных ячеек; вместо этого поместите их вокруг рядов.
  • Дайте строкам overflow:hidden

Вот так: http://jsfiddle.net/39F88/

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <title>Teste</title>
    <style type="text/css">
        table{
            table-layout:fixed;
            width: 333px;
            border-width: 1px;
            border-spacing: 2px;
            border-style: solid;
            border-color: black;
            border-collapse: collapse;
        }

        table th, table td
        {
            border-width: 1px;
            padding: 1px;
            border-style: solid;
            border-color: black;
            border-collapse: collapse;
        }

        table th.column1, table td.column1{
            width:60px;
            background-color:#CCD9FF;
        }

        table th.column2, table td.column2{
            width:100px;
            background-color:#ECFFE5;
        }

        table th.column3, table td.column3{
            width:60px;
            background-color:#FFEBE5;
        }

        table th.column4, table td.column4{
            width:100px;
            background-color: #FFFFCC;
        }

        div#tablecontainer
        {
            width:335px;
            border-top:1px solid black;
            background:url(http://i.stack.imgur.com/ZsO5U.png) TOP LEFT REPEAT-Y;
        }

        div.tablecontainerrow
        {
            clear:both;
            overflow:hidden;
            border:1px solid black;
            border-top:none;
        }

        div#tablecontainer div div.column1
        {
            width: 62px;
            float:left;
        }

        div#tablecontainer div div.column2
        {
            width: 104px;
            float:left;
        }

        div#tablecontainer div div.column3
        {
            width: 62px;
            float:left;
        }

        div#tablecontainer div div.column4
        {
            width: 104px;
            float:left;
        }


    </style>
</head>
<body>
    <h1>CSS and TABLE</h1>
    <table>
        <tr>
            <th class="column1">Header 1</th>
            <th class="column2">Header 2</th>
            <th class="column3">Header 3</th>
            <th class="column4">Header 4</th>
        </tr>
        <tr>
            <td class="column1">line 1 column 1</td>
            <td class="column2">line 1 column 2</td>
            <td class="column3">line 1 column 3</td>
            <td class="column4">line 2 column 4</td>
        </tr>
        <tr>
            <td class="column1">line 2 column 1</td>
            <td class="column2">line 2 column 2</td>
            <td class="column3">line 2 column 3</td>
            <td class="column4">line 2 column 4</td>
        </tr>
        <tr>
            <td class="column1">line 3 column 1</td>
            <td class="column2">line 3 column 2</td>
            <td class="column3">line 3 column 3 (more content)</td>
            <td class="column4">line 3 column 4</td>
        </tr>
    </table>
    <h1>CSS and DIV</h1>
    <div id="tablecontainer">
        <div class="tablecontainerrow">
            <div class="column1">Header 1</div>
            <div class="column2">Header 2</div>
            <div class="column3">Header 3</div>
            <div class="column4">Header 4</div>
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 1 column 1</div>
            <div class="column2">line 1 column 2</div>
            <div class="column3">line 1 column 3</div>
            <div class="column4">line 1 column 4</div>
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 2 column 1</div>
            <div class="column2">line 2 column 2</div>
            <div class="column3">line 2 column 3</div>
            <div class="column4">line 2 column 4</div>
        </div>
        <div class="tablecontainerrow">
            <div class="column1">line 3 column 1</div>
            <div class="column2">line 3 column 2</div>
            <div class="column3">line 3 column 3 (more content)</div>
            <div class="column4">line 3 column 4</div>
        </div>
    </div>
</body>
</html>
person Richard JP Le Guen    schedule 09.06.2011
comment
Это было очень хорошее решение. Это не работает только с IE6. Он был отмечен как правильный. Спасибо! - person outlookrperson; 10.06.2011
comment
Я предполагаю, что я не могу получить вертикальное выравнивание текста, как это делает таблица, не так ли? - person outlookrperson; 10.06.2011
comment
спасибо, действительно помогите с IE и доступностью. - person forX; 22.02.2013
comment
@forX - Помните: если вы говорите о табличных данных, размещение их в таблице не повредит доступности. - person Richard JP Le Guen; 22.02.2013

Использование таблиц для компоновки страниц не очень профессионально, но использование таблиц для отображения таблиц вполне допустимо — именно для этого их и следует использовать. Эмуляция таблиц с помощью div и css заходит слишком далеко.

person Dariusz Walczak    schedule 09.06.2011
comment
Я согласен, но как насчет ситуации, в которой табличное представление данных является лишь одним из нескольких других макетов презентации, которые может выбрать пользователь? - person outlookrperson; 10.06.2011
comment
Радикальное изменение макета страницы (или ее части) с использованием только css может быть затруднено. Не всегда возможно полностью отделить структуру документа (HTML) от его представления (CSS), по крайней мере без особых усилий. Чтобы добиться некоторых эффектов или обойти некоторые специфичные для браузера ошибки, вы должны изменить структуру (например, добавить несколько волшебных div). Чтобы сделать это возможным, более дешевым и менее разочаровывающим, я бы подумал о замене как CSS, так и HTML. Замена может быть выполнена на стороне сервера в случае традиционных страниц или на стороне клиента (с использованием JS), когда обновление страницы нежелательно. - person Dariusz Walczak; 10.06.2011
comment
Спасибо за ваши комментарии. Они уместны и имеют смысл для меня. - person outlookrperson; 10.06.2011

Это ужасный ответ, я не могу поверить, что даже предлагаю его, НО, если вы чертовски одержимы созданием таблицы из div...

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

Это рекомендуется только в том случае, если вы ДОЛЖНЫ создать таблицу с элементами div.

В CSS есть малоизвестное свойство display, которое поможет вам в этом, прочитайте здесь: table-cell css.

Опять же, просто используйте таблицу, если можете.

person Jeremy B.    schedule 09.06.2011
comment
И использование display:table-cell для чего угодно, кроме элемента td, приводит к тому, что в браузерах появляются всевозможные гремлины. Сильно осуждаемый и с семантической точки зрения, на самом деле неправильно использовать элементы div для представления табличных данных. - person colinross; 10.06.2011
comment
Использование table-cell на td похоже на написание слова DOG на вашем домашнем бигле. - person Jeremy B.; 10.06.2011
comment
его только там, чтобы вернуться к правильному значению, если у вас есть проблемы с наследованием от родительских значений. На самом деле он начинался как режим рендеринга (браузера), и значение css было добавлено для ручного запуска этого режима рендеринга. Каждый браузер немного отличается в том, когда этот режим на самом деле будет давать требуемые результаты, поскольку неправильное использование этого значения может привести к ситуациям, когда механизму рендеринга приказано отображать ячейку таблицы без родительской строки, набора строк или таблицы. - person colinross; 10.06.2011

Если вы представляете табличные данные (множество атрибутов нескольких похожих объектов, также называемых табличными данными), используйте тег <table>.

person colinross    schedule 09.06.2011

div#tablecontainer
{
    width: 328px;
    display:table;
}

div.tablecontainerrow
{
    display:table-row;
}
div.tablecontainerrow div{
    display:table-cell;
    vertical-align:middle;
}

Конечно, я думаю, что большинство современных браузеров справляются с этим, за исключением MSIE...

person Wrikken    schedule 09.06.2011
comment
Да, конечно, это почти бесполезно, и единственная его цель — проверить, правильно ли браузеры поддерживают функцию CSS. Это может принести некоторую пользу в XHTML со встроенным XML, но не более того. - person Wrikken; 10.06.2011
comment
это интересное решение, но жаль, что display: table работает только с IE 8.0 и выше. К сожалению, я считаю, что IE 7.0 пока необходим. Не так ли? - person outlookrperson; 10.06.2011
comment
Зависит: в общедоступном Интернете поддержка MSIE 7 (а для некоторых сайтов — MSIE 6, проверьте статистику пользовательского агента конкретного сайта) в основном является обязательной. Опять же, как я уже сказал, его можно использовать только при встраивании отображаемого XML в XHTML, что я видел больше во внутренних сетях, чем в Интернете (но это может быть мой ограниченный опыт), и в контролируемой среде вы, конечно, a сказать, какие браузеры будут использоваться. - person Wrikken; 10.06.2011

Насколько я знаю, единственный способ обойти это — явно установить высоту ваших «столбцов», иначе по умолчанию для div будет задана высота: авто, и они будут такими же большими, как содержимое внутри них. Установка высоты может быть опасной, если у вас есть контент, который требует больше места, чем позволяет высота.

person gdub    schedule 09.06.2011
comment
Как правило, установка высоты пытается заставить слой представления (HTML), который был явно разработан, чтобы НЕ обеспечивать вертикальную компоновку - для принудительной вертикальной компоновки - и, как таковой, проблематичен - как в теории, так и на практике. - person colinross; 10.06.2011
comment
это не решение, потому что содержимое столбца является динамическим, и я не знаю его длины. - person outlookrperson; 10.06.2011

Очень надоедливая проблема, только что возникла на работе. Я обычно использую фон для решения этой проблемы, но поскольку теперь все должно быть отзывчивым, создавать изображения для каждого медиазапроса раздражает. Это единственный раз, когда я буду использовать JavaScript для достижения того, чего хочу. Глупо, что не поддерживается.

HTML:

<ul class="table-layout clearfix">
    <li>
        <p>Header 1</p>
        <p>Header 1</p>
        <p>Header 1</p>
        <p>Header 1</p>
        <p>Header 1</p>
        <p>Header 1</p>
    </li>
    <li>
        <p>Header 1</p>
    </li>
    <li>
        <p>Header 1</p>
    </li>
</ul>

JavaScript:

$(document).ready(function(){

    var height = 0;

    $(".table-layout li").each(function(i){

        if($(this).height() > height)
            height = $(this).height();

    });

    $(".table-layout li").css("height", height + 'px');

});

CSS:

    /**
     * Markup free clearing.
     *
     * @see http://perishablepress.com/press/2009/12/06/new-clearfix-hack
     */
    .clearfix:after {
      content: ".";
      display: block;
      height: 0;
      clear: both;
      visibility: hidden;
    }
    /* IE6 */
    * html .clearfix {
      height: 1%;
    }
    /* IE7 */
    *:first-child + html .clearfix {
      min-height: 1%;
    }

    ul, li{
        margin:0;
        padding:0;
        list-style-type:none;
    }

    ul{
        width:335px;
        overflow:hidden;
    }

    ul li{
        width: 31.5%;
        float:left;
        border:1px solid #000;
        margin-right:4px;
    }

http://jsfiddle.net/kXrn5/6/

person Michael E    schedule 08.11.2013

Вот моя попытка. Это, вероятно, не идеально, но это начало. Для меня он работает с новейшими версиями Chrome, Firefox, Safari, Opera, IE10 и IE9. Извините, у меня нет IE7 для тестирования. Я сомневаюсь, что это работает, так как с IE7 было трудно иметь дело.

http://jsfiddle.net/nluis3294/uLuof882/

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

Однако также можно сказать, что я хочу, чтобы мои нетабличные данные были выровнены по сетке и чтобы эти строки и столбцы растягивались, как обычная html-таблица. Это дизайнерский выбор, и он абсолютно законен. Вот где трудности. Вы можете использовать таблицы, которые намного проще, но технически неверны. Или вы можете использовать элементы div и полагаться на такие трюки, как фоновые изображения, искусственные столбцы и разделители, чтобы все выглядело как таблицы.

Использование искусственных столбцов также не кажется мне «правильным». Если вы хотите изменить ширину столбца, вам нужно отредактировать фоновое изображение. И использование фонового изображения для установки цвета фона кажется мне странным. У меня есть аналогичные оговорки по поводу других приемов, таких как столбцы Psuedo или приемы с отрицательными полями. По моему мнению, они должны просто изменить css, чтобы обеспечить простой способ получить что-то похожее на сетку без уловок.

<div class="testTable">
<div class="testRow">
    <div class="testColumn1">
        aa
    </div>
    <div class="testColumn2">
        bb<br/>
        bbb2
    </div>
    <div class="testColumn3">
        cc<br/>
        cccc2
    </div>
    <div class="testColumn4">
        dddddd<br/>
        dddddd
    </div>

</div>
<div class="testRow">
    <div class="testColumn1">
        aa
    </div>
    <div class="testColumn2">
        bb<br/>
        bbb2
    </div>
    <div class="testColumn3">
        cc<br/>
        cccc2
    </div>
    <div class="testColumn4">
        dddddd<br/>
        dddddd
    </div>

</div>

<div class="testRow">
    <div class="testColumn1">
        aaa aaa
    </div>
    <div class="testColumn2">
        bb<br/>
        bbb2<br/>
        bbbbbbbbbbbbbbbbbbbb3

    </div>
    <div class="testColumn3">
        cccccc<br/>

    </div>
    <div class="testColumn4">
        ddddd<br/>
        ddd
    </div>  
    </div>
</div>

CSS:

div.testTable{
    width: 30%; display: table; table-layout: auto;
    padding:0;
    margin:0;

}

div.testRow{
    display: table-row; width: 100%; 
white-space: nowrap;
    vertical-align:top;
    padding:0;
    margin:0;

}

div.testColumn1{
    display: table-cell; height:100%; min-width: 25%; background-color: #CCD9FF;    
    vertical-align:top;
    padding: 0.2em;

    border: 1px solid black;
    margin:0;

}

div.testColumn2{
    display: table-cell; height:100%; min-width: 25%;background-color: #ECFFE5; 
    vertical-align:top;
    padding: 0.2em;

    border: 1px solid black;
    margin:0;

}
div.testColumn3{
    display: table-cell; height:100%; min-width: 25%;background-color: #FFEBE5; 
    vertical-align:top;
    padding: 0.2em;

    border: 1px solid black;
    margin:0;

}

div.testColumn4{
    display: table-cell; height:100%; min-width: 25%;background-color: #FFFFCC; 
    vertical-align:top;
    padding: 0.2em;

    border: 1px solid black;
    margin:0;
}
person NL3294    schedule 30.01.2015