Search code examples
htmltwitter-bootstrapresponsive-designtwitter-bootstrap-3

Break a table row into multiple line (responsive layout)


I have a webpage that lists items. The default template uses a table for that, which i find very appropriate. In this table however, there is one column that contains much more text than the others:

enter image description here

While that works out on a large screen, it is very annoying to read on a small screen:

enter image description here

In order to use the available space better, I can only think of a fake-table layout using divs. I did a prototype, using bootstrap grid layout, that looks like a table row on large screens, but has a different layout on small and extra small screens:

enter image description here

While that improves the readability of the text by using the full width, I cannot use the utilities I've got for tables any more, and it breaks the user experience in subtle ways. For example, I use a nice script that enables sorting at the client. But that works only on real tables. (Also, there are small inconsistencies and visual differences between real tables and fake tables)

Is there any way that I can reformat a table row into a multi-line container similar to the one in the last image?

FYI: I am using jquery 2.1.1, Bootstrap 3.2.0.1 as GUI Framework and asp.net MVC on the server.

Bootply is here: http://www.bootply.com/pRehwTai4G

Edit: in case that did not come out clear enough: I want to keep the <tr> and <td> tags but style them similar to the divs. I do not want to replace the table with divs.


Solution

  • It's 2024, and we now have better tools at our disposal to effect responsive table layouts. In particular, we can use a CSS media query to override the table to use a grid layout, and then we can override cells in specific columns so that they span the full width of the table, which forces them to flow onto their own rows. See below for an adaptation of OP's example that responsively reflows the "Beschreibung" column in moderately width-constrained browser viewports and additionally reflows the "Titel" column in extremely width-constrained browser viewports.

    body {
        background-color: #fff;
        color: #333;
        font-family: Arial, sans-serif;
    }
    table.responsive {
        border-collapse: collapse;
    }
    table.responsive > :is(thead, tbody, tfoot) > tr > :is(td, th) {
        padding: 0.667em;
        text-align: initial;
        vertical-align: top;
    }
    table.responsive > thead > tr > :is(td, th) {
        border-bottom: 3px solid #666;
    }
    table.responsive > thead > tr > th.sort-asc {
        border-color: #af0331;
    }
    table.responsive > thead > tr > th.sort-asc::after {
        border-color: #333;
        border-style: none solid solid none;
        border-width: 3px;
        content: "";
        display: inline-block;
        height: 0.25em;
        margin-left: 0.5em;
        margin-top: -0.25em;
        transform: rotate(45deg);
        vertical-align: middle;
        width: 0.25em;
    }
    table.responsive > tbody > tr > :is(td, th) {
        border-bottom: 1px solid #777;
    }
    table.responsive > tbody > tr:nth-child(odd) > :is(td, th) {
        background-color: #ddd;
    }
    table.responsive > tbody > tr:hover > :is(td, th) {
        background-color: #b7bcd6;
    }
    @media screen and (max-width: 25cm) {
        table.responsive {
            display: grid;
            grid-auto-flow: dense;
            grid-template-columns: repeat(5, auto);
        }
        table.responsive > :is(thead, tbody, tfoot),
        table.responsive > :is(thead, tbody, tfoot) > tr {
            display: contents;
        }
        table.responsive > thead > tr > :is(td, th):nth-child(3) {
            display: none;
        }
        table.responsive > tbody > tr > :is(td, th):nth-child(3) {
            grid-column: 1 / -1;
        }
        table.responsive > tbody > tr > :is(td, th):nth-child(3)::before {
            content: "Beschreibung: ";
            font-weight: bold;
        }
        table.responsive > tbody > tr > :is(td, th):not(:nth-child(3)) {
            border-bottom: none;
            padding-bottom: 0;
        }
    }
    @media screen and (max-width: 20cm) {
        table.responsive {
            grid-template-columns: repeat(4, auto);
        }
        table.responsive > thead > tr > :is(td, th):nth-child(2) {
            display: none;
        }
        table.responsive > tbody > tr > :is(td, th):nth-child(2) {
            grid-column: 1 / -1;
        }
        table.responsive > tbody > tr > :is(td, th):nth-child(2)::before {
            content: "Titel: ";
            font-weight: bold;
        }
    }
    <table class="responsive">
        <thead>
            <tr>
                <th>Sitzungstyp</th>
                <th>Titel</th>
                <th class="sort-asc">Beschreibung</th>
                <th>Priorität</th>
                <th>Erstellt</th>
                <th>Geändert</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>ILK-AK Garching</td>
                <td>Einen guten Titel zu finden ist eigentlich eine Diskussion …</td>
                <td>Eine wunderbare Heiterkeit hat meine ganze Seele eingenommen, gleich den süßen Frühlingsmorgen, die ich mit ganzem Herzen genieße. Ich bin allein und…</td>
                <td>Niedrig</td>
                <td>18.07.2014 12:03</td>
                <td>vor 14 Minuten</td>
            </tr>
            <tr>
                <td>ILK-AK Garching</td>
                <td>Tests von mechanischen Apparaten sind grundsätzlich erwünsc…</td>
                <td>Er hörte leise Schritte hinter sich. Das bedeutete nichts Gutes. Wer wünde ihm schon folgen, spät in der Nacht und dazu noch in dieser engen Gasse mi…</td>
                <td>Mittel</td>
                <td>von einer Stunde</td>
                <td>vor 11 Minuten</td>
            </tr>
            <tr>
                <td>ILK-AK Garching</td>
                <td>Zeta-Kafka ist, gleich einem Manifest, pompös und glorreich</td>
                <td>Jemand musste Josef K. verleumdet haben, denn ohne dass er etwas Böses getan hätte, wurde er eines Morgens verhaftet. »Wie ein Hund!« sagte er, es wa…</td>
                <td>Niedrig</td>
                <td>vor einer Stunde</td>
                <td>vor 13 Minuten</td>
            </tr>
            <tr>
                <td>ILK-AK Augsburg</td>
                <td>Alles in Ordnung</td>
                <td>Keine Panik</td>
                <td>Niedrig</td>
                <td>vor einer Stunde</td>
                <td>vor 33 Sekunden</td>
            </tr>
        </tbody>
    </table>