What is the best way to implement an AppBar that fades in and out when scrolling within a div?

I'm trying to implement a Scrollable AppBar that hides on scroll down and reappears when scrolling up.

Check out this image for reference

To achieve this functionality, I am following the guidelines provided by Material-UI documentation

export default function HideAppBar(props) {
  return (
    <React.Fragment>
      <div style={{ height: "100px", width: "100px", overflow: "auto" }}>
        {" "}
        External content
      </div>
      <CssBaseline />
      <div style={{ height: "400px", width: "300px", overflow: "auto" }}>
        <HideOnScroll {...props}>
          <AppBar style={{ position: "inherit" }}>
            <Toolbar>
              <Typography variant="h6">Scroll to Hide App Bar</Typography>
            </Toolbar>
          </AppBar>
        </HideOnScroll>

        <Toolbar />
        <Container>
          <Box my={2}>
            {[...new Array(12)]
              .map(
                () => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`
              )
              .join("\n")}
          </Box>
        </Container>
      </div>
    </React.Fragment>
  );

View this demo on CodeSandbox

If you're encountering issues where the AppBar does not show when scrolling up, make sure to scroll all the way back to the top before expecting it to appear again.

Answer №1

The solution to this problem lies in

  • implementing an eventlistener for scrolling within our specified div
  • determining the direction of the scroll (up or down) by comparing the scrollPosition in our state
  • managing the css to display/hide the AppBar accordingly

relevant JavaScript:

import React, { useState, useEffect } from "react";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import CssBaseline from "@material-ui/core/CssBaseline";
import Box from "@material-ui/core/Box";
import Container from "@material-ui/core/Container";

export default function HideAppBar(props) {
  const [scrollPosition, setScrollPosition] = useState(0);
  const [showBar, setShowBar] = useState(false);

  useEffect(() => {
    document
      .getElementById("insideDiv")
      .addEventListener("scroll", handleScroll);
  });

  const handleScroll = event => {
    const newScrollPosition = event.target.scrollTop;
    setScrollPosition(newScrollPosition);
    if (scrollPosition && scrollPosition > newScrollPosition) {
      setShowBar(true);
    } else {
      setShowBar(false);
    }
  };

  return (
    <React.Fragment>
      <div style={{ height: "100px", width: "100px", overflow: "auto" }}>
        {" "}
        External content
      </div>
      <CssBaseline />
      showBar? {showBar.toString()}
      <div
        id="insideDiv"
        style={{ height: "400px", width: "300px", overflow: "auto" }}
      >
        <AppBar
          style={
            showBar
              ? {
                  position: "absolute",
                  top: "120px",
                  width: "280px",
                  left: "0"
                }
              : { position: "inherit" }
          }
        >
          <Toolbar>
            <Typography variant="h6">Scroll to Hide App Bar</Typography>
          </Toolbar>
        </AppBar>

        <Toolbar />
        <Container>
          <Box my={2}>
            {[...new Array(12)]
              .map(
                () => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`
              )
              .join("\n")}
          </Box>
        </Container>
      </div>
      Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus
      ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur
      ac, vestibulum at eros. Praesent commodo cursus magna, vel scelerisque
      nisl consectetur e Cras mattis consectetur purus sit amet fermentum. Cras
      justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus,
      porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus
      magna, vel scelerisque nisl consectetur e Cras mattis consectetur purus
      sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget
      quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
      Praesent commodo cursus magna, vel scelerisque nisl consectetur e Cras
      mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac
      facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac,
      vestibulum at eros. Praesent commodo cursus magna, vel scelerisque nisl
      consectetur e
    </React.Fragment>
  );
}

forked and updated codesandbox here

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

Tips for halting the movement of marquee text once it reaches the center briefly before resuming animation

Is there a way to make text slide in, pause when centered, and then repeat the process? I'm looking for some help with this animation. Here is the code snippet: <marquee direction="left" id="artistslide"> <span id="currentartist">< ...

Creating dynamic routes in express.js with fixed components

I'm exploring how to create a route in express that captures URLs like this: /events/0.json Here's what I've attempted so far (but it's not working as expected): router.put('/events.json/:id.json', isLogged, events.update) ...

Unexpected issues have arisen with the $.ajax function, causing it

I am facing an issue where I can see the loader.gif but unable to view avaiable.png or not_avaiable.png in my PHP file. What could be causing this problem? $(document).ready(function()//When the dom is ready { $("#inputEmail").change(function() { ...

Please input new items by clicking a button

I have a dilemma with handling an array of objects in my Vue component. I am using v-for to display the objects, but now I want to update certain items in the array and save only those changes in a new object. Currently, when I attempt this by mapping over ...

Steps for eliminating an element using jQuery from a variable filled with HTML code

I'm developing a forum where users have the ability to quote other users' comments. When a user clicks on "quote" for a comment, it captures the HTML of that comment and displays it in a box that says Quote: Original post by a member, similar t ...

Instructions for implementing personalized horizontal and vertical scrolling within Angular 9

I am currently working on an angular application where users can upload files, and I display the contents of the file on the user interface. These files may be quite long, so I would need vertical scrolling to navigate through them easily. Additionally, fo ...

After utilizing a while loop with class objects, make sure to reset them afterwards

I am facing a dilemma due to Js referencing objects. Within my Js "class," I have created a new player with various variables, strings, arrays, and functions to check specific conditions related to those variables. As part of my code, I am running a whil ...

The image is not properly aligned with the background image

I'm currently working on a page design using bootstrap and css where I want images to fade and reveal the background when hovered over. The challenge I'm facing is that although all images are set to 100px in size, there is white space visible ar ...

Validating numbers using the Formik and Yup libraries

Hey there, I'm currently facing an issue while using Formik + Yup to validate my form. I am having trouble validating the number for the date, and whenever I try to interact with any field, the app crashes after adding the number field. Can someone pr ...

Utilizing a filter within the ng-model directive

I have a question about using a filter with an h3 element. Here is the code snippet: {{ event.date | date:'dd-MM-yyyy' }} It's working perfectly fine and Angular is formatting the date as expected. However, when I try to use the same filte ...

Issue: The function "generateActiveToken" is not recognized as a function

I encountered an issue in my Node.js project and I'm unsure about the root cause of this error. Within the config folder, there is a file named generateToken.js which contains the following code snippet: const jwt = require('jsonwebtoken'); ...

The resource-intensive nature of ExpressJs HTTP Streaming is causing my disk space to deplete rapidly

My express server app.get('/data', (_, res) => { const interval = setInterval( () => res.write(`${Math.random().toString()}\n`), 1000 ); res.on('close', () => { clearInterval(interval); ...

Changing properties of JavaScript arrays

Currently using Express and dealing with an array of objects that I need to adjust the created property for better presentation, utilizing the dateFormat package. The array originates from a mongo query and is stored in a variable called stories. A sample ...

Developing dynamic forms within arrays using AngularJS

Hey there! I've got a scenario where I have an array of people in my dynamic application. Each person, such as James, Bob, and Walter, has their own set of data that needs to be filled out using simple directives. $scope.users = [ { name: ...

Obtaining NodeJS from a mysterious subdirectory

-- plugins ---- myplugin1 ------ core ---- myplugin2 ------ core If this represents the directory structure, is there a method to import all core directories from plugins without specifying the specific plugin names like myplugin1? require('/plugins ...

typescript: Imported modules in typescript are not functioning

I'm facing an issue where I installed the 'web-request' module but unable to get it working properly. Here is my code: npm install web-request After installation, I imported and used it in my class: import * as WebRequest from 'web-r ...

Styling does not seem to apply to inner components in NEXTJS

I am attempting to create a ChatGPT replica using Next.js and Tailwind CSS. My focus is currently on the main chat screen, where each message is displayed using a separate Message component with its own styling. However, I am facing an issue where the styl ...

Tips for transferring information from one function to another, where the second function acts as an argument within the first function

Can we extract the data from an object map created within a function, such as getData();, and access it in another function called useData(); that is passed as an argument to the original function? const getData = (useData) => { const myData = { ...

React hook issue causing data to not update when submitting the button

Form.jsx ... const initialValues = { name: '', id: '', price: '' } const initialSD = { name: "Test Name", id: "Test ID", price: "Test Price" } const FormComponent = () ...

Player-Oriented Online Game: Addressing Target Accuracy Challenges in ctx.setTransform

I'm currently developing a web game and my goal is to ensure that the player remains at the center of the screen. However, as the player moves further away from the center, the accuracy decreases. I've attempted using ctx.setTransform, which work ...