Last modified: August 22, 2025
In this guide, learn about the different ways to include styling in your CMS React project. You can also refer to the styling example project for working examples of supported styling methods, including a number of major styling libraries. Below, learn more about each of the following methods:

Tailwind

Tailwind CSS is a framework designed to speed up the building process by providing utility classes for styling your markup without needing to write custom CSS. You can learn more about Tailwind CSS on HubSpot’s blog. To configure Tailwind for your components:
{
  "name": "my-react-app",
  "version": "0.1.0",
  "type": "module",
  "dependencies": {
    ...
    "tailwindcss": "^3.3.2"
  }
  ...
}
  • Add a Tailwind configuration file to your project subcomponent.
import { fileURLToPath } from 'url';
const componentsDir = fileURLToPath(new URL('./components', import.meta.url));

export default {
  content: [`${componentsDir}/**/*.{js,ts,jsx,tsx}`],
  theme: {
    extend: {},
  },
  plugins: [],
};
  • Add a PostCSS configuration file to your project subcomponent, then import the Tailwind configuration file and include Tailwind as a plugin along with any Tailwind-specific configuration.
import tailwind from 'tailwindcss';
import autoprefixer from 'autoprefixer';
import postcssNested from 'postcss-nested';
import tailwindConfig from './tailwind.config.js';

export default {
  plugins: [tailwind(tailwindConfig), postcssNested, autoprefixer()],
};
  • Create a tailwind.css file in your styles directory. Then, import that file in your top-level component with the base Tailwind layer directives.
See HubSpot’s styling example for more details.

styled-components

styled-components is a library that enables you to write CSS in JavaScript and inject styles dynamically. Learn more about the basics of styled-components. To use styled-components in your project:
{
  "name": "my-react-app",
  "version": "0.1.0",
  "type": "module",
  "dependencies": {
    ...
    "styled-components": "^6.0.3"
  }
  ...
}
  • Create a registry component using the styled-components server-side rendering API and useInlineHeadAsset(), and wrap the components you want to style in it. See the StyledComponentsRegistry.jsx example file for more details.
  • For each island you’re using, you must wrap each subtree in a registry to capture styles when rendering on the server. To make this easier, you may use the Wrapper prop on the Island component to wrap the contents without needing to edit the island components themselves. Note that this prop also lets you configure this once by replacing all instances of <Island /> with a <StyledIsland /> component that looks similar to the following:
import { Island } from '@hubspot/cms-components';
import StyledComponentsRegistry from './StyledComponentsRegistry?client';

export default function StyledIsland(props) {
  return <Island {...props} Wrapper={StyledComponentsRegistry} />;
}
Please note:As shown above, when using the Wrapper prop you must import the component with a ?client suffix to make sure it can be bundled for the client.
  • You can now import styled from 'styled-components' and use it to style your components.
import { useState, useId } from 'react';
import { styled } from 'styled-components';

const StyledButton = styled.button`
  padding: ${(props) => 10 + props.$count * 10}px;
`;

export default function InteractiveStyledComponent() {
  const id = useId();
  const [count, setCount] = useState(0);

  return (
    <StyledButton
      $count={count}
      onClick={() => setCount((prevCount) => prevCount + 1)}
    >
      Current count is: {count} {id}
    </StyledButton>
  );
}

styled-jsx

styled-jsx is a library that enables you to write encapsulated and scope CSS to style your components. By setting styles at the individual component level, you can add, change, and delete styles for one component without impacting others. To use styled-jsx in your project:
{
  "name": "my-react-app",
  "version": "0.1.0",
  "type": "module",
  "dependencies": {
    ...
    "styled-jsx": "^5.1.2"
  }
  ...
}
import { Island } from '@hubspot/cms-components';
import StyledComponentsRegistry from './StyledComponentsRegistry?client';

export default function StyledIsland(props) {
  return <Island {...props} Wrapper={StyledComponentsRegistry} />;
}
import { useState, useId } from 'react';

export default function InteractiveStyledJSXComponent() {
  const id = useId();
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount((prevCount) => prevCount + 1)}>
      Current count is: {count} {id}
      <style jsx>
        {`
          button {
            padding: ${10 + count * 10}px;
          }
        `}
      </style>
    </button>
  );
}

CSS Modules

CSS Modules is a CSS file where all class names and animation names are scoped locally by default. You can use CSS Modules within any React component by importing a file ending in .module.css, which will return a CSS module object:
import classes from './example.module.css';

export default function MyComponent() {
  return <div className={classes.red}>red text</div>;
}
When you import a CSS modules file from inside a React component:
  • A <style> tag will automatically be inserted into the page when the component is rendered server-side or when it’s dynamically rendered in the browser.
  • Those styles will automatically be namespaced so they don’t interfere with anything else on the page.
You can also import regular CSS files into your React components, but their selectors will not be automatically namespaced.

Dynamic styles based on props

If you need to dynamically adjust styles based on props, try one of the following options:
  • If you need conditional styling that is either on or off, you can have a className that the React component code conditionally renders in your JSX.
  • If you need dynamic styling that is not on or off, but rather a specific color or number that you need to apply to your styles:
    • You can define CSS custom properties in your CSS or CSS Modules code and inject new CSS custom property values via React.
    • Or use React to set inline styles on the specific part of the module HTML.
The code below shows examples of each of the above techniques.
import styles from './example2.module.css';

export default function FancierComponent(props) {
const { hasPurpleBorder, paddingPx, customSecondTextColor } = props;

// Example: toggling styles via a prop
const classes = [styles['fancy-module-wrapper']];
  if (hasPurpleBorder) {
  classes.push(styles['purple-border']);
}

// Example: using inline style attribute (with React's style syntax)
const inlineStyles = { padding: paddingPx };

// Example: setting a CSS custom property value that's picked up by other CSS
const inlineAndCustomPropertyStyles = {
  ...inlineStyles,
  '--second-text-color': customSecondTextColor,
};

return (
<div className={classes.join(' ')} style={inlineAndCustomPropertyStyles}>
  <p>First text</p>
  <p className={styles['second-text']}>Second text</p>
</div>
);
}

Using other CSS-in-JS libraries

CMS React projects support any CSS-in-JS libraries that provide a server-side rendering API and don’t depend on a Babel plugin. The same registry patterns described above can be generalized for other libraries to emit CSS to include as part of the server-side render. You’ll also need to include the registry as a Wrapper on any <Island> component if there are styles within the island.