Implementation steps of pure CSS to solve the ceiling and floor absorption in H5 layout


What products do you want to mention

Recently, we made a demand, to be exact, iterative demand: we added a head overview (similar to the figure below) to better enable users to observe marketing changes. The beginning of the story quietly laid the groundwork.

Previously, this page was just an evaluation list (which can be pulled up and loaded). In order to make the data easier to read, the header of the list adopts a fixed layout. However, when I added this overview, I didn’t mention the product, so I simply and rudely changed the list header to the relative layout, OK, test.

But the next day, I found that there was too much data to be pulled up and loaded. After the list header was pushed up, if I wanted to filter again, I had to slide the list up to see it. This experience was very poor. So colleagues said that they should either ask about the product or make the overview plus overview into a fixed one.

My first reaction was that I was afraid the product would make meonlyFix the header of the filter list and pay attention to that one.

Then there is the following dialogue:

Sure enough, what are you afraid of and what are you coming to. But as my colleagues said, I have to answer my own needs with tears.

After comments and suggestions, sticky’s scheme is added, which is indeed the optimal solution.

Local ceiling

The following code is the of the pagedomstructure

<div id="demo" className={style.demo}>
  < H3 id = "title" classname = "title" > this is an overview header</h3>
  <div id="content" className="content">
    <div className="filter-bar">
      <h3>This is the header of the list</h3>
      <h3>Below is a scrolling list</h3>
    <ul className="list">
      {{ key, label }) => <li key={key}>{label}</li>)}

JS implementation

Because the page itself has scroll event monitoring, the first idea was to use js, but it was off work and it was Friday. I didn’t think I could do it in five minutes, so I ran away.

Now let’s try to implement it with JS. Let’s sort out the ideas first:

  • Listen for page scrolling. When the distance between the top of UL element and the top of the page is greater than the height of title, add a CSS class to make the filter head suck the top;
  • When the UL element is less than or equal to the height of the title from the top, delete the added class and unfilter the top of the head

JS code

useEffect(() => {
  const demo = document.querySelector('#demo');
  const content = document.querySelector('#content');
  const titleHeight = document.querySelector('#title').clientHeight;
  let fixed = false;
  demo.addEventListener('scroll', (e) => {
    //Add ceiling
    if (!fixed && >= titleHeight) {
      fixed = true;
    //Cancel ceiling
    if (fixed && < titleHeight - 5) {
      fixed = false;
}, []);

It doesn’t seem difficult, but in fact, there is still a lot of room for optimization before the code goes online, which will be analyzed and supplemented later.

CSS viewport implementation

JS seems very simple, but it’s like that popular sentence:The sudden bad news made the poor family worse。 In this page with drop-down loading, we have done a lot of logic processing in monitoring, so if we can implement it in CSS, we should try not to bother JS.

First, sort out the ideas and dig deep into the needs of products:

  • Keep the screening head within the visual range (ceiling) to ensure that it can be screened;
  • When there are many list data, display as many lists as possible, that is, there is no need to see the overview header;
  • The list is pulled up and loaded;

When clarifying the above ideas, we find that when the list is very long, the overview header is hidden and simply expressed in pseudo code (VH is the viewport unit, 100vh represents the visual height of the whole screen):

 if (titleHeight + filterBarHeight + listHeight > 100vh) {

So how to hide the overview header, and the filter header and list are just out of the viewport?

filterBarHeight + listHeight = 100vh

When the user swipes up and only needs the content (filter header and list) to be exactly one viewport height (100vh), the overview header is just hidden, and the filter header is just the top. The implementation with CSS is similar to this:

//It is not a complete code. Please see the demo for details:
.demo {
 :global {
   .title {
     height: 15vh;
     line-height: 15vh;
     text-align: center;
     border-bottom: 1PX solid #eee;
     background-color: #fff;
   .filter-bar {
     height: 15vw;
     background-color: #888;
     display: flex;
     align-items: center;
   .list {
     max-height: calc(100vh - 15vw);; //  The settings here are important
     overflow: scroll;
     background-color: rgba(127, 255, 212, .8);

Optimal implementation CSS sticky

Positioning in CSS(position)There is an unusual property value:sticky

Excerpt from MDN official documents:

The element is located according to the normal document flow, and then offset from its nearest scroll ancestor and nearest block level ancestor, including table related elements, based on the values of top, right, bottom, and left. Viscous localization can be considered as a mixture of relative localization and fixed localization. Elements are relatively positioned before crossing a specific threshold, and then fixed.

Here, we change the scheme following JS. We only need to change the positioning attribute of filter bar to sticky positioning to remove the dependence on JS;

.demo {
  max-height: 100%;
  overflow: scroll;
  .filter-bar {
    position: sticky;
    top: 0;

The demo class acts on the outermost dom(<div className={style.demo}>)In, the apparent height is 100vh, and when the content exceeds the height, it is rolling; The filter bar element adopts sticky positioning. When the height distance from the demo element is greater than 0, it adopts relative positioning, that is, it is positioned in the form of normal document flow; When the height is less than or equal to 0, it adopts fixed positioning to achieve the effect of ceiling absorption.


Do you think CSS is very simple, just set it a little, just think that the content height is exactly the same100vhI need a little experience (QI). I often write H5. I believe the sticky scheme is also a novice. In fact, it is not only simple, but also has at least two advantages compared with JS:

  • If JS is just like the above, directly change the positioning of the filter head to fixed positioning. People with good eyesight can actually feel the moment when the list jumps, that is, the list will suddenly move up the height of filterbar to fill the filter head leaving the normal document flow; (the solution is to set a layer of DOM outside the filter header and give it a fixed height, so that the filter header is separated from the normal document flow, but the height is still high);
  • When operating DOM element rearrangement with JS, I won’t say much about the redrawing and remake that the interviewer says every year. The performance consumption is certainly higher than that of CSS implementation;

Of course, there is also a compatibility problem with IOS phones in the viewport scheme. Because the visibility will change when Safari’s head and bottom slide, when the bar is visible, the actual 100vh is higher than the visible height of the screen, which will cause the ceiling head to be blocked. So far, although there are many on the Internetheight: -webkit-fill-available;, but it is invalid for this scenario; But as long as we rely on 100vh, we all face this dilemma. Safari is too wonderful. The next ie is it

According to the above analysis, the fatal problem of 100vh on IOS Safari will fade the pure CSS solution. But the PC page, or the page you want to write, like me, runs in the app (that is, there is no bar), so this scheme is feasible. All plans should be specific scenes and specific analysis. No one is born perfect. Here is just to improve a way of thinking and gain some insight.

The sticky scheme does not depend on 100vh, and it can be written in 100%, so there is no worry, so in contrast, the optimal solution issticky; butheight: 100%It’s a bottomless hole. You need to write from the HTML tag to the container element with scrolling.

Elastic bottom suction

After finishing the local elastic ceiling, let’s say another common, selective ceiling: when the page content is less than 100vh, we want toFooterIt is bottom absorbing. When the page content is greater than 100vh,FooterIn the normal document flow, the visual area of the content is larger without affecting the beauty because of too little content, as shown in the figure:

Like the first picture, there are still many people who do not do positioning, because they firmly believe that the content of their website will not be insufficient, but in the past, the more common practice was to fix positioning at the bottom.

Elastic bottom absorption utilizationmin-heightPlus absolute positioning, the implementation is very simple. No more than 5 lines of core code CSS:

  position: relative;
  min-height: 100vh;

footer {
  width: 100%;
  position: absolute;
  bottom: 0;

The principle is that the minimum height of the content area is a screen, and then the bottom is absolutely positioned relative to the screen; When the content becomes more, the height is greater than 100vh, because it is dependentbottom: 0;Therefore, it will always absorb the bottom, which is the cleverness.

For this scenario,height: -webkit-fill-availableIs effective.

This is the end of this article about the implementation steps of pure CSS to solve the top and bottom suction in H5 layout. For more relevant CSS top and bottom suction content, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!

Recommended Today

Python code reading (Chapter 59): query the dictionary key value according to value

Introduction to Python code reading collection:Why not recommend Python beginners to directly look at the project source code The code read in this article implementsvalueQuery dictionarykeyThe function of. The code snippet read in this article comes from30-seconds-of-python。 find_keys def find_keys(dict, val): return list(key for key, value in dict.items() if value == val) # EXAMPLES ages […]