Styling a Fixed Header in CSS/HTML - Scroll Effect

Is it possible to hide only the upper part of the nav-bar, similar to the behavior in WhatsApp? I am using material-ui for this particular use-case. Currently, my implementation causes the app-bar to extend only when the scroll position is less than 48px, unlike the behavior shown in the .gif below where it extends on every scroll up event. It seems like the app-bar scrolls first until it reaches a fixed position, after which the rest of the content begins to scroll.

Edit

I tried implementing a proof-of-concept but it doesn't work as expected: stackblitz

This is how my approach looks:

export default function TabBar() {
  const [value, setValue] = React.useState(0);
  const [yOffset, setYOffset] = React.useState(0);

  function handleChange(event: React.ChangeEvent<{}>, newValue: number) {
    setValue(newValue);
  }

  function transitionY() {
    const transitionYthreshold = 48;
    return Math.min(transitionYthreshold, yOffset);
  }

  useEffect(() => {
    window.addEventListener('scroll', handleScroll, { passive: true });
    return () => window.removeEventListener('scroll', handleScroll);
  });

  function handleScroll() {
    setYOffset(window.pageYOffset);
  }

  return (
    <React.Fragment>
      <AppBar
        position="sticky"
        color="default"
        style={{
          transition: 'all 0.1s',
          transform: `translateY(-${transitionY()}px)`
        }}
      >
        <Toolbar style={{ minHeight: '48px' }}>
          <div style={{ width: '30px', marginRight: '1em' }} />
          <span style={{ fontWeight: 'bold', fontSize: '20px', verticalAlign: 'super' }}>Help-Educate</span>
        </Toolbar>
        <Tabs
          value={value}
          onChange={handleChange}
          indicatorColor="primary"
          textColor="primary"
          variant="fullWidth"
        >
          <Tab label="Home"  {...a11yProps(0)}/>
          <Tab label="Donations"  {...a11yProps(1)}/>
          <Tab label="About Us"  {...a11yProps(2)}/>
        </Tabs>
      </AppBar>
      <TabPanel value={value} index={0}>
        <Container>
          {**SomeSuperLongText**}
        </Container>
      </TabPanel>
      <TabPanel value={value} index={1}>
         {**SomeSuperLongText**}
      </TabPanel>
      <TabPanel value={value} index={2}>
         {**SomeSuperLongText**}
      </TabPanel>
    </React.Fragment>
  );
}

A gif showcasing the desired behavior can be found here: dropbox-link

https://i.stack.imgur.com/YFjIA.png

Answer №1

Although it may not be the most elegant solution, I managed to come up with a workaround after experimenting:

import React from "react";
import PropTypes from "prop-types";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
Typography from "@material-ui/core/Typography";
import CssBaseline from "@material-ui/core/CssBaseline";
import useScrollTrigger from "@material-ui/core/useScrollTrigger";
import Box from "@material-ui/core/Box";
import Container from "@material-ui/core/Container";
import Slide from "@material-ui/core/Slide";

function HideOnScroll(props) {
const { children } = props;
const trigger = useScrollTrigger({
threshold: 0
});

return (
<Slide appear={false} direction="down" in={!trigger}>
{children}
</Slide>
);
}

HideOnScroll.propTypes = {
children: PropTypes.element.isRequired
};

export default function HideAppBar(props) {
return (
<React.Fragment>
<CssBaseline />
<HideOnScroll {...props}>
<AppBar>
<Toolbar>
<Typography variant="h6">Scroll to Hide App Bar</Typography>
</Toolbar>
</AppBar>
</HideOnScroll>
<Toolbar />
<AppBar position="sticky">
<Toolbar>
<Typography variant="h6">Bar will stay</Typography>
</Toolbar>
</AppBar>
<Container>
<Box my={2}>
{[...new Array(20)]
.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>
</React.Fragment>
);
}

--> You can add another sticky app bar within the content container and adjust the useScrollTrigger with threshold option accordingly.

Check it out here: https://codesandbox.io/s/serverless-cache-rcxen

Answer №2

Check out my unique solution here: https://stackblitz.com/edit/react-ts-opelwo

In this code snippet, I have created a Container with a scrollable text area. You can adjust the visibility of scrollbars using CSS.

<Container
          style={{
          top:48,
          paddingTop:48,
          bottom: - 48,
          scrollTop: yOffset - transitionY(),
          pointerEvents: transitionY()<48?"none":"auto"
        }} className="cont" onScroll={handleInsideScroll}>

The key is to control the pointer-events property for the container to either enable or disable scrolling functionality based on user interaction. This approach utilizes CSS instead of JS for smoother and more optimized results.

There are a couple of issues: - After switching pointer-events, you may need to move your mouse slightly to resume scrolling (this could potentially be resolved by directly modifying containerRef.style.pointerEvents rather than updating states). - The script does not handle scrolling up exactly like in the gif animation provided, requiring additional logic to detect upward scrolling behavior.

As a TypeScript beginner, I couldn't explore all possibilities, but I find CSS solutions preferable for their efficiency and fluidity over JavaScript alternatives.

Answer №3

I checked out the whatsapp navbar and I see what you're looking for.

One way to achieve this effect is by using window.pageYOffset to adjust the style.top of the navbar within the window.onscroll function.

You can find a working example on the w3schools website that demonstrates this exact behavior.

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

How come my flex-box navigation bar is not collapsing as I shrink the browser window size?

I'm currently experimenting with FlexBox to enhance the design of my website, specifically focusing on creating a responsive and collapsible navigation bar for mobile users. I'm encountering issues with the flex commands in the .nbar class not wo ...

Testing React Component State Updates

I've been dedicated to achieving close to 100% unit test coverage with my React application, focusing particularly on the useAsync hook. I came across a code snippet from react hooks: import { useState, useEffect, useCallback } from 'react'; ...

When HTML elements are dynamically inserted through JavaScript using quilljs, they may cause conflicts with the layout properties

I am currently working on creating a simple webpage layout similar to that of Stack Overflow, with a sidebar and a main content area that can scroll. In my case, the content area is intended to host a QuillJS text editor. To integrate the QuillJS editor i ...

Find the div element that wraps around the currently selected radio button

Take a look at this code snippet: <div class="paymentOption"> <input type="radio" name="paymentOption" value="1" /> <span class="marginLeft10">1-time payment using a different credit card</span> </div> Is it feasible ...

Setting up a React App deployment with Nginx Reverse Proxy using Docker Compose

I have a Docker Compose project with multiple services (two APIs, database, and more). To expose the APIs over the network, I set up an Nginx container as a reverse proxy. In addition, I need to make a Web App developed in React accessible. This app gener ...

Issues with Internet Explorer causing headaches with CSS :first-child selector malfunctioning, experiencing strange behavior when utilizing Google Web Fonts

Having some trouble with the layout of a website, particularly in IE. The issue can be observed at . When comparing the page in IE to Firefox, there are noticeable differences. Firstly, the top module on the right side is not displaying correctly in IE. I ...

React Hook Form not refreshing form inputs

Despite successfully submitting the form, saving the data to state, and persisting it in local storage, I am facing an issue where updating a form field's value does not reflect the changes. It seems that when trying to modify a form field that is po ...

Obtain a collection of strings from an array of objects based on specified criteria

What is the most efficient method to extract an array of specific strings from an array of objects, where a certain condition needs to be met? Solution Attempt: const array = [{ "Item": "A", "Quantity": 2 ...

Having trouble getting the @tailwindcss/forms plugin to function properly alongside React

After installing the tailwindcss plugin forms using npm with npm install @tailwindcss/forms, I added the dependency in the forms section of my tailwindconfig file by including plugins: [ require("@tailwindcss/forms") ]. As per the documentation ...

Problem with rendering React Router v4 ConnectedRouter on nested routes

The routes for the first level are correctly displayed from Layout.tsx, but when clicked on ResourcesUI.tsx, the content is not rendered as expected (see code below). The ResourceUI component consists of 2 sections. The left section contains links, and th ...

Pressing the reset button will restore the table to its original

As a new React developer with experience mainly in hooks, I have been struggling to find a good example involving hooks. Currently, I am working on implementing an antd table with search functionality. My question is, when a user types something into the ...

Managing User Roles in a Front-end React JS MERN Application

In my MERN APP (MongoDB, Express, ReactJS, NodeJS), I handle the logged user on the backend using tokens to grant access based on their role. Now, the question arises: How can I control the user's role on the front-end (ReactJS) to distinguish betwee ...

Save property using the useState hook

I am working on implementing a sorting function in the child component, where the props are passed in from the parent through an axios call. Should I: Store the prop in the child component's useState? Pass the parent's setState function as a pro ...

The concept of an HTML pop-up message that hovers above the content

While working on my HTML form, I encountered an issue regarding the display of a warning message notifying users about the caps lock being on. Currently, the warning is shown correctly in a div located to the right of the text box. However, this div's ...

Implement CSS to layer HTML 5 canvases while including a margin

I have a design conundrum in my app where I am using multiple stacked HTML canvas elements for drawing. My goal is to make the canvases fit perfectly within their containing div while also maintaining a left and bottom margin. This is how my HTML structur ...

Utilize a class method within the .map function in ReactJS

In my ReactJS file below: import React, { Component } from "react"; import Topic from "./Topic"; import $ from "jquery"; import { library } from '@fortawesome/fontawesome-svg-core' import { FontAwesomeIcon } from '@fortawesome/react-fontaw ...

The frontend forgets a user's logged-in status when the page is refreshed

Utilizing express, mongodb, redis, and mongoose as the backend for API services. On the front end, I employ react, react-router, and redux. Authentication is handled using sessionId along with cookie. For frontend authentication control, I utilize react ...

What is the best way to apply typography theme defaults to standard tags using Material-UI?

After reading the documentation on https://material-ui.com/style/typography/ and loading the Roboto font, I expected a simple component like this: const theme = createMuiTheme(); const App = () => { return ( <MuiThemeProvider theme={theme}> ...

Using React, retrieving the value of a checked radio button from the state

My issue involves a list of radio buttons generated from a map loop containing numbers like 1, 2, and 3. When I select a radio button, it should set a state: <ul className="flex gap-6 justify-center"> {maxPaxArr.map((keypax) => ...

"Utilizing the react-router onEnter hook to establish a connection with the redux store - here's

I'm attempting to utilize the onEnter hook in react-router to validate a variable in my redux store when navigating to a new route. As per the documentation, the onEnter function: ...receives the next router state as its first argument. The replac ...