0

I have a wide html-table that I'd like to present for lower screen widths by styling it with pure css.

this is the unstyled table enter image description here (the cells are overwide and full of content, this is just an abstract example)

this is the desired outcome my goal

Each row should be a Block with the table cells stacked on top of each other in the same order as in the html source. Then this blocks should be layouted in a grid, so that there are as many blocks next to each other as the screenwidths allows.

Minimal Example

div {
  color: grey;
  border: 1px solid blue;
  width: 600px;
}

body {
  padding: 20px;
  font-family: Helvetica;
}

.box {
  background-color: black;
  color: #fff;

  padding: 10px;
  padding-right: 150px;
  font-size: 14px;
}

/*makes desired blocks*/
.wrapper td {
  display: block;
}

.wrapper td:last-child {
  margin-bottom: 10px;
}
<div>

<table class="wrapper">
  <tr>
    <td class="box a">A1</td>
    <td class="box b">B1</td>
    <td class="box c">C1</td>
    <td class="box d">D1</td>
    <td class="box e">E1</td>
    <td class="box f">F1</td>
  </tr>
  <tr>
    <td class="box a">A2</td>
    <td class="box b">B2</td>
    <td class="box c">C2</td>
    <td class="box d">D2</td>
    <td class="box e">E2</td>
    <td class="box f">F2</td>
  </tr>
  <tr>
    <td class="box a">A3</td>
    <td class="box b">B3</td>
    <td class="box c">C3</td>
    <td class="box d">D3</td>
    <td class="box e">E3</td>
    <td class="box f">F3</td>
  </tr>
    <tr>
    <td class="box a">A4</td>
    <td class="box b">B4</td>
    <td class="box c">C4</td>
    <td class="box d">D4</td>
    <td class="box e">E4</td>
    <td class="box f">F4</td>
  </tr>
</table>
</div>

This does give me the blocks I want. But I failed so far to arrange the elements in a css grid.

Here is an example of what css I tried:

    .wrapper {
  display: grid;
  grid-auto-flow: row dense;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 10px;
  grid-auto-rows: minmax(300px, auto);
}

This does work on nested divs as expected (js Fiddle )

I think it brobably has something to do with tables not being allowed to be layouted as grids.

I'd like to avoid making div tables out of my data though, because semantically it is a table and I've heard that this is better for screen teaders and such.

I also tried the various css placement algorithms I looked at the mozilla examples and tried applying them. Also I messed around with setting display:contents for td and tr selectevly

4
  • 1
    You can keep the table html elements. reset their display property and apply CSS Grid jsfiddle.net/f9q4gntp Commented May 17, 2020 at 13:08
  • @ZohirSalak the ">" is doing what exactly? Commented May 17, 2020 at 13:20
  • tbody{display:contents}would work too where browser understand it ;) Commented May 17, 2020 at 13:22
  • 1
    @Nivatius It's for selecting direction children developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator Commented May 17, 2020 at 13:38

2 Answers 2

1

You can use the flex model, but do not forget that tbody will be there even if not in the HTML code :

Possible example to start from or your grid fiddle attempt updated https://jsfiddle.net/218drc0t/ :

div {
  color: grey;
  border: 1px solid blue;
  width: 600px;
}

body {
  padding: 20px;
  font-family: Helvetica;
}

.box {
  background-color: black;
  color: #fff;
  padding: 10px;
  padding-right: 150px;
  font-size: 14px;
}


/*makes desired blocks*/

.wrapper td {
  display: block;
}

.wrapper td:last-child {
  margin-bottom: 10px;
}

/* DEMO UPDATE */

tbody {
  display: flex;
  flex-wrap: wrap;
}

tr {
  margin: 5px 10px 0;
}
<div>

  <table class="wrapper">
    <tr>
      <td class="box a">A1</td>
      <td class="box b">B1</td>
      <td class="box c">C1</td>
      <td class="box d">D1</td>
      <td class="box e">E1</td>
      <td class="box f">F1</td>
    </tr>
    <tr>
      <td class="box a">A2</td>
      <td class="box b">B2</td>
      <td class="box c">C2</td>
      <td class="box d">D2</td>
      <td class="box e">E2</td>
      <td class="box f">F2</td>
    </tr>
    <tr>
      <td class="box a">A3</td>
      <td class="box b">B3</td>
      <td class="box c">C3</td>
      <td class="box d">D3</td>
      <td class="box e">E3</td>
      <td class="box f">F3</td>
    </tr>
    <tr>
      <td class="box a">A4</td>
      <td class="box b">B4</td>
      <td class="box c">C4</td>
      <td class="box d">D4</td>
      <td class="box e">E4</td>
      <td class="box f">F4</td>
    </tr>
  </table>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

ah I see so my issue was the wrong css selector due to the implied tbody, right?
Yes, this is the tricky part of it . If you do not know that browsers generates it, no way to guess ;)
1

I believe the problem that you are running into is that for a grid layout to work, the grid cells need to be direct children of the grid. In a HTML table, the cells are nested inside table rows, which are nested inside the table head/body/foot.

The display: contents property can come to your rescue here. It basically tells the browser to treat an element as if its children existed in its place. By applying it on the thead, tbody, tfoot and all trs of a table, you are effectively making the table cells direct children of the table, causing the grid layout to be applied properly:

.wrapper > thead, .wrapper > thead > tr, .wrapper > tbody, .wrapper > tbody > tr, .wrapper > tfoot, .wrapper > tfoot > tr {
  display: contents;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.