关于 screenshot
screenshot 是帮助团队通过截图验证 UI 变更的技能,提供不同视口的截图流程、视觉对比和自动化截图测试,以辅助评审并发现响应式问题。
主要功能
- 01桌面、平板和手机截图指南
- 02变更前后视觉对比
- 03Playwright 与 Puppeteer 截图示例
- 04自动化视觉回归测试
- 05截图整理与 PR 检查清单
适用场景
- 01评审 pull request 中的视觉变更
- 02检查不同视口下的响应式布局
- 03记录修复前后的 UI 状态
- 04在 CI 中加入截图检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill screenshot安装后在 Claude Code 中输入/screenshot确认已加载。
附带文件metadata.json
详细介绍
基于截图的 UI 验证
用于 UI 更改的视觉验证工作流,可加快代码审查并及早发现响应式设计问题。
何时使用此技能
在以下情况下使用此技能:
- 进行任何 UI 更改(组件、样式、布局)
- 实现响应式设计
- 创建包含视觉更改的拉取请求
- 希望展示 UI 行为,而无需审查者在本地运行代码
- 需要记录错误修复前后的视觉状态
截图验证为何重要
优势
- 加快审查:审查者无需在本地设置环境,即可立即查看更改
- 记录设计:留下设计决策的视觉记录
- 视觉变更日志:记录 UI 的演变历程
- 发现响应式问题:及早发现手机和平板设备上的问题
- 减少沟通:减少围绕视觉更改的来回沟通
- 质量关卡:促使人们有意识地检查视觉效果
解决的问题
- ❌“我无法在本地复现布局问题”
- ❌“手机上的效果是什么样的?”
- ❌“这是预期的设计吗?”
- ❌“这与旧版本相比如何?”
- ✅ 这些问题都可以通过拉取请求中的截图得到解答
所需截图
对于任何更改 UI 的拉取请求,请捕获以下三种视口尺寸的截图:
1. 桌面视图(1920x1080)
- 整页截图
- 如有需要,提供关键组件的特写
- 修复或重构前后的对比
- 不同状态(默认、悬停、激活、错误、加载中)
2. 平板视图(768x1024)
- 纵向
- 验证响应式断点
- 显示触控交互目标
- 平板模式下的菜单/导航
3. 手机视图(375x667)
- 纵向(iPhone 8/SE 尺寸——常见的最小尺寸)
- 显示触控目标尺寸(最小为 44x44px)
- 记录滚动行为
- 手机菜单状态
如何捕获截图
浏览器开发者工具方法
Chrome/Edge 开发者工具:
- 打开开发者工具(F12 或 Cmd+Option+I)
- 切换设备工具栏(Cmd+Shift+M 或 Ctrl+Shift+M)
- 选择设备预设或自定义尺寸:
- 桌面:1920 x 1080
- 平板:768 x 1024
- 手机:375 x 667
- 捕获截图:
- 整页:Cmd+Shift+P → “Capture full size screenshot”
- 仅视口:Cmd+Shift+P → “Capture screenshot”
Firefox 开发者工具:
- 打开开发者工具(F12)
- 切换响应式设计模式(Cmd+Option+M)
- 设置尺寸
- 点击工具栏中的截图图标
命令行截图工具
使用 Playwright(推荐用于 CI):
// screenshot.js
const { chromium } = require('playwright');
async function captureScreenshots(url) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
// Desktop
await page.setViewportSize({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewportSize({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
运行:node screenshot.js
使用 Puppeteer:
// screenshot.js
const puppeteer = require('puppeteer');
async function captureScreenshots(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// Desktop
await page.setViewport({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewport({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewport({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
拉取请求描述模板
使用此模板记录视觉更改:
## Visual Changes
### Desktop (1920x1080)

**Key changes**:
- Updated header navigation layout
- Improved spacing between sections
- Added hover states to buttons
### Tablet (768x1024)

**Key changes**:
- Stacked layout for sidebar
- Touch-friendly button sizes (48x48px)
- Adjusted typography for readability
### Mobile (375x667)

**Key changes**:
- Hamburger menu replaces horizontal nav
- Single column layout
- Bottom sticky CTA button
### Before/After Comparison
#### Before (Bug)

**Issue**: Text overflowing container on mobile
#### After (Fixed)

**Fix**: Applied word-wrap and max-width constraints
### Interaction States
#### Default State

#### Hover State

#### Active/Selected State

#### Error State

#### Loading State

## Responsive Design Notes
- Breakpoints: 768px (tablet), 375px (mobile)
- All touch targets > 44x44px
- Text remains readable at all sizes (min 16px body)
- No horizontal scrolling on any viewport
- Images scale proportionally
## Accessibility Checks
- [ ] Keyboard navigation works
- [ ] Focus states visible
- [ ] Color contrast meets WCAG AA (4.5:1)
- [ ] Alt text on images
- [ ] ARIA labels where needed
自动化截图测试
使用 Playwright Test
// tests/visual.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Visual Regression', () => {
test('homepage looks correct on desktop', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 1920, height: 1080 });
await expect(page).toHaveScreenshot('homepage-desktop.png');
});
test('homepage looks correct on mobile', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 375, height: 667 });
await expect(page).toHaveScreenshot('homepage-mobile.png');
});
});
运行:npx playwright test --update-snapshots(首次运行以生成基准截图)
使用 Storybook + Chromatic
用于组件级视觉测试:
- 设置 Storybook:
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
};
export const Primary = () => <Button variant="primary">Click me</Button>;
export const Secondary = () => <Button variant="secondary">Click me</Button>;
- 集成 Chromatic:
npm install --save-dev chromatic
npx chromatic --project-token=<token>
- CI 集成(GitHub Actions):
# .github/workflows/chromatic.yml
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx chromatic --project-token=${{ secrets.CHROMATIC_TOKEN }}
截图检查清单
提交包含 UI 更改的拉取请求前:
捕获要求
- 已捕获桌面截图(1920x1080)
- 已捕获平板截图(768x1024)
- 已捕获手机截图(375x667)
- 所有截图均已上传至拉取请求
- 已附上修复错误前后的对比(针对错误修复)
质量检查
- 截图显示完整页面(没有被截断)
- 截图中没有显示 localhost URL
- 截图中没有敏感数据(PII、密钥等)
- 截图清晰易读
- 文件名具有描述性(例如:
desktop-homepage.png)
文档
- 列出每种视口下的关键更改
- 描述响应式行为
- 包含无障碍说明
- 记录交互状态(如适用)
常见问题及解决方案
问题:截图过大
问题:截图大小达到 5MB 以上,在拉取请求中加载缓慢
解决方案:上传前压缩图片
# Using ImageMagick
convert input.png -quality 85 output.png
# Using pngquant
pngquant input.png --output output.png
问题:屏幕截图之间的动态内容发生变化
问题:时间戳、随机数据会导致屏幕截图不一致 解决方案:使用模拟数据,或在测试中冻结时间
// Mock Date
const mockDate = new Date('2025-01-01T00:00:00Z');
jest.useFakeTimers();
jest.setSystemTime(mockDate);
// Or in Playwright
await page.addInitScript(() => {
Date.now = () => 1704067200000; // Fixed timestamp
});
问题:屏幕截图差异显示字体渲染不同
问题:相同的代码在不同操作系统上的渲染效果不同 解决方案:使用 Docker 确保环境一致
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npm", "run", "screenshot"]
屏幕截图整理
目录结构
screenshots/
├── desktop/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
├── tablet/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
└── mobile/
├── homepage.png
├── product-list.png
└── checkout.png
命名规范
- 使用描述性名称:
desktop-homepage-logged-in.png - 相关时注明状态:
mobile-form-error-state.png - 对比版本:
before-header-fix.png、after-header-fix.png
与 CI/CD 集成
GitHub Actions 示例
name: Visual Testing
on: pull_request
jobs:
screenshots:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Start app
run: npm start &
- name: Wait for app
run: npx wait-on http://localhost:3000
- name: Capture screenshots
run: node scripts/screenshot.js
- name: Upload screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: screenshots/
最佳实践
应做事项
- ✅ 截取三种视口尺寸的屏幕截图
- ✅ 修复 Bug 时提供修复前后的截图
- ✅ 记录交互状态(悬停、激活、错误)
- ✅ 压缩大型图像
- ✅ 使用描述性文件名
- ✅ 在屏幕截图中标注关键更改
不应做事项
- ❌ 跳过移动端屏幕截图(“仅限桌面端”的情况很少)
- ❌ 上传包含敏感数据的屏幕截图
- ❌ 使用随机视口尺寸(坚持使用标准尺寸)
- ❌ 忘记记录响应式断点
- ❌ 只依赖屏幕截图(仍需进行代码审查)
相关技能
universal-verification-pre-merge- 合并前验证清单universal-testing-webapp-testing- Web 应用测试模式toolchains-javascript-testing-playwright- Playwright 测试框架universal-debugging-verification-before-completion- 验证工作流
评论
支持 Markdown