responsive-design-system

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Responsive Design System

响应式设计系统

Build adaptive, mobile-first layouts with modern CSS features and Tailwind.
借助现代CSS特性和Tailwind构建自适应、移动优先的布局。

Core Workflow

核心工作流程

  1. Define breakpoints: Establish responsive breakpoint system
  2. Set fluid typography: Clamp-based responsive fonts
  3. Create layout grid: Responsive grid system
  4. Add container queries: Component-level responsiveness
  5. Build responsive components: Adaptive patterns
  6. Test across devices: Verify on all viewports
  1. 定义断点:建立响应式断点系统
  2. 设置流式排版:基于clamp的响应式字体
  3. 创建布局网格:响应式网格系统
  4. 添加容器查询:组件级别的响应能力
  5. 构建响应式组件:自适应模式
  6. 跨设备测试:在所有视口上验证效果

Breakpoint System

断点系统

Tailwind Default Breakpoints

Tailwind默认断点

BreakpointMin WidthTarget Devices
sm
640pxLarge phones (landscape)
md
768pxTablets
lg
1024pxLaptops
xl
1280pxDesktops
2xl
1536pxLarge screens
断点最小宽度目标设备
sm
640px大屏手机(横屏)
md
768px平板电脑
lg
1024px笔记本电脑
xl
1280px台式机
2xl
1536px大屏显示器

Custom Breakpoints

自定义断点

javascript
// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'xs': '475px',
      'sm': '640px',
      'md': '768px',
      'lg': '1024px',
      'xl': '1280px',
      '2xl': '1536px',
      '3xl': '1920px',
      // Max-width breakpoints
      'max-sm': { max: '639px' },
      'max-md': { max: '767px' },
      'max-lg': { max: '1023px' },
      // Range breakpoints
      'tablet': { min: '768px', max: '1023px' },
      // Feature queries
      'touch': { raw: '(hover: none) and (pointer: coarse)' },
      'stylus': { raw: '(hover: none) and (pointer: fine)' },
      'mouse': { raw: '(hover: hover) and (pointer: fine)' },
    },
  },
};
javascript
// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'xs': '475px',
      'sm': '640px',
      'md': '768px',
      'lg': '1024px',
      'xl': '1280px',
      '2xl': '1536px',
      '3xl': '1920px',
      // 最大宽度断点
      'max-sm': { max: '639px' },
      'max-md': { max: '767px' },
      'max-lg': { max: '1023px' },
      // 范围断点
      'tablet': { min: '768px', max: '1023px' },
      // 特性查询
      'touch': { raw: '(hover: none) and (pointer: coarse)' },
      'stylus': { raw: '(hover: none) and (pointer: fine)' },
      'mouse': { raw: '(hover: hover) and (pointer: fine)' },
    },
  },
};

Fluid Typography

流式排版

CSS Clamp Function

CSS Clamp函数

css
/* globals.css */
:root {
  /* Fluid type scale: min, preferred, max */
  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
  --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1rem + 0.6vw, 1.25rem);
  --text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  --text-2xl: clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
  --text-3xl: clamp(1.875rem, 1.4rem + 2.25vw, 2.5rem);
  --text-4xl: clamp(2.25rem, 1.5rem + 3.75vw, 3.5rem);
  --text-5xl: clamp(3rem, 1.8rem + 6vw, 5rem);

  /* Fluid spacing */
  --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
  --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
  --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  --space-lg: clamp(1.5rem, 1rem + 2.5vw, 3rem);
  --space-xl: clamp(2rem, 1.2rem + 4vw, 5rem);
}
css
/* globals.css */
:root {
  /* 流式字体比例:最小值、首选值、最大值 */
  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
  --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1rem + 0.6vw, 1.25rem);
  --text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  --text-2xl: clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
  --text-3xl: clamp(1.875rem, 1.4rem + 2.25vw, 2.5rem);
  --text-4xl: clamp(2.25rem, 1.5rem + 3.75vw, 3.5rem);
  --text-5xl: clamp(3rem, 1.8rem + 6vw, 5rem);

  /* 流式间距 */
  --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
  --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
  --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  --space-lg: clamp(1.5rem, 1rem + 2.5vw, 3rem);
  --space-xl: clamp(2rem, 1.2rem + 4vw, 5rem);
}

Tailwind Fluid Typography

Tailwind流式排版配置

javascript
// tailwind.config.js
const plugin = require('tailwindcss/plugin');

module.exports = {
  theme: {
    extend: {
      fontSize: {
        'fluid-xs': 'clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem)',
        'fluid-sm': 'clamp(0.875rem, 0.8rem + 0.35vw, 1rem)',
        'fluid-base': 'clamp(1rem, 0.9rem + 0.5vw, 1.125rem)',
        'fluid-lg': 'clamp(1.125rem, 1rem + 0.6vw, 1.25rem)',
        'fluid-xl': 'clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem)',
        'fluid-2xl': 'clamp(1.5rem, 1.2rem + 1.5vw, 2rem)',
        'fluid-3xl': 'clamp(1.875rem, 1.4rem + 2.25vw, 2.5rem)',
        'fluid-4xl': 'clamp(2.25rem, 1.5rem + 3.75vw, 3.5rem)',
        'fluid-5xl': 'clamp(3rem, 1.8rem + 6vw, 5rem)',
      },
    },
  },
};
javascript
// tailwind.config.js
const plugin = require('tailwindcss/plugin');

module.exports = {
  theme: {
    extend: {
      fontSize: {
        'fluid-xs': 'clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem)',
        'fluid-sm': 'clamp(0.875rem, 0.8rem + 0.35vw, 1rem)',
        'fluid-base': 'clamp(1rem, 0.9rem + 0.5vw, 1.125rem)',
        'fluid-lg': 'clamp(1.125rem, 1rem + 0.6vw, 1.25rem)',
        'fluid-xl': 'clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem)',
        'fluid-2xl': 'clamp(1.5rem, 1.2rem + 1.5vw, 2rem)',
        'fluid-3xl': 'clamp(1.875rem, 1.4rem + 2.25vw, 2.5rem)',
        'fluid-4xl': 'clamp(2.25rem, 1.5rem + 3.75vw, 3.5rem)',
        'fluid-5xl': 'clamp(3rem, 1.8rem + 6vw, 5rem)',
      },
    },
  },
};

Usage

使用示例

html
<h1 class="text-fluid-4xl font-bold">Responsive Headline</h1>
<p class="text-fluid-base">Body text that scales smoothly.</p>
html
<h1 class="text-fluid-4xl font-bold">响应式标题</h1>
<p class="text-fluid-base">可平滑缩放的正文文本。</p>

Container Queries

容器查询

Enable Container Queries

启用容器查询

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      containers: {
        'xs': '320px',
        'sm': '384px',
        'md': '448px',
        'lg': '512px',
        'xl': '576px',
        '2xl': '672px',
      },
    },
  },
};
javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      containers: {
        'xs': '320px',
        'sm': '384px',
        'md': '448px',
        'lg': '512px',
        'xl': '576px',
        '2xl': '672px',
      },
    },
  },
};

Container Query Usage

容器查询使用示例

html
<!-- Define container -->
<div class="@container">
  <!-- Respond to container size, not viewport -->
  <div class="flex flex-col @md:flex-row @lg:gap-8">
    <div class="@md:w-1/2">
      <h2 class="text-lg @lg:text-2xl">Card Title</h2>
    </div>
    <div class="@md:w-1/2">
      <p class="text-sm @lg:text-base">Card content</p>
    </div>
  </div>
</div>

<!-- Named containers -->
<div class="@container/main">
  <div class="@lg/main:grid-cols-3">...</div>
</div>
html
<!-- 定义容器 -->
<div class="@container">
  <!-- 根据容器尺寸而非视口尺寸做出响应 -->
  <div class="flex flex-col @md:flex-row @lg:gap-8">
    <div class="@md:w-1/2">
      <h2 class="text-lg @lg:text-2xl">卡片标题</h2>
    </div>
    <div class="@md:w-1/2">
      <p class="text-sm @lg:text-base">卡片内容</p>
    </div>
  </div>
</div>

<!-- 命名容器 -->
<div class="@container/main">
  <div class="@lg/main:grid-cols-3">...</div>
</div>

Responsive Card Component

响应式卡片组件

tsx
// components/ResponsiveCard.tsx
export function ResponsiveCard({ title, description, image }: CardProps) {
  return (
    <article className="@container">
      <div className="flex flex-col @sm:flex-row gap-4 p-4 bg-white rounded-lg shadow">
        <img
          src={image}
          alt=""
          className="w-full @sm:w-32 @md:w-48 h-32 @sm:h-auto object-cover rounded"
        />
        <div className="flex-1">
          <h3 className="text-lg @md:text-xl font-semibold">{title}</h3>
          <p className="text-sm @md:text-base text-gray-600 mt-2">
            {description}
          </p>
          <button className="mt-4 px-4 py-2 bg-blue-500 text-white rounded @md:px-6">
            Learn More
          </button>
        </div>
      </div>
    </article>
  );
}
tsx
// components/ResponsiveCard.tsx
export function ResponsiveCard({ title, description, image }: CardProps) {
  return (
    <article className="@container">
      <div className="flex flex-col @sm:flex-row gap-4 p-4 bg-white rounded-lg shadow">
        <img
          src={image}
          alt=""
          className="w-full @sm:w-32 @md:w-48 h-32 @sm:h-auto object-cover rounded"
        />
        <div className="flex-1">
          <h3 className="text-lg @md:text-xl font-semibold">{title}</h3>
          <p className="text-sm @md:text-base text-gray-600 mt-2">
            {description}
          </p>
          <button className="mt-4 px-4 py-2 bg-blue-500 text-white rounded @md:px-6">
            了解更多
          </button>
        </div>
      </div>
    </article>
  );
}

Responsive Grid Layouts

响应式网格布局

Auto-Fit Grid

自动适配网格

html
<!-- Cards that automatically adjust columns -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
  <!-- Cards -->
</div>

<!-- CSS Grid auto-fit -->
<div class="grid gap-6" style="grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))">
  <!-- Cards automatically fit -->
</div>
html
<!-- 自动调整列数的卡片 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
  <!-- 卡片内容 -->
</div>

<!-- CSS Grid自动适配 -->
<div class="grid gap-6" style="grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))">
  <!-- 卡片自动适配布局 -->
</div>

Dashboard Layout

仪表盘布局

tsx
// components/DashboardLayout.tsx
export function DashboardLayout({ sidebar, main }: LayoutProps) {
  return (
    <div className="min-h-screen flex flex-col lg:flex-row">
      {/* Sidebar: Full width on mobile, fixed width on desktop */}
      <aside className="w-full lg:w-64 xl:w-80 bg-gray-900 text-white">
        <div className="p-4 lg:sticky lg:top-0">{sidebar}</div>
      </aside>

      {/* Main content */}
      <main className="flex-1 p-4 md:p-6 lg:p-8">
        <div className="max-w-7xl mx-auto">{main}</div>
      </main>
    </div>
  );
}
tsx
// components/DashboardLayout.tsx
export function DashboardLayout({ sidebar, main }: LayoutProps) {
  return (
    <div className="min-h-screen flex flex-col lg:flex-row">
      {/* 侧边栏:移动端全屏显示,桌面端固定宽度 */}
      <aside className="w-full lg:w-64 xl:w-80 bg-gray-900 text-white">
        <div className="p-4 lg:sticky lg:top-0">{sidebar}</div>
      </aside>

      {/* 主内容区 */}
      <main className="flex-1 p-4 md:p-6 lg:p-8">
        <div className="max-w-7xl mx-auto">{main}</div>
      </main>
    </div>
  );
}

Holy Grail Layout

圣杯布局

tsx
export function HolyGrailLayout({ header, sidebar, main, aside, footer }: LayoutProps) {
  return (
    <div className="min-h-screen grid grid-rows-[auto_1fr_auto]">
      <header className="bg-white border-b px-4 py-3">
        {header}
      </header>

      <div className="grid grid-cols-1 md:grid-cols-[240px_1fr] lg:grid-cols-[240px_1fr_240px]">
        <aside className="hidden md:block bg-gray-50 p-4 border-r">
          {sidebar}
        </aside>

        <main className="p-4 md:p-6 overflow-auto">
          {main}
        </main>

        <aside className="hidden lg:block bg-gray-50 p-4 border-l">
          {aside}
        </aside>
      </div>

      <footer className="bg-gray-900 text-white px-4 py-6">
        {footer}
      </footer>
    </div>
  );
}
tsx
export function HolyGrailLayout({ header, sidebar, main, aside, footer }: LayoutProps) {
  return (
    <div className="min-h-screen grid grid-rows-[auto_1fr_auto]">
      <header className="bg-white border-b px-4 py-3">
        {header}
      </header>

      <div className="grid grid-cols-1 md:grid-cols-[240px_1fr] lg:grid-cols-[240px_1fr_240px]">
        <aside className="hidden md:block bg-gray-50 p-4 border-r">
          {sidebar}
        </aside>

        <main className="p-4 md:p-6 overflow-auto">
          {main}
        </main>

        <aside className="hidden lg:block bg-gray-50 p-4 border-l">
          {aside}
        </aside>
      </div>

      <footer className="bg-gray-900 text-white px-4 py-6">
        {footer}
      </footer>
    </div>
  );
}

Responsive Images

响应式图片

Srcset and Sizes

Srcset和Sizes属性

html
<img
  src="/images/hero-800.jpg"
  srcset="
    /images/hero-400.jpg 400w,
    /images/hero-800.jpg 800w,
    /images/hero-1200.jpg 1200w,
    /images/hero-1600.jpg 1600w
  "
  sizes="(max-width: 640px) 100vw,
         (max-width: 1024px) 75vw,
         50vw"
  alt="Hero image"
  class="w-full h-auto"
/>
html
<img
  src="/images/hero-800.jpg"
  srcset="
    /images/hero-400.jpg 400w,
    /images/hero-800.jpg 800w,
    /images/hero-1200.jpg 1200w,
    /images/hero-1600.jpg 1600w
  "
  sizes="(max-width: 640px) 100vw,
         (max-width: 1024px) 75vw,
         50vw"
  alt="Hero image"
  class="w-full h-auto"
/>

Next.js Image

Next.js Image组件

tsx
import Image from 'next/image';

export function ResponsiveImage({ src, alt }: ImageProps) {
  return (
    <div className="relative aspect-video w-full">
      <Image
        src={src}
        alt={alt}
        fill
        sizes="(max-width: 640px) 100vw,
               (max-width: 1024px) 75vw,
               50vw"
        className="object-cover"
      />
    </div>
  );
}
tsx
import Image from 'next/image';

export function ResponsiveImage({ src, alt }: ImageProps) {
  return (
    <div className="relative aspect-video w-full">
      <Image
        src={src}
        alt={alt}
        fill
        sizes="(max-width: 640px) 100vw,
               (max-width: 1024px) 75vw,
               50vw"
        className="object-cover"
      />
    </div>
  );
}

Art Direction with Picture

使用Picture标签实现艺术方向

html
<picture>
  <!-- Mobile: Square crop -->
  <source
    media="(max-width: 639px)"
    srcset="/images/hero-mobile.jpg"
  />
  <!-- Tablet: 4:3 crop -->
  <source
    media="(max-width: 1023px)"
    srcset="/images/hero-tablet.jpg"
  />
  <!-- Desktop: Wide crop -->
  <img
    src="/images/hero-desktop.jpg"
    alt="Hero"
    class="w-full h-auto"
  />
</picture>
html
<picture>
  <!-- 移动端:方形裁剪 -->
  <source
    media="(max-width: 639px)"
    srcset="/images/hero-mobile.jpg"
  />
  <!-- 平板端:4:3裁剪 -->
  <source
    media="(max-width: 1023px)"
    srcset="/images/hero-tablet.jpg"
  />
  <!-- 桌面端:宽屏裁剪 -->
  <img
    src="/images/hero-desktop.jpg"
    alt="Hero"
    class="w-full h-auto"
  />
</picture>

Responsive Navigation

响应式导航

Mobile Menu Pattern

移动端菜单模式

tsx
'use client';

import { useState } from 'react';
import { Menu, X } from 'lucide-react';

export function ResponsiveNav({ links }: NavProps) {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <nav className="relative">
      {/* Desktop Navigation */}
      <div className="hidden md:flex items-center gap-8">
        {links.map((link) => (
          <a key={link.href} href={link.href} className="hover:text-blue-500">
            {link.label}
          </a>
        ))}
      </div>

      {/* Mobile Menu Button */}
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="md:hidden p-2"
        aria-label="Toggle menu"
      >
        {isOpen ? <X size={24} /> : <Menu size={24} />}
      </button>

      {/* Mobile Navigation */}
      {isOpen && (
        <div className="absolute top-full left-0 right-0 bg-white shadow-lg md:hidden">
          {links.map((link) => (
            <a
              key={link.href}
              href={link.href}
              className="block px-4 py-3 border-b hover:bg-gray-50"
            >
              {link.label}
            </a>
          ))}
        </div>
      )}
    </nav>
  );
}
tsx
'use client';

import { useState } from 'react';
import { Menu, X } from 'lucide-react';

export function ResponsiveNav({ links }: NavProps) {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <nav className="relative">
      {/* 桌面端导航 */}
      <div className="hidden md:flex items-center gap-8">
        {links.map((link) => (
          <a key={link.href} href={link.href} className="hover:text-blue-500">
            {link.label}
          </a>
        ))}
      </div>

      {/* 移动端菜单按钮 */}
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="md:hidden p-2"
        aria-label="切换菜单"
      >
        {isOpen ? <X size={24} /> : <Menu size={24} />}
      </button>

      {/* 移动端导航 */}
      {isOpen && (
        <div className="absolute top-full left-0 right-0 bg-white shadow-lg md:hidden">
          {links.map((link) => (
            <a
              key={link.href}
              href={link.href}
              className="block px-4 py-3 border-b hover:bg-gray-50"
            >
              {link.label}
            </a>
          ))}
        </div>
      )}
    </nav>
  );
}

Responsive Tables

响应式表格

Horizontal Scroll

横向滚动

html
<div class="overflow-x-auto">
  <table class="min-w-full">
    <!-- Table content -->
  </table>
</div>
html
<div class="overflow-x-auto">
  <table class="min-w-full">
    <!-- 表格内容 -->
  </table>
</div>

Stacked on Mobile

移动端堆叠显示

tsx
export function ResponsiveTable({ headers, rows }: TableProps) {
  return (
    <>
      {/* Desktop Table */}
      <table className="hidden md:table w-full">
        <thead>
          <tr>
            {headers.map((header) => (
              <th key={header} className="px-4 py-2 text-left">{header}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, i) => (
            <tr key={i}>
              {row.map((cell, j) => (
                <td key={j} className="px-4 py-2">{cell}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>

      {/* Mobile Cards */}
      <div className="md:hidden space-y-4">
        {rows.map((row, i) => (
          <div key={i} className="bg-white p-4 rounded-lg shadow">
            {row.map((cell, j) => (
              <div key={j} className="flex justify-between py-2 border-b last:border-0">
                <span className="font-medium text-gray-600">{headers[j]}</span>
                <span>{cell}</span>
              </div>
            ))}
          </div>
        ))}
      </div>
    </>
  );
}
tsx
export function ResponsiveTable({ headers, rows }: TableProps) {
  return (
    <>
      {/* 桌面端表格 */}
      <table className="hidden md:table w-full">
        <thead>
          <tr>
            {headers.map((header) => (
              <th key={header} className="px-4 py-2 text-left">{header}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, i) => (
            <tr key={i}>
              {row.map((cell, j) => (
                <td key={j} className="px-4 py-2">{cell}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>

      {/* 移动端卡片式显示 */}
      <div className="md:hidden space-y-4">
        {rows.map((row, i) => (
          <div key={i} className="bg-white p-4 rounded-lg shadow">
            {row.map((cell, j) => (
              <div key={j} className="flex justify-between py-2 border-b last:border-0">
                <span className="font-medium text-gray-600">{headers[j]}</span>
                <span>{cell}</span>
              </div>
            ))}
          </div>
        ))}
      </div>
    </>
  );
}

Touch-Friendly Targets

触控友好的交互目标

css
/* Minimum touch target size: 44x44px */
.touch-target {
  min-height: 44px;
  min-width: 44px;
}

/* Tailwind equivalent */
@layer components {
  .btn-touch {
    @apply min-h-[44px] min-w-[44px] px-4 py-2;
  }
}
html
<!-- Buttons with proper touch targets -->
<button class="min-h-[44px] min-w-[44px] px-4 py-2 bg-blue-500 text-white rounded">
  Click Me
</button>

<!-- Links with padding for touch -->
<a href="#" class="inline-block py-3 px-4">
  Touch-friendly link
</a>
css
/* 最小触控目标尺寸:44x44px */
.touch-target {
  min-height: 44px;
  min-width: 44px;
}

/* Tailwind等效实现 */
@layer components {
  .btn-touch {
    @apply min-h-[44px] min-w-[44px] px-4 py-2;
  }
}
html
<!-- 具备合适触控区域的按钮 -->
<button class="min-h-[44px] min-w-[44px] px-4 py-2 bg-blue-500 text-white rounded">
  点击我
</button>

<!-- 带内边距的触控友好链接 -->
<a href="#" class="inline-block py-3 px-4">
  触控友好链接
</a>

Responsive Spacing

响应式间距

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        // Fluid spacing
        'fluid-1': 'clamp(0.25rem, 0.5vw, 0.5rem)',
        'fluid-2': 'clamp(0.5rem, 1vw, 1rem)',
        'fluid-4': 'clamp(1rem, 2vw, 2rem)',
        'fluid-8': 'clamp(2rem, 4vw, 4rem)',
        'fluid-16': 'clamp(4rem, 8vw, 8rem)',
      },
    },
  },
};
html
<!-- Section with fluid spacing -->
<section class="py-fluid-8 px-fluid-4">
  <h2 class="mb-fluid-4">Section Title</h2>
  <p>Content with responsive spacing</p>
</section>
javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        // 流式间距
        'fluid-1': 'clamp(0.25rem, 0.5vw, 0.5rem)',
        'fluid-2': 'clamp(0.5rem, 1vw, 1rem)',
        'fluid-4': 'clamp(1rem, 2vw, 2rem)',
        'fluid-8': 'clamp(2rem, 4vw, 4rem)',
        'fluid-16': 'clamp(4rem, 8vw, 8rem)',
      },
    },
  },
};
html
<!-- 带流式间距的区块 -->
<section class="py-fluid-8 px-fluid-4">
  <h2 class="mb-fluid-4">区块标题</h2>
  <p>带响应式间距的内容</p>
</section>

Testing Responsive Designs

响应式设计测试

Device Testing Checklist

设备测试清单

markdown
undefined
markdown
undefined

Viewport Testing

视口测试

  • 320px (iPhone SE)
  • 375px (iPhone 12/13)
  • 390px (iPhone 14 Pro)
  • 428px (iPhone 14 Pro Max)
  • 768px (iPad)
  • 1024px (iPad Pro / Small laptop)
  • 1280px (Laptop)
  • 1440px (Desktop)
  • 1920px (Full HD)
  • 2560px (QHD)
  • 320px(iPhone SE)
  • 375px(iPhone 12/13)
  • 390px(iPhone 14 Pro)
  • 428px(iPhone 14 Pro Max)
  • 768px(iPad)
  • 1024px(iPad Pro / 小屏笔记本)
  • 1280px(笔记本电脑)
  • 1440px(台式机)
  • 1920px(全高清)
  • 2560px(2K)

Orientation Testing

横竖屏测试

  • Portrait mode
  • Landscape mode
  • 竖屏模式
  • 横屏模式

Interaction Testing

交互测试

  • Touch interactions
  • Hover states (mouse)
  • Keyboard navigation
undefined
  • 触控交互
  • 悬停状态(鼠标)
  • 键盘导航
undefined

Best Practices

最佳实践

  1. Mobile-first: Start with mobile styles, enhance for larger screens
  2. Use relative units:
    rem
    ,
    em
    ,
    %
    ,
    vw/vh
    over
    px
  3. Test real devices: Emulators don't catch everything
  4. Fluid over fixed: Use
    clamp()
    for smooth scaling
  5. Container queries: For component-level responsiveness
  6. Touch targets: Minimum 44x44px for interactive elements
  7. Content priority: Show most important content first on mobile
  8. Performance: Serve appropriate image sizes
  1. 移动优先:从移动端样式开始,为大屏设备增强效果
  2. 使用相对单位:优先使用
    rem
    em
    %
    vw/vh
    而非
    px
  3. 真机测试:模拟器无法覆盖所有场景
  4. 流式优于固定:使用
    clamp()
    实现平滑缩放
  5. 容器查询:实现组件级别的响应能力
  6. 触控目标:交互元素最小尺寸为44x44px
  7. 内容优先级:移动端优先展示最重要的内容
  8. 性能优化:提供合适尺寸的图片

Output Checklist

输出检查清单

Every responsive implementation should include:
  • Mobile-first approach
  • Breakpoints defined and consistent
  • Fluid typography with clamp()
  • Container queries for components
  • Responsive images with srcset
  • Touch-friendly tap targets (44px+)
  • Tested on real devices
  • Horizontal scroll prevented
  • Navigation adapts to screen size
  • Tables readable on mobile
每个响应式实现都应包含:
  • 移动优先的实现方式
  • 定义一致的断点
  • 使用clamp()的流式排版
  • 组件级别的容器查询
  • 带srcset的响应式图片
  • 44px+的触控友好交互目标
  • 真机测试验证
  • 避免横向滚动
  • 适配屏幕尺寸的导航
  • 移动端可读的表格