Files

26 KiB
Raw Permalink Blame History

name, title, description, tags, source
name title description tags source
concepts/ux-guidelines-99 99 UX Guidelines 99 practical UX rules with code examples, sorted by category and severity.
ux
guidelines
accessibility
performance
mobile
forms
responsiveness
feedback
ui-ux-pro-max-skill

99 UX Guidelines

Практические правила UX, проверенные на реальных продуктах. Каждое правило содержит: что делать, чего НЕ делать, код-пример.

Severity Legend

Бейдж Значение
🔴 High Критично — влияет на доступность, конверсию, Core Web Vitals
🟡 Medium Важно — ухудшает UX, но не критично
🟢 Low Рекомендуется — мелкое улучшение

Navigation (6 правил)

1. Smooth Scroll — High

Anchor links должны прокручивать плавно к целевому разделу.

html { scroll-behavior: smooth; }

❌ <a href='#section'> без CSS — прыжок

2. Sticky Navigation — Medium

Фиксированная навигация не должна перекрывать контент.

<div class="pt-20"> <!-- если nav height = h-20 -->

❌ Нет компенсации padding

3. Active State — Medium

Текущая страница/секция должна быть визуально обозначена.

<span class="text-primary border-b-2">Home</span>

❌ Все ссылки одного стиля

4. Back Button — High

На мобильных пользователи ожидают предсказуемого «назад».

history.pushState(null, '', '/page');

❌ location.replace() — ломает историю

5. Deep Linking — Medium

URL должны отражать текущее состояние для шаринга.

<!-- /page?sort=price&dir=asc -->

❌ Один URL для всех состояний

6. Breadcrumbs — Low

Показывать путь пользователя в иерархии сайта (3+ уровней).

<nav><ol>
  <li><a href="/">Home</a></li>
  <li><a href="/cat">Category</a></li>
  <li>Product</li>
</ol></nav>

❌ Только на глубоких вложенных страницах


Animation (8 правил)

7. Excessive Motion — High

Слишком много анимаций отвлекают и вызывают укачивание.

✅ Анимировать 1-2 ключевых элемента на экран.

❌ animate-bounce на 5+ элементах

8. Duration Timing — Medium

Анимации должны ощущаться отзывчивыми, а не вялыми.

transition-all duration-200; /* 150-300ms */

❌ duration-1000 для UI

9. Reduced Motion — High

Уважать настройки пользователя о движении.

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

❌ Нет проверки media query

10. Loading States — High

Показывать обратную связь во время асинхронных операций.

<div class="animate-pulse"><div class="h-4 bg-gray-200 rounded w-3/4"></div></div>

❌ Пустой экран во время загрузки

11. Hover vs Tap — High

Hover-эффекты не работают на тач-устройствах.

<button onClick={handler}>Click</button>

❌ Только onMouseEnter для важных действий

12. Continuous Animation — Medium

Бесконечные анимации отвлекают.

✅ animate-spin только на лоадерах.

❌ animate-bounce на иконках

13. Transform Performance — Medium

Некоторые CSS-свойства вызывают дорогостоящие repaints.

transform: translateY(-10px); /* GPU-accelerated */
opacity: 0.8;

❌ Анимация top: 10px — trigger layout

14. Easing Functions — Low

Линейное движение выглядит роботизированным.

transition-timing-function: ease-out; /* вход */
transition-timing-function: ease-in;  /* выход */

❌ linear для UI


Layout (7 правил)

15. Z-Index Management — High

Конфликты stacking context'а прячут элементы.

<div class="z-10"><div class="z-20"></div></div>

❌ z-[9999] — хаос

16. Overflow Hidden — Medium

Скрытый overflow может обрезать контент.

<div class="overflow-auto"><div class="w-max">...</div></div>

❌ overflow-hidden на контейнере с текстом

17. Fixed Positioning — Medium

Фиксированные элементы могут перекрывать друг друга.

<header class="fixed top-0 left-0 right-0 h-20 z-50">
<main class="pt-20">

❌ Несколько overlapping fixed без gap

18. Stacking Context — Medium

Новый stacking context сбрасывает z-index.

<!-- Parent creates new stacking context -->
<div class="relative z-10">
  <div class="z-50"></div> <!-- только внутри parent -->
</div>

❌ z-index: 9999 не работает через контекст

19. Content Jumping — High

Сдвиг layout при загрузке контента — дёргает.

<img src="..." class="aspect-video" alt="..." />

❌ Нет размеров на изображениях — контент прыгает

20. Viewport Units — Medium

100vh проблематичен на мобильных (адресная строка).

<div class="min-h-dvh"> <!-- dynamic viewport height -->

❌ h-screen на мобильных — обрезка контента

21. Container Width — Medium

Слишком широкий текст трудно читать.

<p class="max-w-prose">...</p> <!-- ~65ch -->

❌ Текст на всю ширину viewport


Touch (6 правил)

22. Touch Target Size — High

Маленькие кнопки трудно нажимать точно.

<button class="min-h-[44px] min-w-[44px]">Tap</button>

❌ w-6 h-6 — 24px, ниже минимума

23. Touch Spacing — Medium

Расстояние между тач-целями — минимум 8px.

<button class="gap-2">Buttons</button>

❌ gap-0 или gap-1 между кнопками

24. Gesture Conflicts — Medium

Кастомные жесты могут конфликтовать с системой.

<!-- Vertical scroll primary, horizontal only in carousels -->
<div class="overflow-x-auto overflow-y-visible">

❌ Горизонтальный свайп на основном контенте

25. Tap Delay — Medium

300ms tap delay ощущается как лаг.

button { touch-action: manipulation; }

❌ Нет touch-оптимизации — 300ms задержка

26. Pull to Refresh — Low

Случайное обновление — раздражает.

<body style="overscroll-behavior: contain;">

❌ Стандартное поведение (pull-down на всём)

27. Haptic Feedback — Low

Тактильная обратная связь улучшает взаимодействие.

if ('vibrate' in navigator) navigator.vibrate(10);

❌ Вибрация при каждом тапе


Interaction (8 правил)

28. Focus States — High

Клавиатурные пользователи видят фокус только через visible focus.

<button class="focus:ring-2 focus:ring-blue-500">

❌ outline-none без замены

29. Hover States — Medium

Визуальная обратная связь на интерактивных элементах.

<button class="hover:bg-gray-100 cursor-pointer">

❌ Нет hover-стиля на кликабельных элементах

30. Active States — Medium

Немедленная обратная связь при нажатии.

<button class="active:scale-95 transition-transform">

❌ Нет active state

31. Disabled States — Medium

Чётко указывать неинтерактивные элементы.

<button disabled class="opacity-50 cursor-not-allowed">

❌ Disabled выглядит как enabled

32. Loading Buttons — High

Предотвращать двойную отправку формы.

<button disabled={loading} className={loading ? 'animate-pulse' : ''}>
  {loading ? 'Processing...' : 'Submit'}
</button>

❌ Кнопка кликабельна во время загрузки

33. Error Feedback — High

Пользователь должен знать об ошибке.

<div class="text-red-600 text-sm mt-1">Invalid email</div>

❌ Тихий fail — нет индикации

34. Success Feedback — Medium

Подтверждать успешные действия.

<div className="text-green-600 flex items-center gap-2">
  <CheckIcon /> Saved successfully
</div>

❌ Действие завершается без подтверждения

35. Confirmation Dialogs — High

Подтверждать деструктивные действия.

<button onClick={() => setShowModal(true)}>Delete</button>
<!-- Modal: Are you sure? -->

❌ Удаление без подтверждения


Accessibility (10 правил)

36. Color Contrast — High

Текст должен быть читаемым на фоне.

/* #333 on white = 7:1 ✅ | #999 on white = 2.8:1 ❌ */
.color { color: #333333; background: #ffffff; }

❌ #999 на #ffffff — fails WCAG AA

37. Color Only — High

Не передавать информацию только цветом.

<span class="text-red-600">
  <AlertIcon /> Error: insufficient funds
</span>

❌ Только красная рамка без текста

38. Alt Text — High

У изображений должен быть текстовый эквивалент.

<img src="dog.jpg" alt="Dog playing in park" />

❌ alt="" для контентных изображений

39. Heading Hierarchy — Medium

Экранные читалки используют заголовки для навигации.

<h1>Home</h1><h2>About</h2><h3>Team</h3>

❌ h1 → h4 — пропуск уровней

40. ARIA Labels — High

Интерактивные элементы нужны доступные имена.

<button aria-label="Close menu"><X /></button>

❌ <button><Icon/></button> без aria-label

41. Keyboard Navigation — High

Весь функционал доступен через клавиатуру.

<a href="#" tabindex="0">Link</a>

❌ Недоступные элементы (tabindex не совпадает с визуальным порядком)

42. Screen Reader — Medium

Контент должен иметь смысл при чтении вслух.

<nav>...</nav><main>...</main><article>...</article>

❌ <div> для всего — "div soup"

43. Form Labels — High

Каждый input должен иметь associated label.

<label for="email">Email</label>
<input type="email" id="email" />

❌ Только placeholder='Email'

44. Error Messages — High

Ошибки должны анонсироваться.

<div role="alert" class="text-red-600">Error message</div>

❌ Только красная рамка — screen reader не прочитает

Клавиатурные пользователи должны пропускать навигацию.

<a href="#main" className="sr-only focus:not-sr-only">
  Skip to main content
</a>

❌ 100 тапов до контента


Performance (8 правил)

46. Image Optimization — High

Большие изображения замедляют загрузку.

<img src="small.webp" srcset="small.webp 400w, medium.webp 800w, large.webp 1600w"
     sizes="(max-width: 640px) 100vw, 50vw" alt="..." />

❌ 4000px изображение для 400px display

47. Lazy Loading — Medium

Загружать контент по мере необходимости.

<img src="below-fold.jpg" loading="lazy" alt="..." />

❌ Все изображения loading="eager"

48. Code Splitting — Medium

Большие бандлы замедляют начальный рендер.

const Dashboard = lazy(() => import('./Dashboard'));

❌ Весь код в main bundle

49. Caching — Medium

Повторные визиты должны быть быстрыми.

Cache-Control: public, max-age=31536000, immutable

❌ Каждый запрос на сервер

50. Font Loading — Medium

Шрифты не должны блокировать рендер.

font-display: swap;

❌ FOIT (Flash of Invisible Text)

51. Third Party Scripts — Medium

Внешние скрипты блокируют рендер.

<script async src="https://analytics.js/tracker.js"></script>

❌ <script src="..."> в head без async

52. Bundle Size — Medium

Большой JavaScript замедляет интерактивность.

# Bundle analyzer
npx webpack-bundle-analyzer stats.json

❌ Без мониторинга размера бандла

53. Render Blocking — Medium

CSS/JS могут блокировать первый рендер.

<link rel="preload" href="/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

❌ Весь CSS в head блокирует paint


Forms (9 правил)

54. Input Labels — High

Каждый input — видимый label.

<label class="block text-sm font-medium mb-1" for="email">Email</label>
<input id="email" type="email" />

❌ Только placeholder='Email'

55. Error Placement — Medium

Ошибки — рядом с полем.

<input /><div class="text-red-500 text-sm mt-1">Invalid email</div>

❌ Все ошибки вверху формы

56. Inline Validation — Medium

Валидация при blur (не только при submit).

input.addEventListener('blur', validate);

❌ Только onSubmit валидация

57. Input Types — Medium

Использовать правильные типы input.

<input type="email" />
<input type="tel" />
<input type="number" />

❌ type='text' для email

58. Autofill Support — Medium

Помогать браузерам автозаполнять.

<input autocomplete="email" />
<input autocomplete="current-password" />

❌ autocomplete='off' везде

59. Required Indicators — Medium

Обозначать обязательные поля.

<label><span class="after:content-['*'] after:text-red-500">Email</span></label>

❌ Без индикации — пользователь гадает

60. Password Visibility — Medium

Позволять видеть пароль при вводе.

<input type={showPassword ? 'text' : 'password'} />
<button onClick={() => setShowPassword(!showPassword)}>
  {showPassword ? 'Hide' : 'Show'}
</button>

❌ Пароль всегда скрыт

61. Submit Feedback — High

Подтверждать статус отправки формы.

{loading && <span>Submitting...</span>}
{success && <span className="text-green-600">Saved!</span>}

❌ Клик — нет ответа

62. Input Affordance — Medium

Inputs должны выглядеть интерактивными.

<input class="border rounded px-3 py-2 bg-white" />

❌ Borderless inputs — выглядят как текст

63. Mobile Keyboards — Medium

Показывать правильную клавиатуру.

<input inputmode="numeric" pattern="[0-9]*" />

❌ Текстовая клавиатура для чисел


Responsive (8 правил)

64. Mobile First — Medium

Сначала мобильный, потом улучшаем.

/* Default mobile styles */
.container { padding: 1rem; }
@media (min-width: 768px) {
  .container { padding: 2rem; } /* tablet+ */
}

❌ Desktop-first с max-width query

65. Breakpoint Testing — Medium

Тестировать на всех экранах.

<!-- Test at: 320, 375, 414, 768, 1024, 1440 -->

❌ Только на своём устройстве

66. Touch Friendly — High

Мобильные лейауты — большие touch targets.

<button class="md:min-h-[48px] min-h-[56px]">

❌ Desktop-sized targets на мобильных

67. Readable Font Size — High

Минимум 16px body на мобильных.

<p class="text-base md:text-lg">...</p> <!-- 16px+ -->

❌ text-xs для body текста

68. Viewport Meta — High

Установить viewport для мобильных.

<meta name="viewport" content="width=device-width, initial-scale=1">

❌ Нет viewport meta

69. Horizontal Scroll — High

Избегать горизонтального скролла.

<div class="max-w-full overflow-x-hidden">

❌ Горизонтальный скролл на мобильных

70. Image Scaling — Medium

Изображения — пропорционально контейнеру.

<img class="max-w-full h-auto" />

❌ width='800' fixed — overflow

71. Table Handling — Medium

Таблицы — горизонтальный скролл на мобильных.

<div class="overflow-x-auto">
  <table class="min-w-full">...</table>
</div>

❌ Таблица выходит за viewport


Typography (6 правил)

72. Line Height — Medium

Адекватный line-height улучшает читаемость.

<p class="leading-relaxed">...</p> <!-- 1.625 -->

❌ leading-none (1) для body

73. Line Length — Medium

Длинные строки трудно читать.

<p class="max-w-prose">...</p> <!-- ~65ch -->

❌ Текст на всю ширину viewport

74. Font Size Scale — Medium

Консистентный тип-масштаб.

<!-- 12 14 16 18 24 32 40 48 56 64 -->

❌ Произвольные размеры

75. Font Loading — Medium

Шрифты без сдвигов layout.

font-display: swap;
/* + похожий fallback */
font-family: 'Inter', system-ui, -apple-system, sans-serif;

❌ Нет fallback шрифта

76. Contrast Readability — High

Body текст — хороший контраст.

<p class="text-gray-900 bg-white">...</p>

❌ text-gray-400 на gray-100

77. Heading Clarity — Medium

Заголовки — отличаются от body.

<h2 class="text-2xl font-bold">...</h2>
<p class="text-base font-normal">...</p>

❌ Заголовок того же размера, что body


Feedback (6 правил)

78. Loading Indicators — High

Показать статус системы во время ожидания.

{isLoading && <Skeleton className="h-4 w-3/4 animate-pulse" />}

❌ Замороженный UI

79. Empty States — Medium

Направлять пользователя, когда нет контента.

<div className="text-center py-12">
  <p className="text-gray-500">No items yet. <a href="/create" className="text-blue-600">Create one!</a></p>
</div>

❌ Пустое белое пространство

80. Error Recovery — Medium

Помогать восстанавливаться после ошибок.

<div className="text-red-600">
  Failed to load. <button className="underline">Try again</button>
</div>

❌ Сообщение об ошибке без пути назад

81. Progress Indicators — Medium

Показывать прогресс multi-step.

<div className="flex gap-2">
  <div className="h-2 flex-1 bg-blue-600 rounded"></div>
  <div className="h-2 flex-1 bg-gray-200 rounded">Step 2 of 4</div>
</div>

❌ Нет step info

82. Toast Notifications — Medium

Всплывающие сообщения для не-критичной инфы.

<div className="fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-3 rounded shadow-lg"
     autoDismiss={3000}>
  Item saved!
</div>

❌ Toast, который не исчезает

83. Confirmation Messages — Medium

Подтверждать успешные действия.

<div className="text-green-600 flex items-center gap-2">
  <CheckIcon /> Saved successfully
</div>

❌ Без подтверждения


Content (4 правила)

84. Truncation — Medium

Обрезать длинный контент.

<p className="line-clamp-2 cursor-pointer" onClick={expand}>
  Long text...
</p>

❌ Overflow: hidden — обрезка без expand

85. Date Formatting — Low

Использовать локализованные форматы дат.

new Date().toLocaleDateString('ru-RU', { dateStyle: 'medium' })
// "20 июн 2026 г."

❌ 01/02/03 — неоднозначно

86. Number Formatting — Low

Форматировать большие числа.

(1234567).toLocaleString('ru-RU') // "1 234 567"
// или (1.2M)

❌ 1234567 — без разделителей

87. Placeholder Content — Low

Использовать реалистичный placeholder.

<input defaultValue="john@example.com" />

❌ Lorem ipsum везде


Onboarding / Search / Data Entry (3 правила)

88. User Freedom — Medium

Пользователь должен уметь пропустить туториал.

<button className="text-gray-500 underline">Skip Tutorial</button>

❌ Запертый overlay до конца

89. Search Autocomplete — Medium

Помогать находить результаты быстрее.

<input type="search" debounced onChange={showSuggestions} />

❌ Полное вбивание + Enter

90. No Results — Medium

Показывать «Нет результатов» с подсказками.

<div>
  <p>Try searching for: shoes, hats, bags</p>
</div>

❌ «No results found.» — тупик

91. Bulk Actions — Low

Массовое редактирование.

<div className="flex items-center gap-4">
  <input type="checkbox" className="row-checkbox" />
  <div className="flex gap-2">
    <button className="btn-sm">Delete Selected</button>
    <button className="btn-sm">Archive</button>
  </div>
</div>

❌ Одиночные действия на каждую строку


AI Interaction (4 правила)

92. AI Disclaimer — High

Пользователи должны знать, что общаются с ИИ.

<div className="flex items-center gap-2 text-sm text-gray-500 mb-4">
  <BotIcon /> AI Assistant
</div>

❌ Фейковое человеческое имя без лейбла

93. Streaming — Medium

Потоковая подача текста вместо ожидания 100%.

<div className="typewriter">
  {streamedText}
  <span className="animate-pulse">▌</span>
</div>

❌ Spinner до 100% completion

94. Spatial UI — High (VisionOS)

Элементы должны реагировать на gaze.

// VisionOS
.hoverEffect(.scale, enabled: true)

❌ Статичный элемент до pinch

95. Depth Layering — Medium (VisionOS)

Z-глубина для контента.

.material(.thin)
.offsetZ(10)

❌ Плоские непрозрачные панели


Sustainability (2 правила)

96. Auto-Play Video — Medium

Видео потребляет данные и энергию.

<video playsInline muted preload="none" poster="cover.jpg">
  <source src="video.mp4" type="video/mp4" />
</video>

❌ autoplay loop — трафик

97. Asset Weight — Medium

Тяжёлые 3D/изображения увеличивают carbon footprint.

const Model = lazy(() => import('./model.glb?draco')); // Draco compression

❌ Raw .obj файлы 50MB


Additional AI Interaction (1 правило)

98. Feedback Loop — Low

ИИ нуждается в обратной связи для улучшения.

<div className="flex gap-2 mt-4">
  <button className="btn-sm">👍 Helpful</button>
  <button className="btn-sm">👎 Not helpful</button>
  <button className="btn-sm">Regenerate</button>
</div>

❌ Только текст, без возможности оценки


Accessibility (1 правило)

99. Motion Sensitivity — High

Параллакс/Scroll-jacking вызывает тошноту.

@media (prefers-reduced-motion: reduce) {
  .parallax { transform: none !important; }
}

❌ ScrollTrigger.create() без проверки prefers-reduced-motion


Quick Reference by Category

Category Count High Severity
Navigation 6 1
Animation 8 2
Layout 7 1
Touch 6 1
Interaction 8 2
Accessibility 11 7
Performance 8 1
Forms 10 2
Responsive 8 3
Typography 6 1
Feedback 6 1
Content 4 0
Onboarding/Search/Data 4 0
AI Interaction 4 1
Sustainability 2 0
Spatial UI 2 1
Total 99 27 🔴