- let columns = 20;
- let rows = 40;
header
  h1 CSS responsive table
  p
    | ...with fixed column and row headers and scroll snap. - 
    a(href='https://twitter.com/scottjehl/status/1407356545080434697') @scottjehl
main
  .primary(role='region' aria-label='data table' tabindex='0')
    // Note: use the aria-label attribute above to describe this keyboard-focusable region appropriately, per your implementation. Alternatively, it could instead be an aria-labelledby attribute that points to a table caption's ID attribute. Thx for thoughts, @aardrian
    table
      thead
        tr
          th.pin
          - for (var i = 0; i < columns; ++i) {
            th Col Header
          - }
      tbody
        - for (var r = 0; r < rows; ++r) {
          tr
            if r%2
              th Long&nbsp;Row&nbsp;Header
            else
              th
            - for (var i = 0; i < columns; ++i) {
              td Cell Data
            - }
        - }
  aside
    | sidebar
footer
  | Site footer
View Compiled
html,
body {
  height: 100%;
}
body {
  font: 90%/1.4 system-ui;
  margin: 0;
  font-family: sans-serif;
  display: flex;
  flex-direction: column;
}
header {
  display: none;
  padding: 0.5em 5vw;
  border-bottom: 1px solid #ddd;
}
header h1,
header p {
  margin: 0;
}
footer {
  display: none;
  padding: 0.5em 5vw;
  border-top: 1px solid #ddd;
}
aside {
  display: none;
  padding: 7vh 5vw;
}
main {
  min-height: 0;
  -max-width: 100em;
}
.primary {
  overflow: auto;
  scroll-snap-type: both mandatory;
}
@media (min-width: 40em) {
  main {
    display: flex;
  }
  aside {
    flex: 0 1 20vw;
    order: 1;
    border-right: 1px solid #ddd;
  }
  .primary {
    order: 2;
  }
}
table {
  border-collapse: collapse;
  border: 0;
}
th,
td {
  background-clip: padding-box;
  scroll-snap-align: start;
}
td {
  background-color: #fff;
  border: 1px solid #028;
}
tbody tr:last-child th,
tbody tr:last-child td {
  border-bottom: 0;
}
thead {
  z-index: 1000;
  position: relative;
}
th,
td {
  padding: 0.6rem;
  min-width: 6rem;
  text-align: left;
  margin: 0;
}
thead th {
  position: sticky;
  top: 0;
  border-top: 0;
  background-clip: padding-box;
  min-height: 3em;
}
thead th.pin {
  left: 0;
  z-index: 1001;
  border-left: 0;
}
tbody th {
  background-clip: padding-box;
  border-left: 0;
  -opacity: 80%;
}
tbody {
  z-index: 10;
  position: relative;
}
tbody th {
  position: sticky;
  left: 0;
}
th {
  background-color: #aaac;
  -border: 1px solid #000;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.