第七章:项目实战-第二节-TailwindCSS响应式官网开发
- 开源代码
- 2025-09-21 19:30:01

本节将介绍如何使用 Tailwind CSS 开发一个现代化的响应式企业官网,包括页面布局、组件开发、响应式设计等方面。
页面布局 导航栏组件 // components/Navbar.tsx import { useState } from 'react'; const Navbar = () => { const [isOpen, setIsOpen] = useState(false); return ( <nav className="bg-white shadow-lg fixed w-full top-0 z-50"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="flex justify-between h-16"> {/* Logo */} <div className="flex-shrink-0 flex items-center"> <img className="h-8 w-auto" src="/logo.svg" alt="Company Logo" /> </div> {/* Desktop Menu */} <div className="hidden md:flex md:items-center md:space-x-8"> <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium"> 首页 </a> <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium"> 产品 </a> <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium"> 解决方案 </a> <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium"> 关于我们 </a> <button className="ml-8 bg-blue-500 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-600 transition-colors"> 联系我们 </button> </div> {/* Mobile Menu Button */} <div className="md:hidden flex items-center"> <button onClick={() => setIsOpen(!isOpen)} className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100" > <svg className={`${isOpen ? 'hidden' : 'block'} h-6 w-6`} stroke="currentColor" fill="none" viewBox="0 0 24 24" > <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16" /> </svg> <svg className={`${isOpen ? 'block' : 'hidden'} h-6 w-6`} stroke="currentColor" fill="none" viewBox="0 0 24 24" > <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /> </svg> </button> </div> </div> </div> {/* Mobile Menu */} <div className={`${isOpen ? 'block' : 'hidden'} md:hidden`}> <div className="px-2 pt-2 pb-3 space-y-1"> <a href="#" className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50"> 首页 </a> <a href="#" className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50"> 产品 </a> <a href="#" className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50"> 解决方案 </a> <a href="#" className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50"> 关于我们 </a> <button className="w-full bg-blue-500 text-white px-4 py-2 rounded-lg text-base font-medium hover:bg-blue-600 transition-colors"> 联系我们 </button> </div> </div> </nav> ); }; Hero 区域 // components/Hero.tsx const Hero = () => { return ( <div className="relative bg-white overflow-hidden"> <div className="max-w-7xl mx-auto"> <div className="relative z-10 pb-8 bg-white sm:pb-16 md:pb-20 lg:max-w-2xl lg:w-full lg:pb-28 xl:pb-32"> <main className="mt-10 mx-auto max-w-7xl px-4 sm:mt-12 sm:px-6 md:mt-16 lg:mt-20 lg:px-8 xl:mt-28"> <div className="sm:text-center lg:text-left"> <h1 className="text-4xl tracking-tight font-extrabold text-gray-900 sm:text-5xl md:text-6xl"> <span className="block">打造现代化的</span> <span className="block text-blue-600">企业数字体验</span> </h1> <p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"> 我们提供全方位的数字化解决方案,帮助企业实现数字化转型,提升运营效率,创造更大的商业价值。 </p> <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start"> <div className="rounded-md shadow"> <a href="#" className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 md:py-4 md:text-lg md:px-10" > 开始使用 </a> </div> <div className="mt-3 sm:mt-0 sm:ml-3"> <a href="#" className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-blue-700 bg-blue-100 hover:bg-blue-200 md:py-4 md:text-lg md:px-10" > 了解更多 </a> </div> </div> </div> </main> </div> </div> <div className="lg:absolute lg:inset-y-0 lg:right-0 lg:w-1/2"> <img className="h-56 w-full object-cover sm:h-72 md:h-96 lg:w-full lg:h-full" src="/hero-image.jpg" alt="Hero Image" /> </div> </div> ); }; 功能组件 特性展示组件 // components/Features.tsx const features = [ { title: '快速部署', description: '提供一站式部署解决方案,快速上线您的业务系统。', icon: ( <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /> </svg> ), }, { title: '安全可靠', description: '采用业界领先的安全防护措施,保障您的数据安全。', icon: ( <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /> </svg> ), }, // ... 更多特性 ]; const Features = () => { return ( <div className="py-12 bg-white"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="lg:text-center"> <h2 className="text-base text-blue-600 font-semibold tracking-wide uppercase">特性</h2> <p className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl"> 更好的解决方案 </p> <p className="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto"> 我们提供全面的解决方案,满足您的各种业务需求。 </p> </div> <div className="mt-10"> <div className="space-y-10 md:space-y-0 md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10"> {features.map((feature) => ( <div key={feature.title} className="relative"> <div className="absolute flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white"> {feature.icon} </div> <p className="ml-16 text-lg leading-6 font-medium text-gray-900">{feature.title}</p> <dd className="mt-2 ml-16 text-base text-gray-500">{feature.description}</dd> </div> ))} </div> </div> </div> </div> ); }; 客户案例组件 // components/Cases.tsx const cases = [ { title: '企业A的数字化转型', description: '帮助企业A实现了全面的数字化转型,提升了30%的运营效率。', image: '/case-1.jpg', }, // ... 更多案例 ]; const Cases = () => { return ( <div className="bg-gray-50 py-12 lg:py-20"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="text-center"> <h2 className="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl"> 成功案例 </h2> <p className="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto"> 看看我们如何帮助客户实现业务增长。 </p> </div> <div className="mt-12 grid gap-8 md:grid-cols-2 lg:grid-cols-3"> {cases.map((case_) => ( <div key={case_.title} className="flex flex-col rounded-lg shadow-lg overflow-hidden" > <div className="flex-shrink-0"> <img className="h-48 w-full object-cover" src={case_.image} alt={case_.title} /> </div> <div className="flex-1 bg-white p-6 flex flex-col justify-between"> <div className="flex-1"> <h3 className="text-xl font-semibold text-gray-900"> {case_.title} </h3> <p className="mt-3 text-base text-gray-500"> {case_.description} </p> </div> <div className="mt-6"> <a href="#" className="text-base font-semibold text-blue-600 hover:text-blue-500" > 了解更多 → </a> </div> </div> </div> ))} </div> </div> </div> ); }; 响应式优化 媒体查询策略 // styles/breakpoints.ts export const breakpoints = { sm: '640px', // 小屏幕设备 md: '768px', // 平板设备 lg: '1024px', // 小型笔记本 xl: '1280px', // 大型笔记本 '2xl': '1536px' // 桌面设备 }; // 使用示例 <div className=" grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 "> {/* 内容 */} </div> 图片响应式处理 // components/ResponsiveImage.tsx interface ResponsiveImageProps { src: string; alt: string; className?: string; } const ResponsiveImage: React.FC<ResponsiveImageProps> = ({ src, alt, className = '' }) => { return ( <picture> <source media="(min-width: 1024px)" srcSet={`${src}?w=1200`} /> <source media="(min-width: 768px)" srcSet={`${src}?w=800`} /> <img src={`${src}?w=400`} alt={alt} className={`w-full h-auto ${className}`} loading="lazy" /> </picture> ); }; // 使用示例 <ResponsiveImage src="/hero-image.jpg" alt="Hero Image" className="rounded-lg shadow-lg" /> 响应式导航 // hooks/useResponsiveNav.ts import { useState, useEffect } from 'react'; export const useResponsiveNav = () => { const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMobile, setIsMobile] = useState(false); useEffect(() => { const checkWidth = () => { setIsMobile(window.innerWidth < 768); if (window.innerWidth >= 768) { setIsMenuOpen(false); } }; window.addEventListener('resize', checkWidth); checkWidth(); return () => window.removeEventListener('resize', checkWidth); }, []); return { isMenuOpen, setIsMenuOpen, isMobile }; }; 性能优化 图片懒加载 // components/LazyImage.tsx import { useEffect, useRef, useState } from 'react'; interface LazyImageProps { src: string; alt: string; className?: string; placeholder?: string; } const LazyImage: React.FC<LazyImageProps> = ({ src, alt, className = '', placeholder = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' }) => { const [isLoaded, setIsLoaded] = useState(false); const [imageSrc, setImageSrc] = useState(placeholder); const imageRef = useRef<HTMLImageElement>(null); useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { setImageSrc(src); observer.unobserve(entry.target); } }); }, { rootMargin: '50px' } ); if (imageRef.current) { observer.observe(imageRef.current); } return () => { if (imageRef.current) { observer.unobserve(imageRef.current); } }; }, [src]); return ( <img ref={imageRef} src={imageSrc} alt={alt} className={` transition-opacity duration-300 ${isLoaded ? 'opacity-100' : 'opacity-0'} ${className} `} onLoad={() => setIsLoaded(true)} /> ); }; 组件优化 // components/OptimizedCarousel.tsx import { memo } from 'react'; interface CarouselProps { items: Array<{ id: string; image: string; title: string; }>; } const OptimizedCarousel = memo(({ items }: CarouselProps) => { return ( <div className="relative overflow-hidden"> <div className="flex snap-x snap-mandatory overflow-x-auto"> {items.map((item) => ( <div key={item.id} className="snap-start flex-shrink-0 w-full md:w-1/2 lg:w-1/3" > <LazyImage src={item.image} alt={item.title} className="w-full h-64 object-cover" /> <h3 className="mt-2 text-lg font-medium text-gray-900"> {item.title} </h3> </div> ))} </div> </div> ); }); OptimizedCarousel.displayName = 'OptimizedCarousel'; 动画效果 滚动动画 // hooks/useScrollAnimation.ts import { useEffect, useRef } from 'react'; export const useScrollAnimation = (options = {}) => { const elementRef = useRef<HTMLElement>(null); useEffect(() => { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('animate-fade-in'); observer.unobserve(entry.target); } }); }, options); if (elementRef.current) { observer.observe(elementRef.current); } return () => { if (elementRef.current) { observer.unobserve(elementRef.current); } }; }, []); return elementRef; }; // 使用示例 const Section = () => { const animationRef = useScrollAnimation({ threshold: 0.1 }); return ( <div ref={animationRef} className="opacity-0 transition-opacity duration-1000" > {/* 内容 */} </div> ); }; 最佳实践响应式设计
移动优先设计合理使用断点灵活的布局系统性能优化
图片优化组件懒加载动画性能用户体验
交互反馈加载状态平滑过渡开发建议
组件复用样式模块化持续优化测试
响应式测试性能测试兼容性测试第七章:项目实战-第二节-TailwindCSS响应式官网开发由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“第七章:项目实战-第二节-TailwindCSS响应式官网开发”
上一篇
松灵机器人地盘安装ros驱动并且发布ros指令进行控制
下一篇
机器学习决策树