--- title: Emotion Styling Guidelines and Best Practices sidebar_position: 2 --- # Emotion Styling Guidelines and Best Practices ## Emotion Styling Guidelines ### DO these things: - **DO** use `styled` when you want to include additional (nested) class selectors in your styles - **DO** use `styled` components when you intend to export a styled component for re-use elsewhere - **DO** use `css` when you want to amend/merge sets of styles compositionally - **DO** use `css` when you're making a small, or single-use set of styles for a component - **DO** move your style definitions from direct usage in the `css` prop to an external variable when they get long - **DO** prefer tagged template literals (`css={css\`...\`}`) over style objects wherever possible for maximum style portability/consistency - **DO** use `useTheme` to get theme variables ### DON'T do these things: - **DON'T** use `styled` for small, single-use style tweaks that would be easier to read/review if they were inline - **DON'T** export incomplete Ant Design components ## When to use `css` or `styled` ### Use `css` for: 1. **Small, single-use styles** ```tsx import { css } from '@emotion/react'; const MyComponent = () => (
Content
); ``` 2. **Composing styles** ```tsx const baseStyles = css` padding: 16px; border-radius: 4px; `; const primaryStyles = css` ${baseStyles} background-color: blue; color: white; `; const secondaryStyles = css` ${baseStyles} background-color: gray; color: black; `; ``` 3. **Conditional styling** ```tsx const MyComponent = ({ isActive }: { isActive: boolean }) => (
Content
); ``` ### Use `styled` for: 1. **Reusable components** ```tsx import styled from '@emotion/styled'; const StyledButton = styled.button` padding: 12px 24px; border: none; border-radius: 4px; background-color: ${({ theme }) => theme.colors.primary}; color: white; &:hover { background-color: ${({ theme }) => theme.colors.primaryDark}; } `; ``` 2. **Components with complex nested selectors** ```tsx const StyledCard = styled.div` padding: 16px; border: 1px solid ${({ theme }) => theme.colors.border}; .card-header { font-weight: bold; margin-bottom: 8px; } .card-content { color: ${({ theme }) => theme.colors.text}; p { margin-bottom: 12px; } } `; ``` 3. **Extending Ant Design components** ```tsx import { Button } from 'antd'; import styled from '@emotion/styled'; const CustomButton = styled(Button)` border-radius: 8px; font-weight: 600; &.ant-btn-primary { background: linear-gradient(45deg, #1890ff, #722ed1); } `; ``` ## Using Theme Variables Always use theme variables for consistent styling: ```tsx import { useTheme } from '@emotion/react'; const MyComponent = () => { const theme = useTheme(); return (
Content
); }; ``` ## Common Patterns ### Responsive Design ```tsx const ResponsiveContainer = styled.div` display: flex; flex-direction: column; ${({ theme }) => theme.breakpoints.up('md')} { flex-direction: row; } `; ``` ### Animation ```tsx const FadeInComponent = styled.div` opacity: 0; transition: opacity 0.3s ease-in-out; &.visible { opacity: 1; } `; ``` ### Conditional Props ```tsx interface StyledDivProps { isHighlighted?: boolean; size?: 'small' | 'medium' | 'large'; } const StyledDiv = styled.div` padding: 16px; background-color: ${({ isHighlighted, theme }) => isHighlighted ? theme.colors.primary : theme.colors.grayscale.light5}; ${({ size }) => { switch (size) { case 'small': return css`font-size: 12px;`; case 'large': return css`font-size: 18px;`; default: return css`font-size: 14px;`; } }} `; ``` ## Best Practices ### 1. Use Semantic CSS Properties ```tsx // ✅ Good - semantic property names const Header = styled.h1` font-size: ${({ theme }) => theme.typography.sizes.xl}; margin-bottom: ${({ theme }) => theme.gridUnit * 4}px; `; // ❌ Avoid - magic numbers const Header = styled.h1` font-size: 24px; margin-bottom: 16px; `; ``` ### 2. Group Related Styles ```tsx // ✅ Good - grouped styles const Card = styled.div` /* Layout */ display: flex; flex-direction: column; padding: ${({ theme }) => theme.gridUnit * 4}px; /* Appearance */ background-color: ${({ theme }) => theme.colors.grayscale.light5}; border: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; border-radius: ${({ theme }) => theme.borderRadius}px; /* Typography */ font-family: ${({ theme }) => theme.typography.families.sansSerif}; color: ${({ theme }) => theme.colors.grayscale.dark2}; `; ``` ### 3. Extract Complex Styles ```tsx // ✅ Good - extract complex styles to variables const complexGradient = css` background: linear-gradient( 135deg, ${({ theme }) => theme.colors.primary} 0%, ${({ theme }) => theme.colors.secondary} 100% ); `; const GradientButton = styled.button` ${complexGradient} padding: 12px 24px; border: none; color: white; `; ``` ### 4. Avoid Deep Nesting ```tsx // ✅ Good - shallow nesting const Navigation = styled.nav` .nav-item { padding: 8px 16px; } .nav-link { color: ${({ theme }) => theme.colors.text}; text-decoration: none; } `; // ❌ Avoid - deep nesting const Navigation = styled.nav` ul { li { a { span { color: blue; /* Too nested */ } } } } `; ``` ## Performance Tips ### 1. Avoid Inline Functions in CSS ```tsx // ✅ Good - external function const getBackgroundColor = (isActive: boolean, theme: any) => isActive ? theme.colors.primary : theme.colors.secondary; const Button = styled.button<{ isActive: boolean }>` background-color: ${({ isActive, theme }) => getBackgroundColor(isActive, theme)}; `; // ❌ Avoid - inline function (creates new function on each render) const Button = styled.button<{ isActive: boolean }>` background-color: ${({ isActive, theme }) => isActive ? theme.colors.primary : theme.colors.secondary}; `; ``` ### 2. Use CSS Objects for Dynamic Styles ```tsx // For highly dynamic styles, consider CSS objects const dynamicStyles = (props: Props) => ({ backgroundColor: props.color, fontSize: `${props.size}px`, // ... other dynamic properties }); const DynamicComponent = (props: Props) => (
Content
); ```