CSS - ensure that two elements with display: table-row stay stacked on top of one another

I came across this HTML structure

.table {
  display: table;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  text-align: center;
  padding: 5px;
  border-right: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
}

.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
  background: red;
}
<body>
  <div class="table">
    <div class="row">
      <div class="cell sticky"><span>Header Row 1</span>
      </div>
    </div>
    <div class="row">
      <div class="cell sticky"><span>Header Row 2</span>
      </div>
    </div>
    <div class="row">
      <div class="cell">Detail Row 1</div>
    </div>
    <div class="row">
      <div class="cell">Detail Row 2</div>
    </div>
    <div class="row">
      <div class="cell">Detail Row 3</div>
    </div>
  </div>
</body>

It successfully makes the second Header Row sticky, just as intended. However, I am wondering how to make both Header Rows sticky on top of each other. This way, both rows remain visible when the user scrolls the page.

Answer №1

To ensure the second sticky block behaves correctly, it is crucial to set the top property. This value should match the height of the first sticky block. Utilize the pseudo class :nth-child() to target each parent element containing a sticky block.

The height of the initial sticky block is approximately 30px.

Review the provided CSS code for further clarification on this concept.

.table {
  display: table;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  text-align: center;
  padding: 5px;
  border-right: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
}

.sticky {
  position: -webkit-sticky;
  position: sticky;
  background: red;
}

.row:nth-child(1) .sticky {
  top: 0px;
} 

.row:nth-child(2) .sticky {
  top: 30px;
}

Answer №2

Incorporated both headers into a unified sticky row.

.table {
    display: table;
}

.row {
    display: table-row;
}

.cell {
    display: table-cell;
    text-align: center;
    padding: 5px;
    border-right: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
}

.sticky1, .sticky2, sticky {
    position: -webkit-sticky;
    position: sticky;
    top: 0px;
    background: red;
}
<div class="table">
    <div class="row">
        <div class="cell sticky1"><span>Header Row 1</span>
        <div class="cell sticky2"><span>Header Row 2</span>
        </div>
    </div>
    <div class="row">
        </div>
    </div>
    <div class="row">
        <div class="cell">Detail Row 1</div>
    </div>
    <div class="row">
        <div class="cell">Detail Row 2</div>
    </div>
    <div class="row">
        <div class="cell">Detail Row 3</div>
    </div>
    <div class="row">
        <div class="cell">Detail Row 3</div>
    </div>
    <div class="row">
        <div class="cell">Detail Row 3</div>
    </div>

Answer №3

My suggestion is to take a different approach by using a table-based structure rather than a div-based structure.

table {
  text-align: left;
  position: relative;
  border-collapse: collapse; 
}
th, td {
  padding: 0.25rem;
}
tr.red th {
  background: red;
  color: white;
}
tr.green th {
  background: green;
  color: white;
}
tr.purple th {
  background: purple;
  color: white;
}
th {
  background: white;
  position: sticky;
  top: 0; /* Don't forget this, required for the stickiness */
  box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4);
}
<table>
  <thead>
    <tr class="red">
      <th>Header Row 1</th>
      <th>Header Row 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Header Detail 1.</td>
      <td>Header Detail 2.</td>
    </tr>
    <tr>
      <td>Header Detail 1.</td>
      <td>Header Detail 2.</td>
    </tr>
    ... (more table rows)
  </tbody>
</table>

If you still prefer using a DIV structure, here's an example:

.wrap {
  height: 80vh;
  position: relative;
  overflow: scroll;
  margin: 10em auto 20em;
  max-width: 960px;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}

.scenes {
  display: flex;
  flex-wrap: nowrap;
}

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

... (more CSS rules)

@media (max-width: 767px) {
  .track {
    flex: 1 0 calc(50% + 7px);
  }
}
<div class="wrap">
  <div class="scenes">
    <div class="track">
      <div class="heading">Heading 1</div>
      <div class="entry">
        <h3>Lorem ipsum dolor sit amet.</h3>
      </div>
      <div class="entry">
        <h3>Lorem ipsum dolor sit amet consectetur.</h3>
      </div>
      ... (more entries)
    </div>
    ... (more tracks)
  </div>
</div>

Answer №4

In an actual table structure, the use of thead, tbody, or tfoot tags is essential for grouping multiple rows together to maintain their position. To replicate the behavior of a tbody, the table-row-group property in CSS can be utilized :

https://developer.mozilla.org/en-US/docs/Web/CSS/display

table-row-group

table-header-group

table-footer-group

These elements function similarly to HTML elements.

A possible scenario below maintains the layout of the table and focuses on handling groups of rows rather than individual rows :

.table {
  display: table;
}

/*new */
.header-row-group {
  display: table-header-group;
  font-weight:bold;
}
/* end new */
.row {
  display: table-row;
}

.cell {
  display: table-cell;
  text-align: center;
  padding: 5px;
  border-right: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
}

.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
  background: red;
}
<body>
  <div class="table">
    <div class="header-row-group sticky"><!-- header row group added -->
      <div class="row">
        <div class="cell "><span>Header Row 1</span></div> <div class="cell">header Row 1</div>
      </div>
      <div class="row">
        <div class="cell "><span>Header Row 2</span></div> <div class="cell">Wider Cell on  Row 2</div>
      </div>
    </div>
    
    <div class="row">
      <div class="cell">Detail cell</div> 
      <div class="cell">Detail cell</div>
    </div>
    <!-- Additional rows with detail cells -->

  </div>
</body>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Blackberry - Printing HTML String within a text box

My question involves dealing with HTML Strings such as <p>something</p> etc... some other html string etc... <p>something</p> I want to display this formatted string in a field. For Android, I use a WebView... For iPhone, a UIWe ...

Issue with alignment on the printed version of an HTML document

While attempting to print an auto-generated HTML page through my Thermal POS printer, I encountered a large left margin issue. The application is developed using PyQt5, and I had to resort to a python script to generate the HTML code. Unfortunately, in the ...

Extracting information from CSS code

I am struggling to parse a RSS feed because all the information is contained within the description element. The CSS formatting makes it challenging to extract the actual strings. For example, below is a snippet of the description element: <table style ...

Is it possible to examine elements within Outlook?

Creating HTML emails can be quite the challenge, especially when trying to make them compatible with Outlook. Is there a method to inspect elements in Outlook similar to how we do on a browser's console? ...

Ways to ensure your page stays confidential

Concept: Exploring the idea of making specific pages on a website private. For example, having 4 navigation links where one link leads to a private page that requires a username and password for access. Currently, my practice website has 7 links directing ...

Swiper.IO pagination indicators not displaying

Why is the pagination not showing up on the image carousel I created with Swiper? Despite being in the DOM, it has a height of 0 and manual changes have no effect. Any suggestions? import Swiper from '../../vendor/swiper.min.js'; export default ...

What is the way to change the background color using HTML5 getItem?

Here is the code I am currently using: $(this).css('backgroundcolor', localStorage.getItem('bgColorr') + " !important;"); When I execute this: alert( localStorage.getItem('bgColorr') + " !important;"); I receive the correc ...

Issue with displaying elements at intended layering order when parent element has fixed positioning

My web app features both upper and lower elements (div) with a position: fixed. Each element has child popups also with position: fixed. Even though I want to position the popup above its parent element, using z-index doesn't work due to inheritance ...

Display one div and conceal all others

Currently, I am implementing a toggle effect using fadeIn and fadeOut methods upon clicking a button. The JavaScript function I have created for this purpose is as follows: function showHide(divId){ if (document.getElementById(divID).style.display == ...

Is there a way to hide my jQuery menu?

Can anyone help me figure out how to make it close when I click on a link? <nav class="navigation"> <a href="" class="menuIcon"><i class="fa fa-bars"></i></a> <ul class="nav"> <li class="clearfix"&g ...

Learn the method for printing CSS outlines and background colors in IE8 using JQuery's printElement feature

Printing my HTML calendar table in Chrome results in a perfect display. However, when I try to print it in IE8, the background colors and images are not included. Despite following steps from a helpful post on setting it as the default option, there were n ...

The hamburger menu on the navigation bar only functions the first time it is clicked

I've encountered an issue with my hidden menu nav bar. The hamburger and close buttons only work once. Should I organize the events within a function and call it at the end, or perhaps use a loop for the button events? It's worth noting that I d ...

Error: Unable to run 'play' on 'HTMLMediaElement': Invocation not allowed

Just a simple inquiry. I am trying to store an HTMLMediaElement method in a variable. // html segment <video id="player" ... /> // javascript segment const video = document.querySelector('#player') const play = video.play video.play() / ...

Unable to locate a resolution for the error message "Warning: Task "uglify" not found"

Below is the content of my Gruntfile.js: module.exports = function(grunt) { require('load-grunt-tasks')(grunt); grunt.initConfig({ uglify: { start: { files: { 'js/script.min.js': ['js/script.js&a ...

Creating a menu with items and listeners from a kmllayer - a step-by-step guide

Currently, I am working with a map that includes a kmllayer. This layer has been added using the following code: ctaLayer = new google.maps.KmlLayer('http://www.npd.no/engelsk/cwi/pbl/en/aFactGlobe/disc/ActivityStatus_Producing_labels.kml'); ...

Troubleshooting: ReactJS CSS Class Issue

I'm fairly new to working with ReactJS and I've encountered an issue while trying to create a class for a specific form. Below is the code I've written: import React, { Component, PropTypes } from 'react'; import s from './s ...

How to retrieve FormData data using Axios

One challenge I'm facing is with an application that I have developed using VueJS, where users can upload files and send them to the backend. The process involves using Axios to send the file as FormData. However, once the file is received on the back ...

When viewed on mobile devices, the image shrinks significantly

I'm experiencing an issue where the image shrinks significantly when viewed on a mobile device or when zooming in the browser. Can you help me understand why this is happening and suggest a solution? Here are the HTML and CSS code snippets: HTML < ...

Is it possible for me to alter the script for my button's onclick

Is there a way to replicate all properties of a div when creating a clone using JavaScript code? I have an existing script that successfully creates a clone of a div when a button is pressed, but it does not copy the CSS properties. How can I ensure that t ...

Creating unique styles with styled components without the use of selectors

Is it possible to achieve contextual styling without using CSS selectors? For example: <Button primary> <Text>BUTTON</Text> // if the button is primary then have 20px padding else 0 <Icon/> // if the button is primary then ...