Tailwind directives in generated HTML when safelist defined. Breaks styling in Gmail
Describe the Bug
When using a custom tailwind config with a safelist, and using responsive tailwind classes, the generated HTML has a style tag with tailwind directives. These directives are invalid CSS which would seem to cause gmail to ignore the style tag entirely.
The directives can be seen in the dev servers code preview pane and in the HTML files generated with the export command.
Dev server Preview
HTML file
When testing emails with an email testing service, some styling was not looking right in some gmail clients. After some debugging, I realized that styles defined in the style tag were only respected when I removed the tailwind directives.
The provided minimal reproduction has 2 emails, one using a custom tailwind config and another that uses the same tailwind config with a safelist added. I have also included the HTML files for both emails generated with the export command.
Which package is affected (leave empty if unsure)
@react-email/tailwind
Link to the code that reproduces this issue
https://github.com/summer-jordan/tw-directive-bug-repro/
To Reproduce
- Create a new project with:
pnpm create email - Create an email that uses the
Tailwindcomponent - Define a tailwind config that has a safelist defined with at least one class
- Add a responsive tailwind class to the email:
md:p-4(This is required so that a style tag is created) - Run the dev server and view the HTML preview (directives will be in the style tag)
- Run the export command (directives will be in the style tag)
Expected Behavior
There should be no tailwind directives in the HTML.
What's your node version? (if relevant)
22.14.0
I want to work on this issue, Would you like to assign me?
I wonder why you need to safelist here, it doesn't seem really needed for the email use case. Can you comment on that @summer-jordan?
Looking at it, the way to go here is to just delete it from the config and warn that the no behavior change will happen because of safelist. safelist doesn't make sense when we talk about inlining most styles, and much less in the email HTML environment.
I wonder why you need to
safelisthere, it doesn't seem really needed for the email use case. Can you comment on that @summer-jordan?
We are building a design system for emails using react-email. Keeping in line with our design system for web, we provide props for specifying margin and padding. These props are converted into classes dynamically. Since we do not have the tailwind classes appearing as a single, unbroken string, the spacing classes do not get converted into inline styles unless we add them to the safelist. https://tailwindcss.com/docs/detecting-classes-in-source-files#dynamic-class-names
Since a consumer of the design system could use any of the available spacing classes, we safelist all of them dynamically. We did not want to keep a list of all available spacing classes as that is quite verbose. I will update the code in my reproduction to demonstrate sometime today.
@summer-jordan can you make a minmal code example of what you mean here? Because it seems to me like it would work without the safelist as React Email only computes the styles from the final className, not from the code itself like normal TailwindCSS.
@gabrielmfern I was able to finally test this out and everything seems to work as you described. I removed the safelist in our codebase and all styles were still generated properly. Thank you for your assistance.
Its seems this is fixed, can we close it @gabrielmfern 😄
@Syed-Umair I think we'll keep it open until we have a decided treatment for Tailwind's safe list, most likely throwing an error when it's used.
We just released a new version that makes safelist a certain no-op and warns when it is enabled in the user's configuration. @react-email/[email protected]/@react-email/[email protected]