feat(skill): add email accessibility guidance to skill (#3551)

Co-authored-by: Hermes <hermes@resend.com>
This commit is contained in:
Christina Martinez
2026-05-27 23:04:08 -07:00
committed by GitHub
parent 62630604e9
commit 6107e01f98
3 changed files with 48 additions and 12 deletions
+31 -7
View File
@@ -19,7 +19,7 @@ metadata:
# React Email # React Email
Build and send HTML emails using React components - a modern, component-based approach to email development that works across all major email clients. Build and send HTML emails using React components. A modern, component-based approach to email development that works across all major email clients.
## Installation ## Installation
@@ -355,12 +355,36 @@ See [references/PATTERNS.md](references/PATTERNS.md) for complete examples inclu
1. **Test across email clients** - Gmail, Outlook, Apple Mail, Yahoo Mail 1. **Test across email clients** - Gmail, Outlook, Apple Mail, Yahoo Mail
2. **Keep it responsive** - Max-width around 600px, test on mobile 2. **Keep it responsive** - Max-width around 600px, test on mobile
3. **Use absolute image URLs** - Host on reliable CDN, always include `alt` text 3. **Use absolute image URLs** - Host on reliable CDN
4. **Provide plain text version** - Required for accessibility 4. **Write meaningful alt text** - Describe purpose and details for content images; use `alt=""` for decorative images (spacers, dividers, background flourishes). React Email's `<Img>` defaults to `alt=""`.
5. **Keep file size under 102KB** - Gmail clips larger emails 5. **Provide plain text version** - Required for accessibility
6. **Add proper TypeScript types** - Define interfaces for all email props 6. **Keep file size under 102KB** - Gmail clips larger emails
7. **Include preview props** - Add `.PreviewProps` for development testing 7. **Add proper TypeScript types** - Define interfaces for all email props
8. **Use verified domains** - For production `from` addresses 8. **Include preview props** - Add `.PreviewProps` for development testing
9. **Use verified domains** - For production `from` addresses
### Accessibility
React Email handles the structural defaults; the rest is content.
**What React Email gives you for free:**
- `<Html>` sets `lang` and `dir` (defaults: `lang="en" dir="ltr"` — override per locale)
- `<Img>` defaults to `alt=""` so decorative images are skipped by screen readers
- `<Markdown>` renders layout tables with `role="presentation"`
- `<Preview>` also emits a `<title>` tag
Upgrade with `npm install react-email@latest` to get these defaults.
**What you still have to do (content choices):**
- Open with a single `<Heading as="h1">`, nest subheadings in order, never skip levels (very short SMS-style emails may skip the heading entirely)
- Set descriptive `alt` on meaningful images; pass an explicit `alt=""` on decorative images — never omit the attribute
- **Linked images are never decorative.** When an `<Img>` is inside a `<Link>` or `<Button>`, the `alt` must describe where the link goes — `alt=""` on a linked image leaves the link with no accessible name
- Write link text that describes the destination (`<Button>Read the report</Button>`, not `click here`)
- Hit 4.5:1 text contrast (WCAG AA); preview in dark mode
- For layout tables you build by hand (outside `<Markdown>`), add `role="presentation"`
- For non-English emails, pass the locale: `<Html lang={locale} dir={isRTL ? 'rtl' : 'ltr'}>` (see [I18N.md](references/I18N.md))
For the full rule set, severity ranking, and authoring checklist, see the [accessibility reference](https://github.com/resend/email-best-practices/blob/main/references/accessibility.md) in the `email-best-practices` skill.
## Additional Resources ## Additional Resources
+6 -2
View File
@@ -155,6 +155,8 @@ import { Section } from 'react-email';
</Section> </Section>
``` ```
Layout components (`<Section>`, `<Row>`, `<Container>`, `<Markdown>` tables) render `<table role="presentation">` by default so screen readers don't announce them as data tables. If you drop in a raw `<table>` for layout, add `role="presentation"` yourself.
### Row & Column ### Row & Column
Row displays content areas horizontally, Column displays content areas vertically. A Column needs to be used in combination with a Row component. Row displays content areas horizontally, Column displays content areas vertically. A Column needs to be used in combination with a Row component.
@@ -286,13 +288,15 @@ import { Img } from 'react-email';
**Props:** **Props:**
- `src` (required) - Image URL (must be absolute) - `src` (required) - Image URL (must be absolute)
- `alt` (required) - Alt text for accessibility - `alt` - Alt text for accessibility (defaults to `""`; set a descriptive value for meaningful images)
- `width` - Image width in pixels - `width` - Image width in pixels
- `height` - Image height in pixels - `height` - Image height in pixels
**Best practices:** **Best practices:**
- Always use absolute URLs hosted on CDN - Always use absolute URLs hosted on CDN
- Always include alt text - **Meaningful images**: write descriptive `alt` text covering purpose and key details (e.g., `alt="Red bicycle leaning against a brick wall"`, not `alt="image"`)
- **Decorative images** (spacers, dividers, background flourishes): pass an explicit `alt=""` so screen readers skip them cleanly — never omit the attribute
- **Linked images are never decorative.** When `<Img>` sits inside a `<Link>` or `<Button>`, its `alt` must describe where the link goes (e.g., `alt="View order #123"`). An empty `alt=""` on a linked image leaves the link with no accessible name for screen readers
- Specify width and height to prevent layout shift - Specify width and height to prevent layout shift
- Use `block` class to avoid spacing issues - Use `block` class to avoid spacing issues
+11 -3
View File
@@ -153,14 +153,22 @@ Use consistent spacing that respects content hierarchy. Larger margins for headi
- Never distort user-provided images - Never distort user-provided images
- Never create SVG images - Never create SVG images
- Always use absolute URLs - Always use absolute URLs
- Include `alt` text for accessibility - Set descriptive `alt` text on meaningful images; pass an explicit `alt=""` on decorative images so screen readers skip them — never omit the attribute
```tsx ```tsx
{/* Meaningful image — describe purpose and details */}
<Img <Img
src="https://example.com/image.png" src="https://example.com/hero.png"
alt="Description" alt="A team of engineers reviewing code on a laptop"
className="w-full h-auto" className="w-full h-auto"
/> />
{/* Decorative image — always pass an empty alt string so screen readers skip it */}
<Img
src="https://example.com/divider.png"
alt=""
className="w-full"
/>
``` ```
## Buttons ## Buttons