CSS

Responsive and Accessible Data Tables with CSS Grid

Transform traditional HTML tables into modern, responsive, and accessible layouts using CSS Grid, ensuring readability across all device sizes without relying on `display: table` properties.

/* Assumed HTML structure:
<div class="grid-table">
  <!-- Headers -->
  <div class="grid-table-header">Product</div>
  <div class="grid-table-header">Price</div>
  <div class="grid-table-header">Quantity</div>
  <div class="grid-table-header">Total</div>

  <!-- Data Rows -->
  <div class="grid-table-row">
    <div class="grid-table-cell" data-label="Product">Laptop X</div>
    <div class="grid-table-cell" data-label="Price">$1200</div>
    <div class="grid-table-cell" data-label="Quantity">1</div>
    <div class="grid-table-cell" data-label="Total">$1200</div>
  </div>
  <div class="grid-table-row">
    <div class="grid-table-cell" data-label="Product">Mouse Y</div>
    <div class="grid-table-cell" data-label="Price">$25</div>
    <div class="grid-table-cell" data-label="Quantity">2</div>
    <div class="grid-table-cell" data-label="Total">$50</div>
  </div>
</div>
*/

.grid-table {
  display: grid;
  /* Define 4 equal columns for desktop view */
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  border: 1px solid #ccc;
  background-color: #eee; /* Gutter color */
  width: 100%;
  max-width: 900px;
  margin: 20px auto;
}

/* Headers need to span the full grid width in desktop if they are part of the main grid */
/* Or, more cleanly, treat them as the first "row" of the grid */
.grid-table-header {
  padding: 12px 15px;
  background-color: #e9e9e9;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
}

/* Each data row itself is a grid item, then its cells form a subgrid */
.grid-table-row {
    display: contents; /* Makes children of grid-table-row participate directly in grid-table's grid */
}

.grid-table-row > .grid-table-cell {
    padding: 12px 15px;
    background-color: #fff;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
}


/* Media query for responsiveness */
@media (max-width: 768px) {
  .grid-table {
    /* On small screens, hide the desktop headers by not assigning them grid areas */
    grid-template-columns: 1fr; /* Single column layout for the main container */
    gap: 0; /* No gap for the main container */
    border: none;
    background-color: transparent;
  }

  .grid-table-header {
    display: none; /* Hide the main table headers */
  }

  .grid-table-row {
    display: grid; /* Each row becomes its own grid */
    grid-template-columns: 1fr; /* Each row's items stack */
    border: 1px solid #ddd;
    margin-bottom: 15px; /* Space between "rows" */
    background-color: #f9f9f9;
    border-radius: 5px;
  }

  .grid-table-row > .grid-table-cell {
    border-bottom: 1px solid #eee; /* Separator between cells within a row */
    padding-left: 100px; /* Space for the pseudo-element label */
    position: relative;
    text-align: left;
    background-color: transparent; /* Cells use row's background */
    min-height: 40px;
  }

  .grid-table-row > .grid-table-cell:last-child {
    border-bottom: none; /* No separator for the last cell in a row */
  }

  .grid-table-cell::before {
    content: attr(data-label);
    font-weight: bold;
    position: absolute;
    left: 15px;
    top: 50%;
    transform: translateY(-50%);
    width: 80px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #666;
    font-size: 0.9em;
  }
}
How it works: This snippet showcases how to use CSS Grid to create responsive and accessible data tables. On larger screens, the `.grid-table` container defines a `grid-template-columns: repeat(4, 1fr)` to lay out headers and data cells in a traditional table-like structure. Each `.grid-table-row` uses `display: contents` so its children (the `.grid-table-cell`s) participate directly in the main grid. For smaller screens, a media query transforms each `.grid-table-row` into its own `display: grid` with a single column, stacking the cells vertically. The `grid-table-header` elements are hidden, and `data-label` attributes on `grid-table-cell` are used with pseudo-elements (`::before`) to display the corresponding header for each data point, ensuring readability and context on mobile devices.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs