Skip to content

Base styles from custom classes are not being inlined if they contain a media queryΒ #2909

@Zdend

Description

@Zdend

What versions are you using? (if relevant)

@react-email/components@1.0.6, react-email@5.2.5

Describe the Bug

When I define a custom class using a plugin, where this class contains base styles (no media queries) and additional styles behind media queries, the base styles don't end up being inlined where the class is used. It correctly keeps the class attached and keeps the styles in the head, however, not every email clients retains the head and so it would lead to broken experience in those email clients.

The expected behaviour is that it should inline all the base classes, retain the class on the element and keep the media query styles in the head for progressive enhancement.

What is affected (leave empty if unsure)

Tailwind Component

Link to the code that reproduces this issue

N/A

To Reproduce

Create a simple template and observe the result inside the preview

import { Body, Head, Html, Text, Tailwind } from '@react-email/components';
import plugin from 'tailwindcss/plugin';

const Foo = () => {
  return (
    <Tailwind
      config={{
        darkMode: 'media',
        plugins: [
          plugin(function ({ addUtilities }) {
            addUtilities({
              '.text-body': {
                '@apply text-[green] dark:text-[orange]': {},
              },
            });
          }),
        ],
      }}
    >
      <Html>
        <Head />
        <Body>
          <Text className="text-body">
            This text should be green in light mode and orange in dark mode
          </Text>
        </Body>
      </Html>
    </Tailwind>
  );
};

export default Foo;

Current result

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" lang="en">
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <meta name="x-apple-disable-message-reformatting" />
    <style>
      .text-body{color:green!important;@media (prefers-color-scheme:dark){color:orange!important}}
    </style>
  </head>
  <body>
    <!--$-->
    <table
      border="0"
      width="100%"
      cellpadding="0"
      cellspacing="0"
      role="presentation"
      align="center">
      <tbody>
        <tr>
          <td>
            <p
              class="text-body"
              style="font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px">
              This text should be green in light mode and orange in dark mode
            </p>
          </td>
        </tr>
      </tbody>
    </table>
    <!--7--><!--/$-->
  </body>
</html>

Expected Behavior

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" lang="en">
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <meta name="x-apple-disable-message-reformatting" />
    <style>
      .text-body{@media (prefers-color-scheme:dark){color:orange!important}}
    </style>
  </head>
  <body>
    <!--$-->
    <table
      border="0"
      width="100%"
      cellpadding="0"
      cellspacing="0"
      role="presentation"
      align="center">
      <tbody>
        <tr>
          <td>
            <p
              class="text-body"
              style="font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px;color:green;">
              This text should be green in light mode and orange in dark mode
            </p>
          </td>
        </tr>
      </tbody>
    </table>
    <!--7--><!--/$-->
  </body>
</html>

As you can see color:green; is inlined in the style attribute and can be safely removed from the class definition in the head.

What's your node version? (if relevant)

v24.11.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions