如何在React/Next.js中结合Tailwind CSS实现类似谷歌搜索的粘性Header(滚动时仅显示顶部搜索栏)
Solution for Sticky Header with Scroll Behavior (Google Search Clone)
Got it, let's replicate that Google-style sticky header where the category bar hides when you scroll down. Here's a tailored implementation for your existing component:
Step 1: Add Scroll Tracking Logic
First, we'll add state to track scroll position and use useEffect to listen for window scroll events. This lets us detect when the user has scrolled past a certain point.
Step 2: Adjust Styling & Visibility
We'll tweak the header's padding and shadow based on scroll state, and conditionally hide the category bar once the user scrolls down.
Modified Component Code
import React, { useRef, useState, useEffect } from 'react'; import Image from 'next/image'; import { useRouter } from 'next/router'; import { MicrophoneIcon, SearchIcon, XIcon, CogIcon, ViewGridIcon } from '@heroicons/react/solid'; function Header() { const router = useRouter(); const searchInputRef = useRef(null); const [value, setValue] = useState(''); // Track if user has scrolled past the top const [isScrolled, setIsScrolled] = useState(false); useEffect(() => { const handleScroll = () => { // Toggle state when scroll exceeds 30px (adjust threshold as needed) setIsScrolled(window.scrollY > 30); }; // Attach scroll listener window.addEventListener('scroll', handleScroll); // Cleanup listener when component unmounts return () => window.removeEventListener('scroll', handleScroll); }, []); const search = (e) => { e.preventDefault(); const term = searchInputRef.current.value; if (!term) return; router.push(`/search?term=${term}`); }; return ( <header className={`flex flex-col sticky top-0 bg-white transition-all duration-200 ${ isScrolled ? 'shadow-md py-2 border-b' // Compact style with shadow when scrolled : 'pt-4 pb-2 border-b-2' // Original padding at the top }`}> {/* 1st DIV - Always visible */} <div className='flex p-2'> <Image loading='lazy' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' alt='Google Logo' width={82} height={30} className='cursor-pointer' /> <form className='flex flex-grow w-4/5 px-6 py-2 ml-10 mr-5 border border-gray-200 rounded-full shadow-md items-center'> <input ref={searchInputRef} className='flex-grow focus:outline-none cursor-pointer' type='text' value={value} onChange={(e) => setValue(e.target.value)} /> {value && ( <XIcon className='h-5 sm:mr-3 text-gray-500 cursor-pointer' onClick={() => setValue('')} /> )} <MicrophoneIcon className='h-5 hidden sm:inline-block text-blue-500 border-l-2 pl-4 border-gray-300' /> <SearchIcon className='h-7 pl-1 text-[#4285f4] cursor-pointer hidden sm:inline-block' /> <button className='hidden' type='submit' onClick={search}> Search </button> </form> </div> {/* 2nd DIV - Hide when scrolled */} {!isScrolled && ( <div className='flex space-x-4 p-6 cursor-pointer'> <p>All</p> <p>Images</p> <p>Video</p> <p>Books</p> <p>More</p> </div> )} </header> ); } export default Header;
Key Changes Breakdown:
- Scroll Detection: The
useEffecthook adds a scroll listener that updatesisScrolledwhen the user scrolls more than 30px from the top. You can adjust this threshold to match your desired behavior. - Conditional Styling: The header's class changes dynamically—when scrolled, it reduces padding and adds a subtle shadow to match Google's compact header style.
- Smooth Transitions: The
transition-all duration-200class makes the header's size and shadow changes feel smooth instead of abrupt. - Category Bar Visibility: The second div is only rendered when the user is at the top of the page (
isScrolledis false), hiding it once they scroll down.
This will give you the exact sticky header behavior you're aiming for—just like the real Google search page.
内容的提问来源于stack exchange,提问作者Aykc
相关产品推荐
相关产品推荐

