Responsive Semantic UI Table
Adam C. |

Semantic UI's table component is not quite mobile-friendly even with the stackable option. Actually, there is no standard way to make a stable responsive. A horizontal scrollable table is often being used, but if you like a stackable way, and with a table header as a label on each row, then in this article, I will show you how to do it using existing Semantic UI's table component with some small changes.

Photo by Jess Bailey on Unsplash

here is a demo

First of all, let's disable the stackable, i.e. use “unstackable” instead., and then add “data-label” attribute to the table cell. which is corresponding to the table header. And the sample HTML code like below:

 <Table celled unstackable striped className="dnxTable">
    <Table.Header>
      <Table.Row>
        <Table.HeaderCell>Header1</Table.HeaderCell>
        <Table.HeaderCell>Header2</Table.HeaderCell>
        <Table.HeaderCell>Header3</Table.HeaderCell>
      </Table.Row>
    </Table.Header>

    <Table.Body>
      <Table.Row>
        <Table.Cell data-label="Header1">Cell</Table.Cell>
        <Table.Cell data-label="Header2">Cell</Table.Cell>
        <Table.Cell data-label="Header3">Cell</Table.Cell>
      </Table.Row>
      ...
    </Table.Body>
 </Table>   

Next, we need to add some CSS, which is applied to the small screen only.

@media only screen and (max-width: 767px) {
  table.dnxTable {
    border: none !important;
  }
  
  table.dnxTable th,
  table.dnxTable td {
    padding: 1em 0.5em;
    position: relative;
  }

  table.dnxTable tr,
  table.dnxTable td,
  table.dnxTable tfoot {
    display: block !important;
    width: 100%;
  }

  table.denxTable tbody tr {
    border-top: 1px solid rgba(34, 36, 38, 0.1);
  }

  table.denxTable tfoot tr {
    border: none !important;
  }

  table.dnxTable td {
    border-top: none !important;
    border-left: none !important;
  }
  
  table.dnxTable tbody tr {
    padding: 0.25em 0;
    border: 1px solid rgba(34, 36, 38, 0.2);
  }

  table.dnxTable tbody tr:not(:last-child) {
    margin-bottom: 0.25em;
  }

  /** important1: hide theader **/
  table.dnxTable thead {
    display: none !important;
  }

  table.dnxTable tbody td {
    padding: 0.3em 0.5em 0.3em 7.5em !important;
  }

  .dnxTable td:not(:last-child) {
    border-bottom: 1px solid rgba(34, 36, 38, 0.1);
  }

  /** important2: use data-label attribute as a table header **/
  table.dnxTable tbody td:before {
    content: attr(data-label);
    left: 0.5em;
    position: absolute;
    top: 0.15em;
    font-weight: bold;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 6em;
    overflow: hidden;
  }
}

As the comments in the CSS code able, there are two important things:

  1. Hide the regular table header, because the table cells are stacked, and we show the corresponding table header at the beginning of the cell content. 
  2. Use the data-label attribute as the content of td:before

td.before has “absolute” position, so it does not auto-wrap. In the case, the header is very long, I use  ellipsis to hide the overflow part. And the width: 6em need to be matched to the padding left of <td>, which is 7.5em. so there are 1.5em padding between label and cell content.

Other CSS definitions could be customized especially those paddings.

Here is the demo