shellscape / jsx-email

Build emails with a delightful DX
https://jsx.email
MIT License
897 stars 28 forks source link

Tailwind classes rendered in head don't get forwarded #121

Open mckelveygreg opened 6 months ago

mckelveygreg commented 6 months ago

Expected Behavior

Tailwind styles are converted to inline styles unless they have media queries.

Actual Behavior

All tailwind ends up in the head, so forwarded emails won't have original styling.

Additional Information

When using react-email last year, I ran into the problem where my designer excited forwarded me the email template I made, only for me to find out that the head (and styles) doesn't get forwarded!

For development, I decided to do the templates Mobile first, and any responsive css would then end up in the head (that is the only place for media queries). This resulted in an email that could be mobile or desktop, but would fallback to mobile if forwarded / resent anywhere else.

For our emails, it is very important that they can be sent, resent, and maintain at least a mobile fallback.


I poked around UnoCSS to see if they have a similar tw-to-css function, and I wasn't able to find anything. Perhaps we could add that as a transformer, but I'm unfamiliar with the lib.


I made a very quick example of an example email, and then I forwarded it to show that the tailwind colors didn't come along:

Original:

image

Forwarded:

image

Perhaps I could be of more help if I could be pointed in a good direction as well! Excited to be able to move to jsx-email and keep contributing

shellscape commented 6 months ago

Hey thanks for opening an issue and the kind words. We actually looked at a similar thing when we were debugging some issues with gmail styles in classes in as well. What we arrived on was using https://github.com/posthtml/posthtml-inline-css. tw-to-css is a great project but just isn't efficient enough for the speed we wanted to achieve.

We ended up finding a better way around the issues we were triaging (hashing class names and replacing css vars). posthtml is an interesting project, they aim to be postcss for html. posthtml-inline-css worked well in demos, but getting it to bundle correctly for our preview app (and anyone else wanting to bundle templates) was a hard slog - it's just not meant to be bundled. That said, it could be a really great post-processing tool for you, if you're running something serverside or in a worker. (It's worth noting that my interaction with the lead maintainer of that project was not positive)

What we do use internally is https://github.com/rehypejs/rehype, which is also an html processing package, and bundles quite nicely. While it doesn't have anything premade to handle this, I wouldn't be opposed to including a plugin for rehype that processed CSS in <head> and <style> tags and inlined it. The one warning I have for you about that is - the size of the email will explode. One great benefit to jsx-email over react-email is the size of the output, especially with tailwind. It can be as much as 10x smaller because we don't inline the tailwind css into style attributes. If you were up for trying your hand at a rehype plugin, we could include an inlineCss option for the render method that would run your plugin as part of processing.

Hope all that made sense 😄

shellscape commented 6 months ago

I did find this https://github.com/tani/rehype-inline-css which would be a good basis. It's using an outdated css package that doesn't support modern css and would probably swap that out for postcss, but it's a start.

grahamplace commented 4 months ago

Having this same issue — just to summarize / make sure my understanding of the current status is right:

shellscape commented 4 months ago

@grahamplace not entirely.

Gmail (and it seems limited to Gmail) strips <head> tags when forwarding (and it's selective about replies).

The current workaround is to use the rehype plugin linked to above - for usage, reference this https://github.com/rehypejs/rehype?tab=readme-ov-file#what-is-this and expand Show example code. And that rehype plugin works very well.

If Tailwind accelerates your development and makes maintenance easier, I would suggest introducing an additional step that ran the html from jsx-email through that rehype plugin. The next major version of jsx-email is in development and will provide an internal option to inline the css, but it requires some breaking changes we can't introduce to the 1.x.x version.

samducker commented 3 months ago

So I seem to be needing to put important infront of all of my text styles I don't know if this is related?

Perhaps the compiler could automatically make all tailwind styles important or reset the base style sheet?

shellscape commented 3 months ago

@samducker you should be able to use? disableDefaultStyle. https://jsx.email/docs/components/hr#component-props

(but yeah that's unrelated to this issue)

shellscape commented 3 months ago

I've got a solution for the forwarded emails in mind, and I'll be working on that over the next week. What I have in mind will be in the next v2.0.0 preview.

shellscape commented 3 months ago

Just wrapped up work on a new hooks system to allow for this. More to come...

shellscape commented 2 months ago

I've implemented a new plugin for the next release that inlines CSS which will effectively resolve this issue. I just can't close this until we release that new version. Still a bunch to wrap up on that before we can.