mcpField
R
responsive-design-system

responsive-design-system

github.com/patricio0312rev设计与 UI63344 次安装41 周前更新
代码仓库

关于 responsive-design-system

用于使用 CSS 和 Tailwind 构建移动优先响应式布局的技能,涵盖断点、流式尺寸、容器查询、自适应组件和视口测试。

主要功能

  1. 01定义响应式断点
  2. 02流式调整字体与间距
  3. 03使用容器查询
  4. 04构建自适应布局与组件
  5. 05应用响应式图片模式
  6. 06测试不同视口尺寸

适用场景

  1. 01创建适用于手机到桌面的布局
  2. 02让卡片根据容器调整
  3. 03检查移动端表格和触控区域

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patricio0312rev/skills --skill responsive-design-system

安装后在 Claude Code 中输入/responsive-design-system确认已加载。

详细介绍

响应式设计系统

使用现代 CSS 特性和 Tailwind 构建自适应、移动优先的布局。

核心工作流

  1. 定义断点:建立响应式断点系统
  2. 设置流体排版:使用基于 Clamp 的响应式字体
  3. 创建布局网格:构建响应式网格系统
  4. 添加容器查询:实现组件级响应
  5. 构建响应式组件:采用自适应模式
  6. 跨设备测试:在所有视口中验证

断点系统

Tailwind 默认断点
断点最小宽度目标设备
sm640px大屏手机(横屏)
md768px平板电脑
lg1024px笔记本电脑
xl1280px台式电脑
2xl1536px大屏幕
自定义断点
// 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)' },
    },
  },
};

流体排版

CSS Clamp 函数
/* 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);
}
Tailwind 流体排版
// 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)',
      },
    },
  },
};
用法
<h1 class="text-fluid-4xl font-bold">Responsive Headline</h1>
<p class="text-fluid-base">Body text that scales smoothly.</p>

容器查询

启用容器查询
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      containers: {
        'xs': '320px',
        'sm': '384px',
        'md': '448px',
        'lg': '512px',
        'xl': '576px',
        '2xl': '672px',
      },
    },
  },
};
容器查询用法

<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">Card Title</h2>
    </div>
    <div class="@md:w-1/2">
      <p class="text-sm @lg:text-base">Card content</p>
    </div>
  </div>
</div>


<div class="@container/main">
  <div class="@lg/main:grid-cols-3">...</div>
</div>
响应式卡片组件
// 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>
  );
}

响应式网格布局

自动适配网格

<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
  
</div>


<div class="grid gap-6" style="grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))">
  
</div>
仪表板布局
// 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>
  );
}
圣杯布局
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>
  );
}

响应式图像

Srcset 和 Sizes
<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
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>
  );
}
使用 Picture 实现艺术指导
<picture>
  
  <source
    media="(max-width: 639px)"
    srcset="/images/hero-mobile.jpg"
  />
  
  <source
    media="(max-width: 1023px)"
    srcset="/images/hero-tablet.jpg"
  />
  
  <img
    src="/images/hero-desktop.jpg"
    alt="Hero"
    class="w-full h-auto"
  />
</picture>

响应式导航

移动端菜单模式
'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>
  );
}

响应式表格

横向滚动
<div class="overflow-x-auto">
  <table class="min-w-full">
    
  </table>
</div>
移动端堆叠显示
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>
    </>
  );
}

触控友好的目标区域

/* 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;
  }
}

<button class="min-h-[44px] min-w-[44px] px-4 py-2 bg-blue-500 text-white rounded">
  Click Me
</button>


<a href="#" class="inline-block py-3 px-4">
  Touch-friendly link
</a>

响应式间距

// 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)',
      },
    },
  },
};

<section class="py-fluid-8 px-fluid-4">
  <h2 class="mb-fluid-4">Section Title</h2>
  <p>Content with responsive spacing</p>
</section>

测试响应式设计

设备测试清单
## 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)

## Orientation Testing

- [ ] Portrait mode
- [ ] Landscape mode

## Interaction Testing

- [ ] Touch interactions
- [ ] Hover states (mouse)
- [ ] Keyboard navigation

最佳实践

  1. 移动优先:从移动端样式开始,再为更大屏幕增强样式
  2. 使用相对单位:优先使用 rem、em、%、vw/vh,而非 px
  3. 在真实设备上测试:模拟器无法发现所有问题
  4. 使用流体尺寸而非固定尺寸:使用 clamp() 实现平滑缩放
  5. 容器查询:用于组件级响应
  6. 触控目标:交互元素的最小尺寸为 44x44px
  7. 内容优先级:在移动端优先显示最重要的内容
  8. 性能:提供尺寸合适的图像

输出检查清单

每个响应式实现都应包含:

  • 移动优先方案
  • 已定义且保持一致的断点
  • 使用 clamp() 实现流体排版
  • 组件使用容器查询
  • 使用 srcset 提供响应式图像
  • 触控友好的点击目标(44px 及以上)
  • 已在真实设备上测试
  • 防止横向滚动
  • 导航可适配屏幕尺寸
  • 表格在移动端易于阅读

评论

支持 Markdown