You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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 useEffect hook adds a scroll listener that updates isScrolled when 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-200 class 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 (isScrolled is 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 10:37:46