本节将介绍如何使用 Tailwind CSS 开发一个现代化的响应式企业官网,包括页面布局、组件开发、响应式设计等方面。

页面布局

导航栏组件

  1. // components/Navbar.tsx
  2. import { useState } from 'react';
  3. const Navbar = () => {
  4. const [isOpen, setIsOpen] = useState(false);
  5. return (
  6. <nav className="bg-white shadow-lg fixed w-full top-0 z-50">
  7. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  8. <div className="flex justify-between h-16">
  9. {/* Logo */}
  10. <div className="flex-shrink-0 flex items-center">
  11. <img
  12. className="h-8 w-auto"
  13. src="/logo.svg"
  14. alt="Company Logo"
  15. />
  16. </div>
  17. {/* Desktop Menu */}
  18. <div className="hidden md:flex md:items-center md:space-x-8">
  19. <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium">
  20. 首页
  21. </a>
  22. <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium">
  23. 产品
  24. </a>
  25. <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium">
  26. 解决方案
  27. </a>
  28. <a href="#" className="text-gray-700 hover:text-gray-900 px-3 py-2 text-sm font-medium">
  29. 关于我们
  30. </a>
  31. <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">
  32. 联系我们
  33. </button>
  34. </div>
  35. {/* Mobile Menu Button */}
  36. <div className="md:hidden flex items-center">
  37. <button
  38. onClick={() => setIsOpen(!isOpen)}
  39. className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100"
  40. >
  41. <svg
  42. className={`${isOpen ? 'hidden' : 'block'} h-6 w-6`}
  43. stroke="currentColor"
  44. fill="none"
  45. viewBox="0 0 24 24"
  46. >
  47. <path
  48. strokeLinecap="round"
  49. strokeLinejoin="round"
  50. strokeWidth="2"
  51. d="M4 6h16M4 12h16M4 18h16"
  52. />
  53. </svg>
  54. <svg
  55. className={`${isOpen ? 'block' : 'hidden'} h-6 w-6`}
  56. stroke="currentColor"
  57. fill="none"
  58. viewBox="0 0 24 24"
  59. >
  60. <path
  61. strokeLinecap="round"
  62. strokeLinejoin="round"
  63. strokeWidth="2"
  64. d="M6 18L18 6M6 6l12 12"
  65. />
  66. </svg>
  67. </button>
  68. </div>
  69. </div>
  70. </div>
  71. {/* Mobile Menu */}
  72. <div className={`${isOpen ? 'block' : 'hidden'} md:hidden`}>
  73. <div className="px-2 pt-2 pb-3 space-y-1">
  74. <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">
  75. 首页
  76. </a>
  77. <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">
  78. 产品
  79. </a>
  80. <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">
  81. 解决方案
  82. </a>
  83. <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">
  84. 关于我们
  85. </a>
  86. <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">
  87. 联系我们
  88. </button>
  89. </div>
  90. </div>
  91. </nav>
  92. );
  93. };

Hero 区域

  1. // components/Hero.tsx
  2. const Hero = () => {
  3. return (
  4. <div className="relative bg-white overflow-hidden">
  5. <div className="max-w-7xl mx-auto">
  6. <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">
  7. <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">
  8. <div className="sm:text-center lg:text-left">
  9. <h1 className="text-4xl tracking-tight font-extrabold text-gray-900 sm:text-5xl md:text-6xl">
  10. <span className="block">打造现代化的</span>
  11. <span className="block text-blue-600">企业数字体验</span>
  12. </h1>
  13. <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">
  14. 我们提供全方位的数字化解决方案,帮助企业实现数字化转型,提升运营效率,创造更大的商业价值。
  15. </p>
  16. <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
  17. <div className="rounded-md shadow">
  18. <a
  19. href="#"
  20. 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"
  21. >
  22. 开始使用
  23. </a>
  24. </div>
  25. <div className="mt-3 sm:mt-0 sm:ml-3">
  26. <a
  27. href="#"
  28. 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"
  29. >
  30. 了解更多
  31. </a>
  32. </div>
  33. </div>
  34. </div>
  35. </main>
  36. </div>
  37. </div>
  38. <div className="lg:absolute lg:inset-y-0 lg:right-0 lg:w-1/2">
  39. <img
  40. className="h-56 w-full object-cover sm:h-72 md:h-96 lg:w-full lg:h-full"
  41. src="/hero-image.jpg"
  42. alt="Hero Image"
  43. />
  44. </div>
  45. </div>
  46. );
  47. };

功能组件

特性展示组件

  1. // components/Features.tsx
  2. const features = [
  3. {
  4. title: '快速部署',
  5. description: '提供一站式部署解决方案,快速上线您的业务系统。',
  6. icon: (
  7. <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  8. <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
  9. </svg>
  10. ),
  11. },
  12. {
  13. title: '安全可靠',
  14. description: '采用业界领先的安全防护措施,保障您的数据安全。',
  15. icon: (
  16. <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  17. <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" />
  18. </svg>
  19. ),
  20. },
  21. // ... 更多特性
  22. ];
  23. const Features = () => {
  24. return (
  25. <div className="py-12 bg-white">
  26. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  27. <div className="lg:text-center">
  28. <h2 className="text-base text-blue-600 font-semibold tracking-wide uppercase">特性</h2>
  29. <p className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
  30. 更好的解决方案
  31. </p>
  32. <p className="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto">
  33. 我们提供全面的解决方案,满足您的各种业务需求。
  34. </p>
  35. </div>
  36. <div className="mt-10">
  37. <div className="space-y-10 md:space-y-0 md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10">
  38. {features.map((feature) => (
  39. <div key={feature.title} className="relative">
  40. <div className="absolute flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white">
  41. {feature.icon}
  42. </div>
  43. <p className="ml-16 text-lg leading-6 font-medium text-gray-900">{feature.title}</p>
  44. <dd className="mt-2 ml-16 text-base text-gray-500">{feature.description}</dd>
  45. </div>
  46. ))}
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. );
  52. };

客户案例组件

  1. // components/Cases.tsx
  2. const cases = [
  3. {
  4. title: '企业A的数字化转型',
  5. description: '帮助企业A实现了全面的数字化转型,提升了30%的运营效率。',
  6. image: '/case-1.jpg',
  7. },
  8. // ... 更多案例
  9. ];
  10. const Cases = () => {
  11. return (
  12. <div className="bg-gray-50 py-12 lg:py-20">
  13. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  14. <div className="text-center">
  15. <h2 className="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl">
  16. 成功案例
  17. </h2>
  18. <p className="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto">
  19. 看看我们如何帮助客户实现业务增长。
  20. </p>
  21. </div>
  22. <div className="mt-12 grid gap-8 md:grid-cols-2 lg:grid-cols-3">
  23. {cases.map((case_) => (
  24. <div
  25. key={case_.title}
  26. className="flex flex-col rounded-lg shadow-lg overflow-hidden"
  27. >
  28. <div className="flex-shrink-0">
  29. <img
  30. className="h-48 w-full object-cover"
  31. src={case_.image}
  32. alt={case_.title}
  33. />
  34. </div>
  35. <div className="flex-1 bg-white p-6 flex flex-col justify-between">
  36. <div className="flex-1">
  37. <h3 className="text-xl font-semibold text-gray-900">
  38. {case_.title}
  39. </h3>
  40. <p className="mt-3 text-base text-gray-500">
  41. {case_.description}
  42. </p>
  43. </div>
  44. <div className="mt-6">
  45. <a
  46. href="#"
  47. className="text-base font-semibold text-blue-600 hover:text-blue-500"
  48. >
  49. 了解更多
  50. </a>
  51. </div>
  52. </div>
  53. </div>
  54. ))}
  55. </div>
  56. </div>
  57. </div>
  58. );
  59. };

响应式优化

媒体查询策略

  1. // styles/breakpoints.ts
  2. export const breakpoints = {
  3. sm: '640px', // 小屏幕设备
  4. md: '768px', // 平板设备
  5. lg: '1024px', // 小型笔记本
  6. xl: '1280px', // 大型笔记本
  7. '2xl': '1536px' // 桌面设备
  8. };
  9. // 使用示例
  10. <div className="
  11. grid
  12. grid-cols-1
  13. gap-6
  14. sm:grid-cols-2
  15. lg:grid-cols-3
  16. xl:grid-cols-4
  17. ">
  18. {/* 内容 */}
  19. </div>

图片响应式处理

  1. // components/ResponsiveImage.tsx
  2. interface ResponsiveImageProps {
  3. src: string;
  4. alt: string;
  5. className?: string;
  6. }
  7. const ResponsiveImage: React.FC<ResponsiveImageProps> = ({
  8. src,
  9. alt,
  10. className = ''
  11. }) => {
  12. return (
  13. <picture>
  14. <source
  15. media="(min-width: 1024px)"
  16. srcSet={`${src}?w=1200`}
  17. />
  18. <source
  19. media="(min-width: 768px)"
  20. srcSet={`${src}?w=800`}
  21. />
  22. <img
  23. src={`${src}?w=400`}
  24. alt={alt}
  25. className={`w-full h-auto ${className}`}
  26. loading="lazy"
  27. />
  28. </picture>
  29. );
  30. };
  31. // 使用示例
  32. <ResponsiveImage
  33. src="/hero-image.jpg"
  34. alt="Hero Image"
  35. className="rounded-lg shadow-lg"
  36. />

响应式导航

  1. // hooks/useResponsiveNav.ts
  2. import { useState, useEffect } from 'react';
  3. export const useResponsiveNav = () => {
  4. const [isMenuOpen, setIsMenuOpen] = useState(false);
  5. const [isMobile, setIsMobile] = useState(false);
  6. useEffect(() => {
  7. const checkWidth = () => {
  8. setIsMobile(window.innerWidth < 768);
  9. if (window.innerWidth >= 768) {
  10. setIsMenuOpen(false);
  11. }
  12. };
  13. window.addEventListener('resize', checkWidth);
  14. checkWidth();
  15. return () => window.removeEventListener('resize', checkWidth);
  16. }, []);
  17. return {
  18. isMenuOpen,
  19. setIsMenuOpen,
  20. isMobile
  21. };
  22. };

性能优化

图片懒加载

  1. // components/LazyImage.tsx
  2. import { useEffect, useRef, useState } from 'react';
  3. interface LazyImageProps {
  4. src: string;
  5. alt: string;
  6. className?: string;
  7. placeholder?: string;
  8. }
  9. const LazyImage: React.FC<LazyImageProps> = ({
  10. src,
  11. alt,
  12. className = '',
  13. placeholder = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
  14. }) => {
  15. const [isLoaded, setIsLoaded] = useState(false);
  16. const [imageSrc, setImageSrc] = useState(placeholder);
  17. const imageRef = useRef<HTMLImageElement>(null);
  18. useEffect(() => {
  19. const observer = new IntersectionObserver(
  20. (entries) => {
  21. entries.forEach((entry) => {
  22. if (entry.isIntersecting) {
  23. setImageSrc(src);
  24. observer.unobserve(entry.target);
  25. }
  26. });
  27. },
  28. {
  29. rootMargin: '50px'
  30. }
  31. );
  32. if (imageRef.current) {
  33. observer.observe(imageRef.current);
  34. }
  35. return () => {
  36. if (imageRef.current) {
  37. observer.unobserve(imageRef.current);
  38. }
  39. };
  40. }, [src]);
  41. return (
  42. <img
  43. ref={imageRef}
  44. src={imageSrc}
  45. alt={alt}
  46. className={`
  47. transition-opacity duration-300
  48. ${isLoaded ? 'opacity-100' : 'opacity-0'}
  49. ${className}
  50. `}
  51. onLoad={() => setIsLoaded(true)}
  52. />
  53. );
  54. };

组件优化

  1. // components/OptimizedCarousel.tsx
  2. import { memo } from 'react';
  3. interface CarouselProps {
  4. items: Array<{
  5. id: string;
  6. image: string;
  7. title: string;
  8. }>;
  9. }
  10. const OptimizedCarousel = memo(({ items }: CarouselProps) => {
  11. return (
  12. <div className="relative overflow-hidden">
  13. <div className="flex snap-x snap-mandatory overflow-x-auto">
  14. {items.map((item) => (
  15. <div
  16. key={item.id}
  17. className="snap-start flex-shrink-0 w-full md:w-1/2 lg:w-1/3"
  18. >
  19. <LazyImage
  20. src={item.image}
  21. alt={item.title}
  22. className="w-full h-64 object-cover"
  23. />
  24. <h3 className="mt-2 text-lg font-medium text-gray-900">
  25. {item.title}
  26. </h3>
  27. </div>
  28. ))}
  29. </div>
  30. </div>
  31. );
  32. });
  33. OptimizedCarousel.displayName = 'OptimizedCarousel';

动画效果

滚动动画

  1. // hooks/useScrollAnimation.ts
  2. import { useEffect, useRef } from 'react';
  3. export const useScrollAnimation = (options = {}) => {
  4. const elementRef = useRef<HTMLElement>(null);
  5. useEffect(() => {
  6. const observer = new IntersectionObserver((entries) => {
  7. entries.forEach((entry) => {
  8. if (entry.isIntersecting) {
  9. entry.target.classList.add('animate-fade-in');
  10. observer.unobserve(entry.target);
  11. }
  12. });
  13. }, options);
  14. if (elementRef.current) {
  15. observer.observe(elementRef.current);
  16. }
  17. return () => {
  18. if (elementRef.current) {
  19. observer.unobserve(elementRef.current);
  20. }
  21. };
  22. }, []);
  23. return elementRef;
  24. };
  25. // 使用示例
  26. const Section = () => {
  27. const animationRef = useScrollAnimation({
  28. threshold: 0.1
  29. });
  30. return (
  31. <div
  32. ref={animationRef}
  33. className="opacity-0 transition-opacity duration-1000"
  34. >
  35. {/* 内容 */}
  36. </div>
  37. );
  38. };

最佳实践

  1. 响应式设计

    • 移动优先设计
    • 合理使用断点
    • 灵活的布局系统
  2. 性能优化

    • 图片优化
    • 组件懒加载
    • 动画性能
  3. 用户体验

    • 交互反馈
    • 加载状态
    • 平滑过渡
  4. 开发建议

    • 组件复用
    • 样式模块化
    • 持续优化
  5. 测试

    • 响应式测试
    • 性能测试
    • 兼容性测试