Pure CSS to solve the ceiling and bottom suction in H5 layout implementation steps

Pure CSS to solve the ceiling and bottom suction in H5 layout implementation steps

What products do you want to mention?

Recently, there was a requirement, or more precisely, an iterative requirement: adding a header overview (similar to the picture below) to allow users to better observe marketing changes. The beginning of the story was thus quietly foreshadowed.

Previously, this page was just a list of reviews (which could be pulled up to load). In order to make the data easier to read, the list header adopted a fixed layout. However, when I added this overview, the product didn't mention it, so I simply and roughly changed the column header to a relative layout, ok, and submitted it for testing.

But the next day, I found that there was too much data to load when I pulled up. After the list header was pushed up, if I wanted to filter it again, I had to swipe up the list again to see it. This experience was very bad. So my colleague suggested that we either ask the product or make the overview and overview fixed.

My first reaction was that after I raised this question, the product would probably ask me tomake the filter list header fixed, note the word "only".

Then the following conversation took place:

As expected, whatever you fear will come true. But as my colleague said, I have to accept the request even if it means crying.

After receiving comments and suggestions, the sticky solution was added, which is indeed the optimal solution.

Partial ceiling

The following code is the dom structure of the page

<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 list header</h3>
      <h3>Filterable</h3>
      <h3>Below is the scrolling list</h3>
    </div>
    <ul className="list">
      {arr.map(({ key, label }) => <li key={key}>{label}</li>)}
    </ul>
  </div>
</div>

JS Implementation

Because the page itself has a scroll event listener, my first thought was to complete it with JS, but I had already gotten off work and it was Friday, so I felt that I couldn’t get it done within 5 minutes, so I ran away.

Now let's try to implement it with JS, first sort out the ideas:

  • Monitor the scrolling of the page. When the top of the ul element is greater than the title height from the top of the page, add a CSS class to make the filter header stick to the top.
  • When the distance between the ul element and the top is less than or equal to the title height, delete the added class and cancel the filtering of 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 && e.target.scrollTop >= titleHeight) {
      fixed = true;
      content.classList.add('with-fixed');
    }
    //Cancel the ceilingif (fixed && e.target.scrollTop < titleHeight - 5) {
      content.classList.remove('with-fixed');
      fixed = false;
    }
  });
}, []);

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

CSS Viewport Implementation

JS seems simple, but it’s like that popular sentence:這突如其來的噩耗,讓本不富裕的家庭雪上加霜. In this kind of page with drop-down loading, we have already done a lot of logical processing in the monitor, so if it can be implemented with CSS, try not to bother with JS.

First, sort out your thoughts and dig deep into the needs of the product:

  • Keep the screening head within the visual range (ceiling mounted) to ensure screening;
  • When there is a lot of list data, display as much of the list as possible, that is, the overview header is not necessary;
  • The list is loaded by pulling up;

When we sort out the above ideas, we find that when the list is very long, the overview header is hidden. It can be simply expressed in pseudo code (vh is the viewport unit, 100vh represents the visual height of the entire screen):

 if (titleHeight + filterBarHeight + listHeight > 100vh) {
     title.hide();
   }

So how do you hide the overview header while keeping the filter header and list right out of the viewport?

filterBarHeight + listHeight = 100vh

When the user swipes up, and only the content (filter header and list) is needed to be exactly one viewport height (100vh), the overview header is hidden, and the filter header is just flush with the top. This is achieved using CSS like this:

// Not a complete code, please see 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 setting here is very important overflow: scroll;
     background-color: rgba(127, 255, 212, .8);
   }

Best Implementation of CSS Sticky

There is an uncommonly used position attribute value in CSS: sticky ;

Excerpt from MDN official documentation:

The element is positioned according to the normal document flow, and then offset relative to its nearest scrolling ancestor and nearest block-level ancestor, including table-related elements, based on the values ​​of top, right, bottom, and left. Sticky positioning can be thought of as a hybrid of relative and fixed positioning. Elements are relatively positioned until they cross a certain threshold, after which they become fixed.

Here we make some changes based on the JS solution. We only need to change the positioning property 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}> ), with a visual height of 100vh. When the content exceeds the height, it scrolls. The filter-bar element uses sticky positioning. When the height is greater than 0 from the demo element, it uses relative positioning, that is, positioning in the form of normal document flow. When the height is less than or equal to 0, it uses fixed positioning to achieve the effect of ceiling absorption.

contrast

Do you feel that CSS is very simple and can be done with a little setting? However, it takes some experience (yun) to make sure the content height is exactly 100vh . For those who often write H5, I believe that the sticky solution is also something that novices will come across. In fact, it is not only simple, but also has at least two advantages compared to JS:

  • JS If you just change the filter header positioning to fixed positioning as above, people with good eyesight can actually feel the moment when the list jumps, that is, the list will suddenly move up the filterBar height to fill the filter header leaving the normal document flow; (the solution is to add an extra layer of DOM outside the filter header and give it a fixed height, so that the filter header is out of the normal document flow, but the height is still there);
  • When using JS to manipulate the rearrangement of Dom elements, I won’t say much about the redrawing and reshooting that interviewers talk about every year. The performance consumed is definitely higher than CSS implementation;

Of course, the viewport solution also has a compatibility issue with iOS phones. Since the visibility of Safari's header and bottom will change when sliding, when the Bar is visible, the actual 100vh is higher than the visible height of the screen, which will cause the ceiling header to be blocked. So far, although there are many comments on the Internet about height: -webkit-fill-available; it is ineffective for this scenario; but as long as you rely on 100vh, you will face this dilemma. Safari is too weird, and it will be the next IE.

After the above analysis, the fatal problem of 100vh on IOS Safari will make this pure CSS solution like 100vh fade. But for PC pages, or like you and me, the page you want to write is running in the APP (that is, there is no bar), then this solution is feasible. All plans require specific scenarios and analysis. No one is born perfect. This is just to improve your way of thinking and broaden your horizons.

The sticky solution does not rely on 100vh, it can be written in 100%, so there is no such worry, so in comparison, the best solution is sticky ; but height: 100% is a bottomless pit, you need to start from the html tag and write all the way to the container element with scrolling.

Elastic bottom

After talking about partial elastic ceiling absorption, let's talk about a common one, selective bottom absorption: when the page content is less than 100vh, we hope that Footer is bottom-absorbed. When the page content is greater than 100vh, Footer is in the normal document flow, making the content visible area larger without affecting the appearance due to too little content, as shown in the figure:

There are still many people who do not use positioning like the first picture, because they firmly believe that the content of their website will never be insufficient, but in the past, a more common practice was to use fixed positioning at the bottom.

The elastic bottom uses min-height plus absolute positioning, which is very simple to implement. The core code does not exceed 5 lines of css:

body{
  position: relative;
  min-height: 100vh;
}

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

The principle is that the minimum height of the content area is one screen, and then the bottom is absolutely positioned relative to the screen; when the content becomes more, the height is greater than 100vh, and because it relies on bottom: 0; it will always absorb the bottom, and this is the cleverness.

For this scenario, height: -webkit-fill-available is effective.

This concludes this article about the steps to implement the pure CSS solution to the ceiling and bottom suction problem in the H5 layout. For more relevant CSS ceiling and bottom suction content, please search 123WORDPRESS.COM’s previous articles or continue to browse the related articles below. I hope that everyone will support 123WORDPRESS.COM in the future!

<<:  Several methods to execute sql files under mysql command line

>>:  How to use Web front-end vector icons

Recommend

Vue project realizes login and registration effect

This article example shares the specific code of ...

MySQL series 15 MySQL common configuration and performance stress test

1. Common MySQL configuration All the following c...

Detailed explanation of the implementation of nginx process lock

Table of contents 1. The role of nginx process lo...

Docker time zone issue and data migration issue

Latest solution: -v /usr/share/zoneinfo/Asia/Shan...

Vue uses three methods to refresh the page

When we are writing projects, we often encounter ...

An example of vertical centering of sub-elements in div using Flex layout

1. Flex is the abbreviation of Flexible Box, whic...

How to configure multiple tomcats with Nginx load balancing under Linux

The methods of installing nginx and multiple tomc...

Create a custom system tray indicator for your tasks on Linux

System tray icons are still a magical feature tod...

How to implement Hover drop-down menu with CSS

As usual, today I will talk about a very practica...

Detailed explanation of docker entrypoint file

When writing a Dockerfile, include an entrypoint ...

Summary of Linux date command knowledge points

Usage: date [options]... [+format] or: date [-u|-...

Teach you how to implement the observer mode in Javascript

Table of contents What is the Observer Pattern? S...