Tailwind CSS Skill
Overview
Expert guidance for Tailwind CSS styling with mobile-first responsive design, custom themes, and utility-first approach. Focuses on accessibility, dark mode, and performance optimization.
When This Skill Applies
This skill triggers when users request:
Styling : "Style this KPI card", "Button component style", "Design a form"
Responsive : "Mobile-first layout", "Responsive dashboard", "Grid with breakpoints"
Themes : "Custom dark theme", "Extend tailwind theme", "Color scheme"
Layouts : "Dashboard grid", "Card layout", "Flexible container"
Core Rules
1. Mobile-First Design
// ✅ GOOD: Mobile-first progressive enhancement
<div className="w-full px-4 py-2 sm:w-1/2 sm:px-6 md:w-1/3 md:px-8 lg:w-1/4">
<KPICard />
</div>
// Breakpoints:
// sm: 640px - Small tablets/phones
// md: 768px - Tablets
// lg: 1024px - Desktops
// xl: 1280px - Large screens
// 2xl: 1536px - Extra large screens
Requirements:
Base styles for mobile (no prefix)
Progressive enhancement with sm:, md:, lg: prefixes
Start with mobile layout, enhance for larger screens
Use responsive breakpoints: sm:640px, md:768px, lg:1024px
2. Responsive Utilities
// ✅ GOOD: Fluid responsive layouts
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{items.map(item => <Item key={item.id} item={item} />)}
</div>
// ✅ GOOD: Responsive spacing
<div className="p-4 sm:p-6 md:p-8 lg:p-12">
Content
</div>
// ✅ GOOD: Container queries (if needed)
<div className="@container">
<div className="@lg:grid-cols-2">
Nested responsive content
</div>
</div>
Requirements:
Use fluid utilities (w-full, flex-1) for mobile
Add breakpoints (sm:, md:, lg:) for larger screens
Consider container queries for nested responsive components
Test layouts at multiple breakpoints (375px, 768px, 1024px, 1440px)
3. Custom Themes
// tailwind.config.ts
export default {
darkMode: 'class', // or 'media'
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6',
900: '#1e3a8a',
},
erp: {
'card': '#ffffff',
'card-dark': '#1f2937',
},
},
spacing: {
'18': '4.5rem',
'88': '22rem',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
plugins: [],
};
Requirements:
Extend theme in tailwind.config.ts, don't override
Use semantic names (primary, secondary, accent)
Define custom colors, fonts, spacing in theme
Support CSS variables for dynamic theming
Use darkMode: 'class' for manual dark mode toggle
4. Component Styling
// ✅ GOOD: Utility-first approach
export const Button = ({ variant, size, children }) => (
<button className={`
font-semibold rounded-lg
${variant === 'primary' ? 'bg-blue-500 text-white hover:bg-blue-600' : 'bg-gray-200 text-gray-800 hover:bg-gray-300'}
${size === 'sm' ? 'px-3 py-1 text-sm' : 'px-4 py-2'}
transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
`}>
{children}
</button>
);
// ✅ GOOD: CVA or class-variance-authority for variants
import { cva } from 'class-variance-authority';
const buttonVariants = cva(
'font-semibold rounded-lg transition-colors',
{
variants: {
variant: {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
},
size: {
sm: 'px-3 py-1 text-sm',
md: 'px-4 py-2',
},
},
}
);
Requirements:
Prefer inline utility classes over custom CSS
Use @apply sparingly (only for repeated patterns)
Extract complex variants with CVA or similar libraries
Follow shadcn/ui patterns for consistent styling
Use template literals for conditional classes
Output Requirements
Code Files
Component Styling :
Inline utility classes in JSX/TSX
Conditional classes for variants (dark/light, sizes)
Focus states and transitions
Configuration :
tailwind.config.ts updates for custom themes
globals.css for global styles and directives
Dark Mode Support :
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Content with dark mode
</div>
Integration Requirements
shadcn/ui : Follow shadcn design tokens and patterns
Accessibility : WCAG 2.1 AA compliant colors, focus-visible states
Performance : Enable JIT mode, purge unused classes
i18n : Support RTL layouts when needed
Documentation
PHR : Create Prompt History Record for styling decisions
ADR : Document theme decisions (color schemes, breakpoints)
Comments : Document non-obvious utility combinations
Workflow
Analyze Layout Requirements
Identify mobile breakpoints
Determine responsive needs
Check dark mode requirements
Apply Mobile-First Styles
Base styles without breakpoints
Progressive enhancement for larger screens
Test on mobile viewport (375px)
Add Responsive Breakpoints
sm: for tablets (640px)
md: for tablets (768px)
lg: for desktops (1024px)
Test at each breakpoint
Apply Dark Mode
Add dark: variants for colors/backgrounds
Test in both light and dark modes
Ensure contrast ratios in both modes
Validate Accessibility
Check color contrast ratios (4.5:1 minimum)
Add focus-visible states for interactive elements
Ensure touch targets are 44px+ on mobile
Quality Checklist
Before completing any styling:
No Horizontal Scroll Mobile : Layout fits 375px without horizontal scroll
Touch Targets : All interactive elements 44px+ on mobile
Dark/Light Variants : Dark mode support with dark: classes
Utility-First : Minimal custom CSS, use Tailwind utilities
Purge Unused : No unused utility classes in production
Focus States : focus-visible or focus:ring on all interactive elements
Contrast Ratios : WCAG 2.1 AA compliant colors (4.5:1 for text)
Responsive Breakpoints : Tested at sm/md/lg breakpoints
Consistent Spacing : Use Tailwind's spacing scale (0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64)
Transitions : Add transition-* classes for smooth state changes
Common Patterns
KPI Card (Mobile-First)
export const KPICard = ({ title, value, trend, loading }) => (
<div className="
w-full p-4 bg-white dark:bg-gray-800
rounded-lg shadow-sm border border-gray-200 dark:border-gray-700
sm:p-6 md:p-8
">
{loading ? (
<Skeleton className="h-20" />
) : (
<>
<h3 className="text-sm font-medium text-gray-600 dark:text-gray-400">
{title}
</h3>
<p className="text-2xl font-bold text-gray-900 dark:text-white mt-2">
{value}
</p>
{trend && (
<span className={`
inline-flex items-center mt-2 text-sm
${trend > 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}
`}>
{trend > 0 ? '↑' : '↓'} {Math.abs(trend)}%
</span>
)}
</>
)}
</div>
);
Responsive Dashboard Grid
export const DashboardGrid = ({ children }) => (
<div className="
w-full grid gap-4
grid-cols-1
sm:grid-cols-2
md:grid-cols-3
lg:grid-cols-4
xl:grid-cols-5
p-4
">
{children}
</div>
);
Form with Responsive Layout
export const ResponsiveForm = () => (
<form className="
w-full max-w-lg mx-auto
p-4 sm:p-6 md:p-8
bg-white dark:bg-gray-800
rounded-lg shadow-md
">
<div className="space-y-4 sm:space-y-6">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Name
</label>
<input className="
w-full px-4 py-2 text-base
border border-gray-300 dark:border-gray-600
rounded-lg
bg-white dark:bg-gray-700
text-gray-900 dark:text-white
focus:ring-2 focus:ring-blue-500 focus:border-blue-500
" />
</div>
<button className="
w-full sm:w-auto
px-6 py-3 text-base font-semibold
bg-blue-500 hover:bg-blue-600
text-white rounded-lg
transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
">
Submit
</button>
</div>
</form>
);
Dark Mode Toggle Button
export const DarkModeToggle = ({ isDark, onToggle }) => (
<button
className="
p-2 rounded-lg
bg-gray-200 dark:bg-gray-700
hover:bg-gray-300 dark:hover:bg-gray-600
text-gray-800 dark:text-gray-200
transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-blue-500
"
aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
>
{isDark ? '☀️' : '🌙'}
</button>
);
Tailwind Configuration Best Practices
Breakpoint Strategy
// Recommended breakpoint configuration
screens: {
'xs': '475px', // Extra small phones
'sm': '640px', // Small tablets/phones
'md': '768px', // Tablets
'lg': '1024px', // Desktops
'xl': '1280px', // Large screens
'2xl': '1536px', // Extra large screens
}
Color System
// Semantic color naming
colors: {
primary: { 50: '...', 500: '...', 900: '...' },
success: { 50: '...', 500: '...', 900: '...' },
warning: { 50: '...', 500: '...', 900: '...' },
error: { 50: '...', 500: '...', 900: '...' },
}
Spacing Scale
// Use Tailwind's scale: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64, 72, 80, 96
// 1 = 0.25rem (4px), 4 = 1rem (16px), 8 = 2rem (32px)
spacing: {
'128': '32rem',
'144': '36rem',
}
Accessibility Guidelines
Color Contrast : Minimum 4.5:1 for text, 3:1 for large text
Focus States : Always include focus:ring-2 or focus-visible
Touch Targets : Minimum 44x44px for mobile interactive elements
Skip Links : Add sr-only skip links for keyboard users
ARIA Labels : Use aria-label for icon-only buttons
Performance Optimization
JIT Mode : Enabled by default in Tailwind CSS 3+
Purge Unused : Only used classes in production
CSS Minification : Tailwind CLI or PostCSS optimization
Inline Critical CSS : Extract critical CSS for above-fold content
Lazy Load Components : Code split heavy components
References
1 --- 2 name: tailwind-css 3 description: Use when styling UI components or layouts with Tailwind CSS - mobile-first design, responsive utilities, custom themes, or component styling. NOT when plain CSS, CSS-in-JS (styled-components), or non-Tailwind frameworks are involved. Triggers: "style component", "responsive design", "mobile-first", "dark theme", "tailwind classes", "dashboard grid". 4 --- 5 6 # Tailwind CSS Skill 7 8 ## Overview 9 10 Expert guidance for Tailwind CSS styling with mobile-first responsive design, custom themes, and utility-first approach. Focuses on accessibility, dark mode, and performance optimization. 11 12 ## When This Skill Applies 13 14 This skill triggers when users request: 15 - **Styling**: "Style this KPI card", "Button component style", "Design a form" 16 - **Responsive**: "Mobile-first layout", "Responsive dashboard", "Grid with breakpoints" 17 - **Themes**: "Custom dark theme", "Extend tailwind theme", "Color scheme" 18 - **Layouts**: "Dashboard grid", "Card layout", "Flexible container" 19 20 ## Core Rules 21 22 ### 1. Mobile-First Design 23 24 ```jsx 25 // ✅ GOOD: Mobile-first progressive enhancement 26 <div className="w-full px-4 py-2 sm:w-1/2 sm:px-6 md:w-1/3 md:px-8 lg:w-1/4"> 27 <KPICard /> 28 </div> 29 30 // Breakpoints: 31 // sm: 640px - Small tablets/phones 32 // md: 768px - Tablets 33 // lg: 1024px - Desktops 34 // xl: 1280px - Large screens 35 // 2xl: 1536px - Extra large screens 36 ``` 37 38 **Requirements:** 39 - Base styles for mobile (no prefix) 40 - Progressive enhancement with `sm:`, `md:`, `lg:` prefixes 41 - Start with mobile layout, enhance for larger screens 42 - Use responsive breakpoints: `sm:640px`, `md:768px`, `lg:1024px` 43 44 ### 2. Responsive Utilities 45 46 ```jsx 47 // ✅ GOOD: Fluid responsive layouts 48 <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> 49 {items.map(item => <Item key={item.id} item={item} />)} 50 </div> 51 52 // ✅ GOOD: Responsive spacing 53 <div className="p-4 sm:p-6 md:p-8 lg:p-12"> 54 Content 55 </div> 56 57 // ✅ GOOD: Container queries (if needed) 58 <div className="@container"> 59 <div className="@lg:grid-cols-2"> 60 Nested responsive content 61 </div> 62 </div> 63 ``` 64 65 **Requirements:** 66 - Use fluid utilities (`w-full`, `flex-1`) for mobile 67 - Add breakpoints (`sm:`, `md:`, `lg:`) for larger screens 68 - Consider container queries for nested responsive components 69 - Test layouts at multiple breakpoints (375px, 768px, 1024px, 1440px) 70 71 ### 3. Custom Themes 72 73 ```typescript 74 // tailwind.config.ts 75 export default { 76 darkMode: 'class', // or 'media' 77 content: ['./src/**/*.{ts,tsx}'], 78 theme: { 79 extend: { 80 colors: { 81 primary: { 82 50: '#eff6ff', 83 100: '#dbeafe', 84 500: '#3b82f6', 85 900: '#1e3a8a', 86 }, 87 erp: { 88 'card': '#ffffff', 89 'card-dark': '#1f2937', 90 }, 91 }, 92 spacing: { 93 '18': '4.5rem', 94 '88': '22rem', 95 }, 96 fontFamily: { 97 sans: ['Inter', 'sans-serif'], 98 }, 99 }, 100 }, 101 plugins: [], 102 }; 103 ``` 104 105 **Requirements:** 106 - Extend theme in `tailwind.config.ts`, don't override 107 - Use semantic names (`primary`, `secondary`, `accent`) 108 - Define custom colors, fonts, spacing in theme 109 - Support CSS variables for dynamic theming 110 - Use `darkMode: 'class'` for manual dark mode toggle 111 112 ### 4. Component Styling 113 114 ```jsx 115 // ✅ GOOD: Utility-first approach 116 export const Button = ({ variant, size, children }) => ( 117 <button className={` 118 font-semibold rounded-lg 119 ${variant === 'primary' ? 'bg-blue-500 text-white hover:bg-blue-600' : 'bg-gray-200 text-gray-800 hover:bg-gray-300'} 120 ${size === 'sm' ? 'px-3 py-1 text-sm' : 'px-4 py-2'} 121 transition-colors duration-200 122 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 123 `}> 124 {children} 125 </button> 126 ); 127 128 // ✅ GOOD: CVA or class-variance-authority for variants 129 import { cva } from 'class-variance-authority'; 130 131 const buttonVariants = cva( 132 'font-semibold rounded-lg transition-colors', 133 { 134 variants: { 135 variant: { 136 primary: 'bg-blue-500 text-white hover:bg-blue-600', 137 secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300', 138 }, 139 size: { 140 sm: 'px-3 py-1 text-sm', 141 md: 'px-4 py-2', 142 }, 143 }, 144 } 145 ); 146 ``` 147 148 **Requirements:** 149 - Prefer inline utility classes over custom CSS 150 - Use `@apply` sparingly (only for repeated patterns) 151 - Extract complex variants with CVA or similar libraries 152 - Follow shadcn/ui patterns for consistent styling 153 - Use template literals for conditional classes 154 155 ## Output Requirements 156 157 ### Code Files 158 159 1. **Component Styling**: 160 - Inline utility classes in JSX/TSX 161 - Conditional classes for variants (dark/light, sizes) 162 - Focus states and transitions 163 164 2. **Configuration**: 165 - `tailwind.config.ts` updates for custom themes 166 - `globals.css` for global styles and directives 167 168 3. **Dark Mode Support**: 169 ```jsx 170 <div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white"> 171 Content with dark mode 172 </div> 173 ``` 174 175 ### Integration Requirements 176 177 - **shadcn/ui**: Follow shadcn design tokens and patterns 178 - **Accessibility**: WCAG 2.1 AA compliant colors, focus-visible states 179 - **Performance**: Enable JIT mode, purge unused classes 180 - **i18n**: Support RTL layouts when needed 181 182 ### Documentation 183 184 - **PHR**: Create Prompt History Record for styling decisions 185 - **ADR**: Document theme decisions (color schemes, breakpoints) 186 - **Comments**: Document non-obvious utility combinations 187 188 ## Workflow 189 190 1. **Analyze Layout Requirements** 191 - Identify mobile breakpoints 192 - Determine responsive needs 193 - Check dark mode requirements 194 195 2. **Apply Mobile-First Styles** 196 - Base styles without breakpoints 197 - Progressive enhancement for larger screens 198 - Test on mobile viewport (375px) 199 200 3. **Add Responsive Breakpoints** 201 - `sm:` for tablets (640px) 202 - `md:` for tablets (768px) 203 - `lg:` for desktops (1024px) 204 - Test at each breakpoint 205 206 4. **Apply Dark Mode** 207 - Add `dark:` variants for colors/backgrounds 208 - Test in both light and dark modes 209 - Ensure contrast ratios in both modes 210 211 5. **Validate Accessibility** 212 - Check color contrast ratios (4.5:1 minimum) 213 - Add focus-visible states for interactive elements 214 - Ensure touch targets are 44px+ on mobile 215 216 ## Quality Checklist 217 218 Before completing any styling: 219 220 - [ ] **No Horizontal Scroll Mobile**: Layout fits 375px without horizontal scroll 221 - [ ] **Touch Targets**: All interactive elements 44px+ on mobile 222 - [ ] **Dark/Light Variants**: Dark mode support with `dark:` classes 223 - [ ] **Utility-First**: Minimal custom CSS, use Tailwind utilities 224 - [ ] **Purge Unused**: No unused utility classes in production 225 - [ ] **Focus States**: `focus-visible` or `focus:ring` on all interactive elements 226 - [ ] **Contrast Ratios**: WCAG 2.1 AA compliant colors (4.5:1 for text) 227 - [ ] **Responsive Breakpoints**: Tested at sm/md/lg breakpoints 228 - [ ] **Consistent Spacing**: Use Tailwind's spacing scale (0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64) 229 - [ ] **Transitions**: Add `transition-*` classes for smooth state changes 230 231 ## Common Patterns 232 233 ### KPI Card (Mobile-First) 234 235 ```jsx 236 export const KPICard = ({ title, value, trend, loading }) => ( 237 <div className=" 238 w-full p-4 bg-white dark:bg-gray-800 239 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 240 sm:p-6 md:p-8 241 "> 242 {loading ? ( 243 <Skeleton className="h-20" /> 244 ) : ( 245 <> 246 <h3 className="text-sm font-medium text-gray-600 dark:text-gray-400"> 247 {title} 248 </h3> 249 <p className="text-2xl font-bold text-gray-900 dark:text-white mt-2"> 250 {value} 251 </p> 252 {trend && ( 253 <span className={` 254 inline-flex items-center mt-2 text-sm 255 ${trend > 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'} 256 `}> 257 {trend > 0 ? '↑' : '↓'} {Math.abs(trend)}% 258 </span> 259 )} 260 </> 261 )} 262 </div> 263 ); 264 ``` 265 266 ### Responsive Dashboard Grid 267 268 ```jsx 269 export const DashboardGrid = ({ children }) => ( 270 <div className=" 271 w-full grid gap-4 272 grid-cols-1 273 sm:grid-cols-2 274 md:grid-cols-3 275 lg:grid-cols-4 276 xl:grid-cols-5 277 p-4 278 "> 279 {children} 280 </div> 281 ); 282 ``` 283 284 ### Form with Responsive Layout 285 286 ```jsx 287 export const ResponsiveForm = () => ( 288 <form className=" 289 w-full max-w-lg mx-auto 290 p-4 sm:p-6 md:p-8 291 bg-white dark:bg-gray-800 292 rounded-lg shadow-md 293 "> 294 <div className="space-y-4 sm:space-y-6"> 295 <div> 296 <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> 297 Name 298 </label> 299 <input className=" 300 w-full px-4 py-2 text-base 301 border border-gray-300 dark:border-gray-600 302 rounded-lg 303 bg-white dark:bg-gray-700 304 text-gray-900 dark:text-white 305 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 306 " /> 307 </div> 308 <button className=" 309 w-full sm:w-auto 310 px-6 py-3 text-base font-semibold 311 bg-blue-500 hover:bg-blue-600 312 text-white rounded-lg 313 transition-colors duration-200 314 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 315 "> 316 Submit 317 </button> 318 </div> 319 </form> 320 ); 321 ``` 322 323 ### Dark Mode Toggle Button 324 325 ```jsx 326 export const DarkModeToggle = ({ isDark, onToggle }) => ( 327 <button 328 onClick={onToggle} 329 className=" 330 p-2 rounded-lg 331 bg-gray-200 dark:bg-gray-700 332 hover:bg-gray-300 dark:hover:bg-gray-600 333 text-gray-800 dark:text-gray-200 334 transition-colors duration-200 335 focus:outline-none focus:ring-2 focus:ring-blue-500 336 " 337 aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'} 338 > 339 {isDark ? '☀️' : '🌙'} 340 </button> 341 ); 342 ``` 343 344 ## Tailwind Configuration Best Practices 345 346 ### Breakpoint Strategy 347 348 ```typescript 349 // Recommended breakpoint configuration 350 screens: { 351 'xs': '475px', // Extra small phones 352 'sm': '640px', // Small tablets/phones 353 'md': '768px', // Tablets 354 'lg': '1024px', // Desktops 355 'xl': '1280px', // Large screens 356 '2xl': '1536px', // Extra large screens 357 } 358 ``` 359 360 ### Color System 361 362 ```typescript 363 // Semantic color naming 364 colors: { 365 primary: { 50: '...', 500: '...', 900: '...' }, 366 success: { 50: '...', 500: '...', 900: '...' }, 367 warning: { 50: '...', 500: '...', 900: '...' }, 368 error: { 50: '...', 500: '...', 900: '...' }, 369 } 370 ``` 371 372 ### Spacing Scale 373 374 ```typescript 375 // Use Tailwind's scale: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64, 72, 80, 96 376 // 1 = 0.25rem (4px), 4 = 1rem (16px), 8 = 2rem (32px) 377 spacing: { 378 '128': '32rem', 379 '144': '36rem', 380 } 381 ``` 382 383 ## Accessibility Guidelines 384 385 - **Color Contrast**: Minimum 4.5:1 for text, 3:1 for large text 386 - **Focus States**: Always include `focus:ring-2` or `focus-visible` 387 - **Touch Targets**: Minimum 44x44px for mobile interactive elements 388 - **Skip Links**: Add `sr-only` skip links for keyboard users 389 - **ARIA Labels**: Use `aria-label` for icon-only buttons 390 391 ## Performance Optimization 392 393 1. **JIT Mode**: Enabled by default in Tailwind CSS 3+ 394 2. **Purge Unused**: Only used classes in production 395 3. **CSS Minification**: Tailwind CLI or PostCSS optimization 396 4. **Inline Critical CSS**: Extract critical CSS for above-fold content 397 5. **Lazy Load Components**: Code split heavy components 398 399 ## References 400 401 - Tailwind CSS Documentation: https://tailwindcss.com/docs 402 - Tailwind UI Patterns: https://tailwindui.com 403 - shadcn/ui Components: https://ui.shadcn.com 404 - Web Content Accessibility Guidelines (WCAG 2.1): https://www.w3.org/WAI/WCAG21/quickref/