Home > Back-end >  Table with horizontal scroll with sticky left column and sticky header on top of screen
Table with horizontal scroll with sticky left column and sticky header on top of screen

Time:01-10

I want to create a table with a horizontal scroll and a sticky left column and a sticky header on top of the screen. The table is wide, so I want to scroll it horizontally, but I need to make the first left column sticky. I also need to make the first row (header) sticky on top of the screen when the page is scrolled down. I don't know if these two options are compatible together. I've tried almost everything. Here is my latest code, which almost works, but the first row is not scrolling with the rest of the table. It could be made of divs or table elements, it doesn't matter.

I want to avoid using JavaScript.

body {
  background: #F5F7FA;
  overflow-x: hidden;
}

.wrap {
  position: relative;
  margin: 10em auto 30em;
  max-width: 960px;
  overscroll-behavior: contain;
}

.headers {
  top: 0;
  position: -webkit-sticky;
  position: sticky;
  z-index: 1;
}

.tracks,
.scroller {
  display: flex;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.scroller {
  overflow-x: hidden;
}

.tracks {
  overflow: auto;
  scroll-snap-type: x mandatory;
}

.scenes::-webkit-scrollbar,
.scroller::-webkit-scrollbar {
  display: none;
}

.track {
  flex: 1 0 calc(22%   2px);
  scroll-snap-align: start;
}

.track.first {
    position: sticky;
    left: 0;
}

.sticky {
  position: sticky;
  top: 0;
}

.track   .track {
  margin-left: -1px;
}

.heading {
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  border: solid #fff;
  border-width: 0 1px;
  z-index: 1;
  background: #efefef;
  font-weight: 700;
}

.entry {
  border: 1px solid #ebebeb;
  border-top: 0;
  background: #fff;
  height: 8em;
  padding: 1em;
}


@media (max-width: 767px) {
  .track {
    flex: 1 0 calc(50%   7px);
  }
}
<div >
  <div >
    
    <div >
      <div >
        <div >Heading 1</div>
      </div>
      <div >
        <div >Heading 2</div>
      </div>
      <div >
        <div >Heading 3</div>
      </div>
      <div >
        <div >Heading 4</div>
      </div>
      <div >
        <div >Heading 5</div>
      </div>
    </div>

  </div>

  <div >

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>
   
  </div>
</div>

enter image description here

Option 1: Header scrolls with the rest of the table. Option 2: Completely different solution with the same result.

CodePudding user response:

This is what it should look like, but without using JavaScript only with pure CSS.

function scrollSynchronization() {
  const wrapper1 = document.querySelector('.scroller');
  const wrapper2 = document.querySelector('.tracks');

  wrapper1.addEventListener('scroll', function() {
    wrapper2.scrollLeft = wrapper1.scrollLeft;
  });

  wrapper2.addEventListener('scroll', function() {
    wrapper1.scrollLeft = wrapper2.scrollLeft;
  });
}

scrollSynchronization();
body {
  background: #F5F7FA;
  overflow-x: hidden;
}

.wrap {
  position: relative;
  margin: 10em auto 30em;
  max-width: 960px;
}

.headers {
  top: 0;
  position: -webkit-sticky;
  position: sticky;
  z-index: 1;
}

.tracks,
.scroller {
  display: flex;
  overflow-y: hidden;
}

.scroller {
  overflow-x: scroll;
}

.tracks {
  overflow: auto;
}

.scenes::-webkit-scrollbar,
.scroller::-webkit-scrollbar {
  display: none;
}

.track {
  flex: 1 0 calc(22%   2px);
}

.track.first {
    position: sticky;
    left: 0;
}

.sticky {
  position: sticky;
  top: 0;
}

.track   .track {
  margin-left: -1px;
}

.heading {
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  border: solid #fff;
  border-width: 0 1px;
  z-index: 1;
  background: #efefef;
  font-weight: 700;
}

.entry {
  border: 1px solid #ebebeb;
  border-top: 0;
  background: #fff;
  height: 8em;
  padding: 1em;
}


@media (max-width: 767px) {
  .track {
    flex: 1 0 calc(50%   7px);
  }
}
<div >
  <div >

    <div >
      <div >
        <div >Heading 1</div>
      </div>
      <div >
        <div >Heading 2</div>
      </div>
      <div >
        <div >Heading 3</div>
      </div>
      <div >
        <div >Heading 4</div>
      </div>
      <div >
        <div >Heading 5</div>
      </div>
    </div>

  </div>

  <div >

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>

    <div >
      <div >
        <h3>Lorem, ipsum dolor.</h3>
      </div>
      <div >
        <h3>Lorem, ipsum.</h3>
      </div>
    </div>
   
  </div>
</div>

CodePudding user response:

Yup, you can do this without JavaScript.

* {
   padding: 0;
   margin: 0;
}
main {
   padding: 10px;
}
#Products {
   width: 100%;
   min-width: 900px;
   border-spacing: 0;
}
#Products th:first-child,
#Products td:first-child {
   position: sticky;
   left: 10px;
   z-index: 2;
}
#Products th,
#Products td {
   border-right: 1px solid black;
   border-bottom: 1px solid black;
   background-color: white;
   width: 25%;
   padding: 7px;
}
#Products th {
   background-color: #555;
   color: white;
   position: sticky;
   top: 0;
   z-index: 1;
}
#Products th:last-child,
#Products td:last-child {
   border-right: none;
}
#Products .Heading td {
   border-right: none;
}
<html>
<body>
<main>
  <table id="Products">
     <tr>
        <th></th>
        <th>Product 1</th>
        <th>Product 2</th>
        <th>Product 3</th>
     </tr>
     <tr >
        <td>
           <h3>Battery</h3>
        </td>
        <td></td>
        <td></td>
        <td></td>
     </tr>
     <tbody>
        <tr>
           <td>Charging Cable Length</td>
           <td>7.87&quot; / 19.99 cm</td>
           <td>7.87&quot; / 19.99 cm</td>
           <td>7.87&quot; / 19.99 cm</td>
        </tr>
        <tr>
           <td>Charging Port</td>
           <td>USB Type-C</td>
           <td>USB Type-C</td>
           <td>USB Type-C</td>
        </tr>
        <tr>
           <td>DC Input Power</td>
           <td>5 VDC</td>
           <td>5 VDC</td>
           <td>5 VDC</td>
        </tr>
        <tr>
           <td>Quick Charging Times</td>
           <td>10 Minutes for 5 Hours</td>
           <td>10 Minutes for 5 Hours</td>
           <td>10 Minutes for 5 Hours</td>
        </tr>
        <tr>
           <td>Recharge Time</td>
           <td>3 Hours</td>
           <td>3 Hours</td>
           <td>3 Hours</td>
        </tr>
        <tr>
           <td>Runtime</td>
           <td>30 Hours (BT ANC) 38 Hours (BT) 200 Hours (Standby)</td>
           <td>30 Hours (BT ANC) 38 Hours (BT) 200 Hours (Standby)</td>
           <td>30 Hours (BT ANC) 38 Hours (BT) 200 Hours (Standby)</td>
        </tr>
        <tr>
           <td>Wireless Charging</td>
           <td>None</td>
           <td>None</td>
           <td>None</td>
        </tr>
     </tbody>
     <tr >
        <td>
           <h3>Headphone</h3>
        </td>
        <td></td>
        <td></td>
        <td></td>
     </tr>
     <tbody>
        <tr>
           <td>Active Noise Cancellation</td>
           <td>Yes</td>
           <td>Yes</td>
           <td>Yes</td>
        </tr>
        <tr>
           <td>Controls/Microphone Location</td>
           <td>Controls: Earpiece (Side Unspecified) Microphone: Earpiece (Side Unspecified)</td>
           <td>Controls: Earpiece (Side Unspecified) Microphone: Earpiece (Side Unspecified)</td>
           <td>Controls: Earpiece (Side Unspecified) Microphone: Earpiece (Side Unspecified)</td>
        </tr>
        <tr>
           <td>Diaphragm</td>
           <td>Aluminum-Coated</td>
           <td>Aluminum-Coated</td>
           <td>Aluminum-Coated</td>
        </tr>
        <tr>
           <td>Driver Size</td>
           <td>1.57&quot; / 40 mm</td>
           <td>1.57&quot; / 40 mm</td>
           <td>1.57&quot; / 40 mm</td>
        </tr>
        <tr>
           <td>Driver Type</td>
           <td>Dynamic</td>
           <td>Dynamic</td>
           <td>Dynamic</td>
        </tr>
        <tr>
           <td>Earpiece Connection / Wearing Style</td>
           <td>Headband</td>
           <td>Headband</td>
           <td>Headband</td>
        </tr>
        <tr>
           <td>Earpiece Design</td>
           <td>Over-Ear (Circumaural), Closed-Back</td>
           <td>Over-Ear (Circumaural), Closed-Back</td>
           <td>Over-Ear (Circumaural), Closed-Back</td>
        </tr>
        <tr>
           <td>Earpiece Swivel</td>
           <td>Yes</td>
           <td>Yes</td>
           <td>Yes</td>
        </tr>
        <tr>
           <td>Foldable</td>
           <td>Yes</td>
           <td>Yes</td>
           <td>Yes</td>
        </tr>
        <tr>
           <td>Full Remote OS Support</td>
           <td>Android, iOS</td>
           <td>Android, iOS</td>
           <td>Android, iOS</td>
        </tr>
        <tr>
           <td>Magnet Type</td>
           <td>Neodymium</td>
           <td>Neodymium</td>
           <td>Neodymium</td>
        </tr>
        <tr>
           <td>Number of Drivers</td>
           <td>1, per Earpiece</td>
           <td>1, per Earpiece</td>
           <td>1, per Earpiece</td>
        </tr>
        <tr>
           <td>Sensors</td>
           <td>Proximity, Touch</td>
           <td>Proximity, Touch</td>
           <td>Proximity, Touch</td>
        </tr>
        <tr>
           <td>Voice Coil</td>
           <td>Copper-Clad Aluminum Wire</td>
           <td>Copper-Clad Aluminum Wire</td>
           <td>Copper-Clad Aluminum Wire</td>
        </tr>
     </tbody>
     <tr >
        <td>
           <h3>Microphone</h3>
        </td>
        <td></td>
        <td></td>
        <td></td>
     </tr>
     <tbody>
        <tr>
           <td>Beamforming Support</td>
           <td>No</td>
           <td>No</td>
           <td>No</td>
        </tr>
        <tr>
           <td>Noise Canceling</td>
           <td>Not Specified by Manufacturer</td>
           <td>Not Specified by Manufacturer</td>
           <td>Not Specified by Manufacturer</td>
        </tr>
        <tr>
           <td>Number of Mics</td>
           <td>5</td>
           <td>5</td>
           <td>5</td>
        </tr>
        <tr>
           <td>Type</td>
           <td>MEMS</td>
           <td>MEMS</td>
           <td>MEMS</td>
        </tr>
     </tbody>
     <tr >
        <td>
           <h3>Performance</h3>
        </td>
        <td></td>
        <td></td>
        <td></td>
     </tr>
     <tbody>
        <tr>
           <td>Frequency Response</td>
           <td>4 Hz to 40 kHz (Wired)</td>
           <td>4 Hz to 40 kHz (Wired)</td>
           <td>4 Hz to 40 kHz (Wired)</td>
        </tr>
        <tr>
           <td>Sensitivity</td>
           <td>101 dB at 1 kHz (Passive) 105 dB at 1 kHz (Active)</td>
           <td>101 dB at 1 kHz (Passive) 105 dB at 1 kHz (Active)</td>
           <td>101 dB at 1 kHz (Passive) 105 dB at 1 kHz (Active)</td>
        </tr>
        <tr>
           <td>Storage Capacity</td>
           <td>None</td>
           <td>None</td>
           <td>None</td>
        </tr>
     </tbody>
  </table>
 </main>
 </body>
 </html>

  • Related