`<Tailwind>`: Outlook.com ignores every media query after the first, because the generated `<style>` has adjacent `}}`
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 78/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- react, tailwindcss, typescript
- 领域
- frontend
调研方向
从 packages/react-email/src/components/tailwind/tailwind.tsx 中的 generate(nonInlineStyles) 开始,阅读样式表的序列化方式;issue 还指出了 downlevel-for-email-clients.ts,其中包含现有的邮件客户端适配逻辑。检查包含多个 @media 块的 <style> 生成结果,并确认相邻的右花括号之间有空白分隔,同时保留 CSS 规则。
由索引模型根据 Issue 内容生成。
描述
What versions are you using? (if relevant)
[email protected] (bundled / render), [email protected] (latest of both at time of writing)
Describe the Bug
Outlook.com deletes everything in a <style> element that comes after two adjacent closing braces, }}. This is a long-standing client bug, documented in hteumeuleu/email-bugs#92. The documented workaround is any whitespace between the braces (} }).
<Tailwind> puts every non-inlinable rule in its own @media block and writes the stylesheet minified (generate(nonInlineStyles) in tailwind.tsx). Every block ends in }} and they all share one <style>, so Outlook.com keeps the first @media block and drops the rest.
In practice only one responsive (sm:, md:, …) or dark: rule per email works in Outlook.com. Columns that sit side by side through sm: widths stay stacked at desktop width, and only the first dark-mode colour applies. I've also seen the same thing in Outlook on the web with a Microsoft 365 mailbox and in the new Outlook for Windows.
The CSS is valid, so strictly this is Outlook's bug. But <Tailwind> already adapts its output for email clients (downlevel-for-email-clients.ts), and fixing it there would cover everyone who uses responsive or dark: classes. render(..., { pretty: true }) doesn't help: the <style> contents keep their }}.
Suggested fix: when writing the non-inlinable stylesheet, put whitespace between adjacent closing braces (} }). Merging identical media queries would not be enough on its own: with two different queries (a breakpoint and dark:), the second block still comes after a }}.
What is affected (leave empty if unsure)
Tailwind Component
Link to the code that reproduces this issue
https://github.com/lpolito/react-email-outlook-double-brace
Minimal, self-contained (react-email + tailwindcss only). Core of render.tsx:
import { Body, Head, Html, render, Tailwind } from "react-email";
// Four boxes, each red inline and turned green by its own `sm:` rule.
const Email = () => (
<Tailwind>
<Html>
<Head />
<Body>
<div className="bg-[#cf222e] sm:bg-[#1a7f37]">Box 1</div>
<div className="bg-[#cf222e] sm:bg-[#1f883d]">Box 2</div>
<div className="bg-[#cf222e] sm:bg-[#2da44e]">Box 3</div>
<div className="bg-[#cf222e] sm:bg-[#116329]">Box 4</div>
</Body>
</Html>
</Tailwind>
);
const html = await render(<Email />);
To Reproduce
npm install
npm run render
This writes out/raw.html (react-email's output, unchanged) and out/spaced.html (the same, with one space between each pair of adjacent closing braces inside <style>). The generated <style>:
@media (min-width: 40rem) {
.sm_bg-_1a7f37 {
background-color: rgb(26, 127, 55) !important;
}
}
@media (min-width: 40rem) {
.sm_bg-_1f883d {
background-color: rgb(31, 136, 61) !important;
}
}
@media (min-width: 40rem) {
.sm_bg-_2da44e {
background-color: rgb(45, 164, 78) !important;
}
}
@media (min-width: 40rem) {
.sm_bg-_116329 {
background-color: rgb(17, 99, 41) !important;
}
}
Open both in Outlook.com at desktop width (I used Litmus's Outlook.com client in Chrome).
out/raw.html: box 1 is green, boxes 2–4 stay red.

out/spaced.html: all four are green. (A Microsoft promo pop-up covers part of the top.)

Expected Behavior
Every @media block that <Tailwind> generates survives in Outlook.com, so all four boxes are green at desktop width.
What's your node version? (if relevant)
v24.18.0
- 主要语言
- TypeScript
- 星标
- 19.9k
- 派生
- 1.1k
- 平均合并
- 2 天 15 小时
- 30 天内合并 PR
- 61
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
resend/react-email 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 48/100
resend/react-email#3878 · 1 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
Tailwind stacked media variants leave nested CSS in rendered emails可能已有人在做 @lakshya-dhariwal 于 3 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 35/100
resend/react-email#3874 ·
维护者通常 1 天内回复
-
Inspector Text panel omits Uppercase mark toggle (MARK_NAMES missing "uppercase")可能已有人在做 @svargas-dev 于 9 天前认领。 未关闭
难度 1/5 1 小时以内 新手友好度 22/100
resend/react-email#3849 ·
维护者通常 1 天内回复
-
bug(tailwind): `pixelBasedPreset` only converts spacing and font size; `rounded-*` and `max-w-*` still emit `rem`可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 3/5 1-2 天 新手友好度 45/100
resend/react-email#3845 ·
维护者通常 1 天内回复
-
dependencies
难度 5/5 一周以上 新手友好度 15/100
resend/react-email#746 ·
维护者通常 1 天内回复
查看 resend/react-email 的全部 Issue
相似的 Issue
-
enhancement language
难度 2/5 1-3 小时 新手友好度 67/100
pngwn/twinkleplop#178 ·
-
build P3
难度 2/5 1-3 小时 新手友好度 82/100
maniator/verticopolis#1945 ·
维护者通常 1 天内回复
-
Admin users page number stays stale after filtering可能已有人在做 @matthewxkong 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
feature request needs triage
难度 2/5 1-3 小时 新手友好度 72/100
-
bug
难度 2/5 1-3 小时 新手友好度 67/100
outline/outline#14529 · 1 条评论 ·
维护者通常 1 天内回复