You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Emotion主题中使用styled组件、插值及css方法调用主题?

Question

I'm building a React-based web app using the emotion-theming library to implement dynamic themes that support user environment switching—each environment maps to an independent theme. I've already built a custom CustomThemeProvider to handle dynamic theme switching, and the code works fine: I can retrieve the theme in functional components using emotion's useTheme hook.

However, I'm stuck on how to access and apply the theme from emotion's ThemeProvider in these three specific scenarios:

  1. Interpolation cases like export const style: Interpolation = { cssProp: value };
  2. Components created with emotion/styled, e.g., const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps> = styled.button([]);
  3. Scenarios using the css() method from emotion/core, e.g., const style = css({ cssProp: value });

I haven't found clear answers via Google, so I'm hoping to get guidance here.

My Current Theme Setup Code

export interface CustomThemeContextValue { 
  customTheme?: Theme; 
  setCustomTheme: (theme: Theme) => void; 
};
const CustomThemeContext = React.createContext<CustomThemeContextValue>({ 
  customTheme: undefined, 
  setCustomTheme: (theme) => { } 
});
interface CustomThemeProviderProps { }
export const CustomThemeProvider: FC<CustomThemeProviderProps> = (props) => { 
  const [customTheme, setCustomTheme] = useState<Theme>(theme); 
  const context: CustomThemeContextValue = React.useMemo(
    () => ({ customTheme, setCustomTheme }), 
    [customTheme, setCustomTheme]
  ); 
  return ( 
    <CustomThemeContext.Provider value={context}> 
      <ThemeProvider theme={customTheme} {...props} /> 
    </CustomThemeContext.Provider> 
  ); 
};
export const useCustomTheme = () => { 
  const context = React.useContext(CustomThemeContext); 
  if (!context) { 
    throw new Error('useCustomTheme must be used within a CustomThemeProvider'); 
  } 
  return context; 
};

Root Component Implementation

const Root = () => { 
  return ( 
    <StrictMode> 
      <CustomThemeProvider> 
        <Normalize /> 
        <Global styles={globalStyle} /> 
        <App /> 
      </CustomThemeProvider> 
    </StrictMode> 
  ) 
};

Answer

Great question! All three scenarios can leverage emotion's built-in theme-aware styling once you use the right pattern. Let's break down each case:

1. Using Theme in Interpolation Objects

Instead of defining static styles, you can turn your Interpolation into a function that receives the current theme as an argument. This lets you dynamically pull values from your theme:

// Theme-aware interpolation
export const style: Interpolation<Theme> = (theme) => ({
  color: theme.colors.primary,
  backgroundColor: theme.colors.surface,
  padding: theme.spacing.md,
  borderRadius: theme.borderRadius.sm
});

You can use this style anywhere emotion accepts interpolations—like in the css prop or inside a styled component.

2. Using Theme in emotion/styled Components

Styled components from emotion can directly access the theme by using a function instead of a static object/template literal. Here's how to adjust your Button component:

Option 1: Basic theme access

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps> = styled.button(({ theme }) => ({
  backgroundColor: theme.colors.primary,
  color: theme.colors.textOnPrimary,
  padding: `${theme.spacing.sm} ${theme.spacing.md}`,
  border: 'none',
  cursor: 'pointer'
}));

Option 2: Combine theme with component props

If you need to adjust styles based on component props alongside the theme:

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps> = styled.button(({ theme, variant = 'primary' }) => ({
  backgroundColor: variant === 'primary' ? theme.colors.primary : theme.colors.secondary,
  color: theme.colors.textOnPrimary,
  // ... other dynamic styles
}));

Option 3: Template literal syntax

If you prefer template literals, you can interpolate the theme like this:

const Button = styled.button`
  background-color: ${({ theme }) => theme.colors.primary};
  color: ${({ theme }) => theme.colors.textOnPrimary};
  padding: ${({ theme }) => `${theme.spacing.sm} ${theme.spacing.md}`};
`;

3. Using Theme with emotion/core's css() Method

Just like interpolations, the css() function can take a theme-receiving function to generate dynamic styles:

// Theme-aware css style
const style = css((theme) => ({
  color: theme.colors.textBody,
  fontSize: theme.fontSizes.body,
  lineHeight: theme.lineHeights.body,
  marginBottom: theme.spacing.sm
}));

// Use it in a component
const TextBlock = () => {
  return <div css={style}>This text uses theme values!</div>;
};

Quick Note

All these approaches work seamlessly because your CustomThemeProvider wraps emotion's native ThemeProvider—any nested component or style function will automatically inherit the current theme from emotion's context. You only need your useCustomTheme hook when you want to modify the theme (like triggering a switch); for reading theme values, emotion's built-in theme access is all you need.

内容的提问来源于stack exchange,提问作者joeldebont

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:03:10