2

I'm trying to create a table with CSS grid. So far I created a simple outline.

I have to create the grids at the row level (due to the fact that IRL the tables have more elements and I cannot make them at the table level). So far this works unless there is a very long word (or number), as in that case it overflows the containing cell.

My question is: is it possible to make the table overflow in order to make the cells at least as big as the biggest single word or number? (without making them break—at least the numbers)

Thanks in advance!

Edit: I need to create a table with CSS grid as I need to use the same layout for the mobile version

Edit2: I don't know in advance how many elements I will have in the rows/columns, so I need to make use of repeat

Edit3: I'm looking for a pure CSS solution.

.table {
  margin: 48px 0;
  box-shadow: 0 5px 10px -2px #cfcfcf;
  font-family: Arial;
}

.row {
  display: grid;
  grid-template-columns: repeat( auto-fit, minmax(72px, 1fr) );
  min-height: 48px;
  border-bottom: 1px solid #f1f1f1;
}

.column {
  display: flex;
  width: 100%;
  height: 100%;
  border: 1px solid #f1f1f1;
  align-items: center;
  
}

.row:first-child {
  font-weight: bold;
}
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <div class="table">
      <div class="row">
        <div class="column">Name</div>
        <div class="column">Age</div>
        <div class="column">Favourite Book</div>
        <div class="column">Favourite Color</div>
        <div class="column">Favourite Meal</div>
      </div>
      <div class="row">
        <div class="column">Jimmy</div>
        <div class="column">23</div>
        <div class="column">None</div>
        <div class="column">White</div>
        <div class="column">Paella de Chorizo</div>
      </div>
      <div class="row">
        <div class="column">Johny</div>
        <div class="column">56</div>
        <div class="column">Finnegans Wake</div>
        <div class="column">Purple, Magenta and Violet</div>
        <div class="column">None</div>
      </div>
      <div class="row">
        <div class="column">Robert The Snake Robertson</div>
        <div class="column">1.234.567.890.000.000</div>
        <div class="column">The Count of Monte Cristo</div>
        <div class="column">Orange</div>
        <div class="column">Apples</div>
      </div>
    </div>
        
    
  </body>

</html>
Joe82
  • 1,357
  • 2
  • 24
  • 40
  • 1
    So dumb question, but if its a *table* displaying what looks like *tabular data*, why not use an HTML ``?
    – Bryce Howitson Sep 24 '19 at 15:34
  • Hi Bryce, the problem is that I want to use this same layout for the responsive/mobile version. And with CSS grid it is fairly simple to do that with a few lines of CSS, but with an old and grumpy html table that would be very hard to achieve at all. – Joe82 Sep 24 '19 at 15:35
  • 3
    Totally understand. Just thought I'd save you from reinventing the wheel (er table) if I could :-) – Bryce Howitson Sep 24 '19 at 15:40
  • Responsive tables are kind of a gray area, as there are not very optimal solutions and/or best practices. Best approach I found is this https://www.freecodecamp.org/news/https-medium-com-nakayama-shingo-creating-responsive-tables-with-pure-css-using-the-grid-layout-module-8e0ea8f03e83/ There is also more alternatives discussed here https://medium.com/appnroll-publication/5-practical-solutions-to-make-responsive-data-tables-ff031c48b122 – Joe82 Sep 25 '19 at 06:53

4 Answers4

3

You want a table layout, then use table and not grid:

.table {
  margin: 48px 0;
  box-shadow: 0 5px 10px -2px #cfcfcf;
  font-family: Arial;
  display:table;
  width:100%;
}

.row {
  display: table-row;
  min-height: 48px;
  border-bottom: 1px solid #f1f1f1;
}

.column {
  display: table-cell;
  border: 1px solid #f1f1f1;
  vertical-align: middle;
  padding:10px 0;
}


.row:first-child {
  font-weight: bold;
}
<div class="table">
      <div class="row">
        <div class="column">Name</div>
        <div class="column">Age</div>
        <div class="column">Favourite Book</div>
        <div class="column">Favourite Color</div>
        <div class="column">Favourite Meal</div>
      </div>
      <div class="row">
        <div class="column">Jimmy</div>
        <div class="column">23</div>
        <div class="column">None</div>
        <div class="column">White</div>
        <div class="column">Paella de Chorizo</div>
      </div>
      <div class="row">
        <div class="column">Johny</div>
        <div class="column">56</div>
        <div class="column">Finnegans Wake</div>
        <div class="column">Purple, Magenta and Violet</div>
        <div class="column">None</div>
      </div>
      <div class="row">
        <div class="column">Robert The Snake Robertson</div>
        <div class="column">1.234.567.890.000.000</div>
        <div class="column">The Count of Monte Cristo</div>
        <div class="column">Orange</div>
        <div class="column">Apples</div>
      </div>
    </div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Hi Temaini, I need to create a table with CSS grid as I need to use the same layout for the mobile (responsive) version in a way that is not possible to achieve with display:table – Joe82 Oct 16 '19 at 08:02
  • @Joe82 and what is this *way*? actually the code I provided is given the same output as your code + the requirement you want. How you will manage the responsive later? – Temani Afif Oct 16 '19 at 08:04
  • Using what is described here https://www.freecodecamp.org/news/https-medium-com-nakayama-shingo-creating-responsive-tables-with-pure-css-using-the-grid-layout-module-8e0ea8f03e83/ (not the wrapping, but the card layout). Take in account as well that my real tables are much "wider"—they have lots of columns. – Joe82 Oct 16 '19 at 08:07
  • 1
    @Joe82 as you can see in that code, they are using media query to switch the layout so my code still work fine. You keep display:table for big screen and you switch to display:grid for small screen both are independant. You don't need to exactly follow that tutorial, you simply need to understand the trick – Temani Afif Oct 16 '19 at 08:11
  • True that, I was not thinking about making it that way. I will mark it as correct. – Joe82 Oct 16 '19 at 08:17
1

Well you can use CSS fit-content(max-width) (docs) but I don't know if it can be used in conjunction with grid repeat().

.row {
  display: grid;
  grid-template-columns: auto, fit-content(300px), fit-content(100px), auto, auto;
  min-height: 48px;
  border-bottom: 1px solid #f1f1f1;
}

Edit: Inside a repeat(), you can use the max-content keyword.

grid-template-columns: repeat(auto-fit, minmax(auto, max-content));

You might need to add your own wrapping rules for some cells though.

Bryce Howitson
  • 7,339
  • 18
  • 40
  • Thanks for the insight, but I forgot to add that it is an unknown number of columns (so I need to make use of repeat). – Joe82 Sep 24 '19 at 15:54
  • Perhaps `max-content` then? – Bryce Howitson Sep 24 '19 at 15:59
  • It seems like you cannot use `auto-fit` and `max-content` altogether (check here https://stackoverflow.com/questions/52764726/css-grid-auto-fit-with-max-content ). I've added a plunkr with the modified code here https://plnkr.co/edit/ZaIa8U9tdQydK9UOwN7N – Joe82 Sep 24 '19 at 16:05
  • 1
    This isn't helpful, but I haven't found anything that lets you have both content-based widths and an unknown number of columns... Are you expecting to get a bunch of long non-breaking strings in your final layout? – Bryce Howitson Sep 24 '19 at 17:19
  • Yep, as it is full of numbers, and if many of the figures are large, there is overflow. – Joe82 Sep 25 '19 at 06:39
1

You're using a mix of grid and flexbox. Try with just grid:

Updated to set the repeat style inline (since the amount of columns may change)

.grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);/* overridden inline */
  border-top: 1px solid black;
  border-right: 1px solid black;
}

.grid>div {
  padding: 8px 4px;
  border-left: 1px solid black;
  border-bottom: 1px solid black;
}

.grid>div.th {
  font-weight: bold;
}
<div class="grid" style="grid-template-columns: repeat(5,1fr);">
  <div class="th">Name</div>
  <div class="th">Age</div>
  <div class="th">Favourite Book</div>
  <div class="th">Favourite Color</div>
  <div class="th">Favourite Meal</div>

  <div>Jimmy</div>
  <div>23</div>
  <div>None</div>
  <div>White</div>
  <div>Paella de Chorizo</div>

  <div>Johny</div>
  <div>56</div>
  <div>Finnegans Wake</div>
  <div>Purple, Magenta and Violet</div>
  <div>None</div>

  <div>Robert The Snake Robertson</div>
  <div>1.234.567.890.000.000</div>
  <div>The Count of Monte Cristo</div>
  <div>Orange</div>
  <div>Apples</div>

</div>
Moob
  • 14,420
  • 1
  • 34
  • 47
  • Thanks for your answer. Sorry I didn't clarify it before, but I have an unknown number of rows/columns, so I need to make use of repeat but I cannot specify a fixed number of columns. – Joe82 Sep 24 '19 at 15:57
  • 1
    @joe82 You must know how many columns there are at _some point_. For example, when rendering the 'data' you can set the `grid-template-columns: repeat([someNumber],1fr)` as inline style. (I've updated my answer accordingly.) – Moob Sep 24 '19 at 16:37
  • That could be an approach. The downside is that I would have to set that number kind of manually in each table, which makes it less maintainable than a pure CSS solution. I will wait if there is a pure CSS solution, else will mark this as correct. – Joe82 Sep 25 '19 at 06:49
1

Only add word-break: break-word; property in column class

    .table {
      margin: 48px 0;
      box-shadow: 0 5px 10px -2px #cfcfcf;
      font-family: Arial;
    }

    .row {
      display: grid;
      grid-template-columns: repeat( auto-fit, minmax(72px, 1fr) );
      min-height: 48px;
      border-bottom: 1px solid #f1f1f1;
    }

    .column {
    display: flex;
    width: 100%;
    height: 100%;
    border: 1px solid #f1f1f1;
    align-items: center;
    word-break: break-word;
    }
    .row:first-child {
      font-weight: bold;
    }
    <!DOCTYPE html>
    <html>

      <head>
        <link rel="stylesheet" href="style.css">
      </head>

      <body>
        <div class="table">
          <div class="row">
            <div class="column">Name</div>
            <div class="column">Age</div>
            <div class="column">Favourite Book</div>
            <div class="column">Favourite Color</div>
            <div class="column">Favourite Meal</div>
          </div>
          <div class="row">
            <div class="column">Jimmy</div>
            <div class="column">23</div>
            <div class="column">None</div>
            <div class="column">White</div>
            <div class="column">Paella de Chorizo</div>
          </div>
          <div class="row">
            <div class="column">Johny</div>
            <div class="column">56</div>
            <div class="column">Finnegans Wake</div>
            <div class="column">Purple, Magenta and Violet</div>
            <div class="column">None</div>
          </div>
          <div class="row">
            <div class="column">Robert The Snake Robertson</div>
            <div class="column">1.234.567.890.000.000</div>
            <div class="column">The Count of Monte Cristo</div>
            <div class="column">Orange</div>
            <div class="column">Apples</div>
          </div>
        </div>
            
        
      </body>

    </html>
Syed Taha
  • 9
  • 2
  • Hi @Syed, thanks for the input. That is something I have as last resort, as I would prefer the table to overflow with scroll and being able to see the numbers in a single row (as it is easier to compare figures). – Joe82 Sep 25 '19 at 07:26