Аудит руководств по веб-дизайну интерфейсов
Чему вы научитесь
- 🎯 Позволить AI автоматически анализировать UI-код, обнаруживая проблемы доступности, производительности и UX
- ♿ Применять лучшие практики Web Accessibility (WCAG), повышая доступность сайта
- ⚡ Оптимизировать производительность анимации и загрузку изображений, улучшая пользовательский опыт
- 🎨 Обеспечить правильную реализацию темного режима и адаптивного дизайна
- 🔍 Исправлять распространенные UI-антипаттерны (например,
transition: all, отсутствие aria-label и другие)
Текущие проблемы
Вы написали UI-компоненты, но чувствуете, что что-то не так:
- Сайт прошел функциональные тесты, но неясно, соответствует ли он стандартам доступности
- Плохая производительность анимации, пользователи сообщают о лагах на странице
- В темном режиме некоторые элементы трудно различимы
- Код, сгенерированный AI, работает, но отсутствуют необходимые aria-labels или семантический HTML
- Каждый раз при анализе кода вручную проверяете 17 категорий правил, низкая эффективность
- Не знаете, когда использовать CSS-свойства
prefers-reduced-motion,tabular-numsи другие
На самом деле, инженерная команда Vercel уже разработала набор из 100 руководств по веб-дизайну интерфейсов, охватывающих все сценарии от доступности до оптимизации производительности. Теперь эти правила упакованы в Agent Skills, и вы можете позволить AI автоматически помогать вам анализировать и исправлять UI-проблемы.
Что такое "Web Interface Guidelines"
Web Interface Guidelines — это коллекция стандартов качества UI от Vercel, содержащая 100 правил в 17 категориях. Эти правила основаны на стандартах доступности WCAG, лучших практиках производительности и принципах UX-дизайна, обеспечивая, чтобы качество веб-приложений соответствовало производственному уровню.
Когда использовать этот метод
Типичные сценарии использования навыков руководств по веб-дизайну:
- ❌ Не применимо: чисто серверная логика, простые прототипы страниц (без пользовательского взаимодействия)
- ✅ Применимо:
- Написание новых UI-компонентов (кнопки, формы, карточки и другие)
- Реализация интерактивных функций (модальные окна, выпадающие меню, перетаскивание и другие)
- Анализ или рефакторинг UI-компонентов
- Проверка качества UI перед запуском
- Исправление проблем доступности или производительности, о которых сообщили пользователи
🎒 Подготовка перед началом
Предварительная проверка
Перед началом убедитесь, что вы:
- Установили Agent Skills (см. Руководство по установке)
- Знакомы с основами HTML/CSS/React
- Имеете UI-проект для аудита (может быть один компонент или вся страница)
Основная идея
Руководства по веб-дизайну интерфейсов охватывают 17 категорий, разделенных по приоритетам на три блока:
| Блок категорий | Фокус | Типичная отдача |
|---|---|---|
| Доступность (Accessibility) | Обеспечить доступность для всех пользователей (включая экранное чтение, клавиатуру) | Соответствие стандартам WCAG, расширение аудитории |
| Производительность & UX (Performance & UX) | Оптимизация скорости загрузки, плавности анимации, взаимодействия | Повышение удержания пользователей, снижение отказов |
| Полнота & Детали (Completeness) | Темный режим, адаптивность, валидация форм, обработка ошибок | Снижение жалоб пользователей, повышение бренда |
17 категорий правил:
| Категория | Типичное правило | Приоритет |
|---|---|---|
| Accessibility | aria-labels, семантический HTML, обработка клавиатуры | ⭐⭐⭐ Высший |
| Focus States | Видимый фокус, :focus-visible вместо :focus | ⭐⭐⭐ Высший |
| Forms | autocomplete, валидация, обработка ошибок | ⭐⭐⭐ Высший |
| Animation | prefers-reduced-motion, transform/opacity | ⭐⭐ Высокий |
| Typography | curly quotes, ellipsis, tabular-nums | ⭐⭐ Высокий |
| Content Handling | усечение текста, обработка пустых состояний | ⭐⭐ Высокий |
| Images | dimensions, lazy loading, alt text | ⭐⭐ Высокий |
| Performance | virtualization, предподключение, пакетная обработка DOM | ⭐⭐ Высокий |
| Navigation & State | URL отражает состояние, глубокие ссылки | ⭐⭐ Высокий |
| Touch & Interaction | touch-action, tap-highlight | ⭐ Средний |
| Safe Areas & Layout | безопасные области, обработка полос прокрутки | ⭐ Средний |
| Dark Mode & Theming | color-scheme, theme-color meta | ⭐ Средний |
| Locale & i18n | Intl.DateTimeFormat, Intl.NumberFormat | ⭐ Средний |
| Hydration Safety | value + onChange, предотвращение несоответствия ячеек | ⭐ Средний |
| Hover & Interactive States | hover-состояние, повышение контрастности | ⭐ Средний |
| Content & Copy | активный залог, конкретные метки кнопок | ⭐ Низкий |
| Anti-patterns | пометка распространенных ошибочных шаблонов | ⭐⭐⭐ Высший |
Основные принципы:
- Сначала исправляйте проблемы категории Accessibility — эти влияют на использование пользователями с ограниченными возможностями
- Проблемы производительности начинайте с анимации и изображений — это напрямую влияет на пользовательский опыт
- Проблемы полноты проверяйте в последнюю очередь — темный режим, интернационализация и другие детали
Следуйте за мной
Шаг 1: Запуск AI-аудита UI
Откройте ваш UI-проект (может быть один файл компонента или весь каталог), введите в Claude или Cursor:
Review my UI components for accessibility and UX issuesили
Check accessibility of my siteили
Audit design and apply Web Interface GuidelinesВы должны увидеть: AI активирует навык web-design-guidelines и загрузит последние 100 правил с GitHub.
Шаг 2: Укажите файлы для аудита (если AI не обнаружил автоматически)
Если AI спрашивает, какие файлы нужно проанализировать, вы можете:
# Аудит одного файла
src/components/Button.tsx
# Аудит нескольких файлов (через пробел)
src/components/Button.tsx src/components/Input.tsx
# Аудит всего каталога (с glob-шаблоном)
src/components/**/*.tsxШаг 3: AI автоматически обнаруживает проблемы
AI будет проверять код построчно, выводя результаты аудита в формате file:line после обнаружения проблем. Например:
// ❌ Ваш исходный код (с проблемой)
export function Button({ icon, onClick }: ButtonProps) {
return (
<button
onClick={onClick}
className="p-2 rounded hover:bg-gray-100 transition-all"
>
{icon}
</button>
)
}Результаты аудита AI:
## src/components/Button.tsx
src/components/Button.tsx:8 - icon button missing aria-label
src/components/Button.tsx:8 - animation missing prefers-reduced-motion
src/components/Button.tsx:8 - transition: all → list properties explicitly
src/components/Button.tsx:8 - button needs visible focusИсправленный код от AI:
// ✅ После исправления
export function Button({ icon, onClick, ariaLabel }: ButtonProps) {
return (
<button
onClick={onClick}
aria-label={ariaLabel}
className="p-2 rounded hover:bg-gray-100
transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-blue-500
motion-safe:hover:scale-105 active:scale-100
motion-reduce:transition-none motion-reduce:transform-none"
>
{icon}
</button>
)
}Шаг 4: Примеры распространенных проблем
Проблема 1: Форма ввода без label и autocomplete
// ❌ Ошибка: отсутствие label и autocomplete
<input
type="text"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>// ✅ Правильно: включает label, name, autocomplete
<label htmlFor="email" className="sr-only">
Email address
</label>
<input
id="email"
type="email"
name="email"
autoComplete="email"
placeholder="your@email.com…"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>Правила:
Form Controls need <label> or aria-labelInputs need autocomplete and meaningful nameUse correct type (email, tel, url, number) and inputmode
Проблема 2: Анимация не учитывает prefers-reduced-motion
/* ❌ Ошибка: все пользователи видят анимацию, неудобно для пользователей с вестибулярными расстройствами */
.modal {
transition: all 0.3s ease-in-out;
}/* ✅ Правильно: уважение предпочтения пользователя по уменьшению анимации */
.modal {
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
.modal {
transition: none;
}
}Правила:
Honor prefers-reduced-motion (provide reduced variant or disable)Never transition: all—list properties explicitly
Проблема 3: Изображения без dimensions и lazy loading
// ❌ Ошибка: вызывает Cumulative Layout Shift (CLS)
<img src="/hero.jpg" alt="Hero image" />// ✅ Правильно: заранее резервируем пространство, предотвращая скачок макета
<img
src="/hero.jpg"
alt="Hero: team working together"
width={1920}
height={1080}
loading="lazy"
fetchpriority="high" // для ключевых изображений выше сгиба
/>Правила:
<img> needs explicit width and height (prevents CLS)Below-fold images: loading="lazy"Above-fold critical images: priority or fetchpriority="high"
Проблема 4: Темный режим без color-scheme
<!-- ❌ Ошибка: в темном режиме нативные элементы управления (например, select, input) все еще с белым фоном -->
<html>
<body>
<select>...</select>
</body>
</html><!-- ✅ Правильно: нативные элементы управления автоматически адаптируются к темной теме -->
<html class="dark">
<head>
<meta name="theme-color" content="#0f172a" />
</head>
<body style="color-scheme: dark">
<select style="background-color: #1e293b; color: #e2e8f0">
...
</select>
</body>
</html>Правила:
color-scheme: dark on <html> for dark themes (fixes scrollbar, inputs)<meta name="theme-color"> matches page backgroundNative <select>: explicit background-color and color (Windows dark mode)
Проблема 5: Неполная поддержка клавиатурной навигации
// ❌ Ошибка: только мышью можно кликнуть, пользователи клавиатуры не могут использовать
<div onClick={handleClick} className="cursor-pointer">
Click me
</div>// ✅ Правильно: поддержка клавиатурной навигации (Enter/Space активирует)
<button
onClick={handleClick}
className="cursor-pointer"
// автоматически поддерживает клавиатуру, дополнительный код не нужен
>
Click me
</button>
// или если нужно использовать div, добавьте поддержку клавиатуры:
<div
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault()
handleClick()
}
}}
onClick={handleClick}
className="cursor-pointer"
>
Click me
</div>Правила:
Interactive elements need keyboard handlers (onKeyDown/onKeyUp)<button>for actions,<a>/<Link>for navigation (not<div onClick>)Icon-only buttons need aria-label
Проблема 6: Длинные списки без виртуализации
// ❌ Ошибка: рендеринг 1000 элементов вызывает лаги страницы
function UserList({ users }: { users: User[] }) {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}// ✅ Правильно: использование виртуальной прокрутки, рендер только видимых элементов
import { useVirtualizer } from '@tanstack/react-virtual'
function UserList({ users }: { users: User[] }) {
const parentRef = useRef<HTMLUListElement>(null)
const virtualizer = useVirtualizer({
count: users.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 40, // высота каждого элемента
overscan: 5, // предрендер нескольких элементов для предотвращения пробелов
})
return (
<ul ref={parentRef} className="h-96 overflow-auto">
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map((virtualItem) => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${virtualItem.start}px)`,
}}
>
{users[virtualItem.index].name}
</div>
))}
</div>
</ul>
)
}Правила:
Large lists (>50 items): virtualize (virtua, content-visibility: auto)
Проблема 7: Числовые столбцы без tabular-nums
/* ❌ Ошибка: ширина цифр не фиксирована, вызывает скачок выравнивания */
.table-cell {
font-family: system-ui;
}/* ✅ Правильно: цифры моноширинные, выравнивание стабильное */
.table-cell.number {
font-variant-numeric: tabular-nums;
}Правила:
font-variant-numeric: tabular-nums for number columns/comparisons
Шаг 5: Исправление распространенных антипаттернов
AI автоматически пометит эти антипаттерны:
// ❌ Коллекция антипаттернов
const BadComponent = () => (
<div>
{/* Антипаттерн 1: transition: all */}
<div className="transition-all hover:scale-105">...</div>
{/* Антипаттерн 2: кнопка с иконкой без aria-label */}
<button onClick={handleClose}>✕</button>
{/* Антипаттерн 3: запрет вставки */}
<Input onPaste={(e) => e.preventDefault()} />
{/* Антипаттерн 4: outline-none без фокуса-замены */}
<button className="focus:outline-none">...</button>
{/* Антипаттерн 5: изображения без dimensions */}
<img src="/logo.png" alt="Logo" />
{/* Антипаттерн 6: использование div вместо button */}
<div onClick={handleClick}>Submit</div>
{/* Антипаттерн 7: жестко заданный формат даты */}
<Text>{formatDate(new Date(), 'MM/DD/YYYY')}</Text>
{/* Антипаттерн 8: autofocus на мобильных устройствах */}
<input autoFocus />
{/* Антипаттерн 9: user-scalable=no */}
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
{/* Антипаттерн 10: большие списки без виртуализации */}
{largeList.map((item) => (<Item key={item.id} {...item} />))}
</div>
)// ✅ После исправления
const GoodComponent = () => (
<div>
{/* Исправление 1: явный список переходных свойств */}
<div className="transition-transform hover:scale-105">...</div>
{/* Исправление 2: кнопка с иконкой включает aria-label */}
<button onClick={handleClose} aria-label="Close dialog">✕</button>
{/* Исправление 3: разрешение вставки */}
<Input />
{/* Исправление 4: использование focus-visible кольца */}
<button className="focus:outline-none focus-visible:ring-2">...</button>
{/* Исправление 5: изображения включают dimensions */}
<img src="/logo.png" alt="Logo" width={120} height={40} />
{/* Исправление 6: использование семантической button */}
<button onClick={handleClick}>Submit</button>
{/* Исправление 7: использование Intl форматирования */}
<Text>{new Intl.DateTimeFormat('en-US').format(new Date())}</Text>
{/* Исправление 8: autoFocus только на десктопе */}
<input autoFocus={isDesktop} />
{/* Исправление 9: разрешение масштабирования */}
<meta name="viewport" content="width=device-width, initial-scale=1" />
{/* Исправление 10: виртуализация */}
<VirtualList items={largeList}>{(item) => <Item {...item} />}</VirtualList>
</div>
)Контрольная точка ✅
После выполнения вышеуказанных шагов проверьте, освоили ли вы:
- [ ] Знать, как запустить AI-аудит руководств по веб-дизайну
- [ ] Понимать важность доступности (Accessibility) (высший приоритет Accessibility)
- [ ] Знать, как добавить aria-label и семантический HTML
- [ ] Понимать роль
prefers-reduced-motion - [ ] Знать, как оптимизировать загрузку изображений (dimensions, lazy loading)
- [ ] Понимать правильную реализацию темного режима (
color-scheme) - [ ] Уметь распознавать распространенные UI-антипаттерны в коде
На что обратить внимание
Проблема 1: Только визуал, игнорирование доступности
Доступность не опциональна
Доступность — это юридическое требование (например, ADA, WCAG) и социальная ответственность.
Распространенные упущения:
- Кнопки с иконками без
aria-label - Пользовательские элементы управления (например, выпадающие меню) не поддерживают клавиатуру
- Входы форм без
<label> - Асинхронные обновления (например, Toast) без
aria-live="polite"
Проблема 2: Чрезмерное использование transition: all
Убийца производительности
transition: all отслеживает изменения всех CSS-свойств, заставляя браузер пересчитывать множество значений.
Неправильное использование:
.card {
transition: all 0.3s ease; // ❌ будет переходить background, color, transform, padding, margin и т.д.
}Правильное использование:
.card {
transition: transform 0.3s ease, opacity 0.3s ease; // ✅ только нужные свойства
}Проблема 3: Забыть альтернативу outline
::: focus-visible не опционален После удаления стандартного outline необходимо предоставить видимый стиль фокуса, иначе пользователи клавиатуры не будут знать, где фокус.
Неправильная практика:
button {
outline: none; // ❌ полностью удаляет фокус
}Правильная практика:
button {
outline: none; /* удаляет стандартный некрасивый контур */
}
button:focus-visible {
ring: 2px solid blue; /* ✅ добавляет пользовательский стиль фокуса (только при клавиатурной навигации) */
}
button:focus {
/* не отображается при клике мышью (потому что focus-visible = false) */
}:::
Проблема 4: Изображения без alt или dimensions
::: CLS — один из Core Web Vitals Отсутствие width и height вызывает скачок макета при загрузке страницы, влияя на пользовательский опыт и SEO.
Помните:
- Декоративные изображения с
alt=""(пустая строка) - Информативные изображения с описательным
alt(например, "Team photo: Alice and Bob") - Все изображения включают
widthиheight:::
Проблема 5: Интернационализация (i18n) с жестко заданным форматом
::: Используйте Intl API Не жестко задавайте форматы дат, чисел, валют, используйте встроенный API Intl браузера.
Неправильная практика:
const formattedDate = formatDate(date, 'MM/DD/YYYY') // ❌ американский формат, другие страны будут в замешательствеПравильная практика:
const formattedDate = new Intl.DateTimeFormat(undefined, {
dateStyle: 'medium',
}).format(date) // ✅ автоматически использует локаль пользователя:::
Итоги урока
Ключевые принципы руководств по веб-дизайну интерфейсов:
- Доступность приоритет: обеспечить доступность для всех пользователей (клавиатура, экранное чтение)
- Оптимизация производительности: анимации через
transform/opacity, lazy load изображений, виртуализация больших списков - Уважение пользовательских предпочтений:
prefers-reduced-motion,color-scheme, разрешение масштабирования - Семантический HTML: использование
<button>,<label>,<input>вместо<div> - Проверка полноты: темный режим, интернационализация, валидация форм, обработка ошибок
- Автоматический аудит с AI: позвольте Agent Skills помогать вам обнаруживать и исправлять 100 правил
100 правил Vercel охватывают все сценарии от основ до деталей. Научившись запускать AI для применения этих правил, качество вашего UI достигнет производственного уровня.
Следующий урок
Далее мы изучим Развертывание в Vercel одним кликом.
Вы узнаете:
- Как развернуть проект в Vercel одним кликом (поддержка 40+ фреймворков)
- Автоматическое определение типа фреймворка (Next.js, Vue, Svelte и другие)
- Получение ссылок на предварительный просмотр и передачу прав
Приложение: Справочник по исходному коду
Нажмите, чтобы раскрыть расположение исходного кода
Обновлено: 2026-01-25
| Функция | Путь к файлу | Строки |
|---|---|---|
| Определение навыка руководств по веб-дизайну | skills/web-design-guidelines/SKILL.md | Весь файл |
| Источник правил (100) | https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/command.md | Весь файл |
| Обзор README | README.md | 28-50 |
17 категорий правил:
| Категория | Количество правил | Типичное правило |
|---|---|---|
| Accessibility | 10 | aria-labels, семантический HTML, обработка клавиатуры |
| Focus States | 4 | видимый фокус, :focus-visible |
| Forms | 11 | autocomplete, валидация, обработка ошибок |
| Animation | 6 | prefers-reduced-motion, transform/opacity |
| Typography | 6 | curly quotes, ellipsis, tabular-nums |
| Content Handling | 4 | усечение текста, обработка пустых состояний |
| Images | 3 | dimensions, lazy loading, alt text |
| Performance | 6 | virtualization, предподключение, пакетная обработка |
| Navigation & State | 4 | URL отражает состояние, глубокие ссылки |
| Touch & Interaction | 5 | touch-action, tap-highlight |
| Safe Areas & Layout | 3 | безопасные области, обработка полос прокрутки |
| Dark Mode & Theming | 3 | color-scheme, theme-color |
| Locale & i18n | 3 | Intl.DateTimeFormat, Intl.NumberFormat |
| Hydration Safety | 3 | value + onChange, предотвращение несоответствия ячеек |
| Hover & Interactive States | 2 | hover-состояние, контрастность |
| Content & Copy | 7 | активный залог, конкретные метки кнопок |
| Anti-patterns | 20 | пометка распространенных ошибочных шаблонов |
Ключевые константы:
RULE_SOURCE_URL = "https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/command.md": источник загрузки правилversion = "1.0.0": версия навыка (SKILL.md)
Рабочий процесс:
SKILL.md:23-27: загрузка последних правил с GitHubSKILL.md:31-38: чтение файлов пользователя и применение всех правилSKILL.md:39: если файлы не указаны, запрос у пользователя
Ключевые слова запуска:
- "Review my UI"
- "Check accessibility"
- "Audit design"
- "Review UX"
- "Check my site against best practices"