How to keep an element fixed at the bottom, even when the keyboard is open

WBOY
Release: 2024-08-10 08:59:33
Original
771 people have browsed it

Hey devs! I discovered this while working on my note-taking app.
Here's a post using my app.
Sharing the progress on X (Twitter)

Have you ever been surprised that CSS isn't working the way you expected?
That happened to me (again) when I set an element to be fixed at the bottom and then opened the keyboard on my iPhone.

<div className="fixed bottom-0" />
Copy after login

What I've seen is that element is not visible at all.
Because it's fixed. To the bottom. Behind the keyboard.

How to keep an element fixed at the bottom, even when the keyboard is open

Seems like to fix the fixed we need some JS.

VisualViewport

There's a browser API with good support that can be used for these purposes: VisualViewport.
It returns the width and height of the actual visible viewport. MDN link to docs.
However, do your own investigation to see if it's supported for the versions you're targeting.

How to keep an element fixed at the bottom, even when the keyboard is open

Math

Basically, we need to handle the position of the element with respect to the visual viewport, as well as the scroll position and the element's height. Let's do the math.

Also, since the math is much simpler this way, it makes sense to use the top parameter instead of the bottom.

top = viewport height + scroll - element height
Copy after login

Implementation

I'll use React. For any other framework, you can just copy the content of the useEffect hook.

import { useEffect, useState } from 'react';
import classNames from 'classnames';
import { useDebounce } from 'use-debounce';

const elementHeight = 55; // elem. height in pixels
// It's also a good idea to calculate it dynamically via ref

export const FixedBlock = () => {
  // top postion -> the most important math result goes here
  const [top, setTop] = useState(0);

  useEffect(() => {
    function resizeHandler() {
      // viewport height
      const viewportHeight = window.visualViewport?.height ?? 0;
      // math
      setTop(viewportHeight + window.scrollY - elementHeight)
    }

    // run first time to initialize 
    resizeHandler();

    // subscribe to events which affect scroll, or viewport position
    window.visualViewport?.addEventListener('resize', resizeHandler);
    window.visualViewport?.addEventListener('scroll', resizeHandler);
    window?.addEventListener('touchmove', resizeHandler);

    // unsubscribe
    return () => {
      window.visualViewport?.removeEventListener('resize', resizeHandler);
      window.visualViewport?.removeEventListener('scroll', resizeHandler);
      window?.removeEventListener('touchmove', resizeHandler);
    };
  }, [debouncedScroll]);

  return (
    <>
      <div
        className={classNames(
          'absolute left-0 top-0', // <-- attention, it's absolute
          top === 0 && 'hidden'    // while calculating, we don't need to show it 
        )}
        style={{ transform: `translateY(${debouncedTop}px)` }}
      >
        I am fixed
      </div>
    </>
  );
};

Copy after login

Final results

I also needed to add some animations and hide my block on scroll, but you don't have to do that, and it will always be visible.

How to keep an element fixed at the bottom, even when the keyboard is open

The above is the detailed content of How to keep an element fixed at the bottom, even when the keyboard is open. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!