Inline Styles in React: Dynamic CSS Tutorial
React's style prop allows you to apply styles directly to JSX elements using JavaScript objects instead of CSS strings. Unlike HTML's style attribute (which accepts a string like "color: blue"), React's style prop requires a JavaScript object with camelCased CSS property names, enabling dynamic styling based on component state and props. This guide explains the syntax, best practices, and when to use inline styles versus CSS classes.
Understanding React's style Prop vs. HTML Styles
How does React's style prop differ from HTML's style attribute?
In standard HTML, the style attribute accepts a string of CSS:
<!-- HTML approach -->
<div style="background-color: #f0f0f0; font-size: 16px;">Hello</div>
In React, the style prop accepts a JavaScript object, not a string:
// React approach
<div style={{ backgroundColor: '#f0f0f0', fontSize: '16px' }}>Hello</div>
The key differences are:
- Object syntax — Styles are key-value pairs in a JavaScript object, not a quoted string.
- camelCase properties — CSS properties with hyphens (
background-color,font-size) become camelCase (backgroundColor,fontSize). - String values — Style values must be strings or numbers (e.g.,
'16px','#f0f0f0',10).
This object-based approach has a critical advantage: you can use JavaScript variables and logic to calculate styles dynamically, adapting your component's appearance based on state, props, user interactions, or screen size. This is why inline styles are powerful for interactive React applications.
Demystifying the "Double-Curly" Syntax
Why does style={{...}} have double braces?
The style={{...}} syntax confuses many beginners because it looks like special React syntax, but it's actually two familiar JavaScript concepts combined:
- Outer braces
{ }— These are JSX expression delimiters, signaling to React that you're writing a JavaScript expression (not plain text). - Inner braces
{ }— These are the literal syntax for creating a JavaScript object.
So style={{ color: 'blue' }} is just shorthand for:
// Equivalent approaches:
<div style={{ color: 'blue' }}>Text</div>
<div style={styles}>Text</div> // where styles = { color: 'blue' }
For multiple properties, define the style object separately for readability:
function WelcomeMessage() {
const messageStyles = {
color: 'navy',
backgroundColor: 'lightcyan',
border: '1px solid navy',
padding: '20px',
borderRadius: '8px'
};
return (
<div style={messageStyles}>
<h1>Welcome Aboard!</h1>
<p>We're glad to have you.</p>
</div>
);
}
This approach is far more readable than cramming a large object into JSX, and it makes it easy to reuse styles across multiple elements within the same component.
CSS Property Names: Converting to camelCase
Which CSS properties need to be converted, and how?
All hyphenated CSS properties must be converted to camelCase in React's style objects. Here's a reference table of common conversions:
| CSS Property | React Style Object |
|---|---|
background-color | backgroundColor |
font-size | fontSize |
text-align | textAlign |
border-radius | borderRadius |
padding-left | paddingLeft |
z-index | zIndex |
flex-direction | flexDirection |
grid-template-columns | gridTemplateColumns |
Properties without hyphens like color, width, height, margin, and padding remain unchanged. The camelCase rule applies only to multi-word CSS properties separated by hyphens.
When to Use Inline Styles vs. CSS Classes
Best use cases for inline styles
Inline styles excel in these scenarios:
- Dynamic styles based on state or props — This is the primary advantage. When a button's color changes based on its
disabledstate, or a progress bar's width updates in real-time, inline styles shine. - Computed values — Calculating dimensions at runtime (e.g., positioning a dropdown menu below a button using the button's measured position).
- Rapid prototyping — Testing style changes quickly without switching between JS and CSS files.
- Truly unique, one-off styles — If a style is specific to a single component instance and never reused, inline styles avoid unnecessary CSS files.
Example of dynamic inline styles:
function ProgressBar({ percent }) {
const barStyle = {
width: `${percent}%`,
height: '20px',
backgroundColor: percent < 50 ? 'red' : 'green',
transition: 'width 0.3s ease'
};
return <div style={barStyle}></div>;
}
When to avoid inline styles and use CSS instead
- Shared styles across components — If five components use the same button style, define a
.buttonclass once in CSS instead of repeating the style object. - Media queries and pseudo-classes — Inline styles cannot handle
@mediaqueries,:hover,:focus, or other pseudo-selectors. These require CSS files. - Browser prefixes — Inline styles don't automatically add vendor prefixes like
-webkit-or-moz-. CSS preprocessors like Sass handle this automatically. - Performance-critical applications — Browsers are highly optimized for CSS classes; applying styles via class names is marginally faster than inline styles. For typical applications, the difference is negligible.
- Theme switching — If your app supports light/dark modes, defining classes in CSS and toggling them is cleaner than managing multiple inline style objects.
Best Practices for Inline Styles in React
Follow these guidelines to write maintainable inline styles
- Reserve inline styles for dynamic values — Static styles should live in CSS files or CSS Modules for clarity and reusability.
- Define objects separately — For anything beyond one or two properties, move the style object above the
returnstatement for readability. - Always use camelCase — Remember to convert
background-colortobackgroundColor,padding-lefttopaddingLeft, etc. - Be explicit with units — While React adds
pxto numeric values for properties likewidthandfontSize, always provide units as strings for clarity:fontSize: '16px',margin: '1rem'. - Extract style objects to constants or separate functions — For components with many dynamic styles, define style-generating functions for maintainability.
Example of extracted style logic:
function Button({ isDisabled, color = 'primary' }) {
const getButtonStyle = () => ({
backgroundColor: isDisabled ? '#ccc' : color === 'primary' ? '#007bff' : '#28a745',
color: '#fff',
padding: '10px 20px',
border: 'none',
borderRadius: '4px',
cursor: isDisabled ? 'not-allowed' : 'pointer',
opacity: isDisabled ? 0.6 : 1
});
return <button style={getButtonStyle()}>Click me</button>;
}
Key Takeaways
- React's
styleprop takes a JavaScript object with camelCased CSS property names, not a CSS string like HTML'sstyleattribute. - camelCase conversion is required —
background-colorbecomesbackgroundColor,padding-leftbecomespaddingLeft. - Double braces
{{are not special syntax — the outer braces are JSX expression delimiters, the inner braces create the JavaScript object literal. - Best for dynamic styles — Inline styles excel when styling depends on component state, props, or computed values.
- Use CSS classes for static, shared styles — Define reusable styles in CSS files or CSS Modules to avoid duplication.
- Cannot handle media queries or pseudo-classes — Styles like
:hover,:focus, and@mediaqueries require CSS files.
Frequently Asked Questions
Can I use media queries with inline styles in React?
No. Inline styles cannot handle media queries (@media), pseudo-selectors (:hover, :focus), or pseudo-elements (::before, ::after). For responsive design and interactive states, use CSS classes or CSS-in-JS libraries like styled-components or Emotion that can generate CSS dynamically.
Do I need to add vendor prefixes like -webkit- for inline styles?
React does not automatically add vendor prefixes to inline styles. Modern browsers support most properties without prefixes, but for compatibility with older browsers (which most projects no longer support), use CSS-in-JS libraries or CSS preprocessors like Sass, which handle prefixing automatically.
Should I define style objects inside or outside the component?
Define frequently-reused style objects outside the component to avoid recreating them on every render, which can impact performance. For dynamic styles that change based on props or state, define them inside the component so they can access the current values. If the object is complex, extract it to a function that accepts dependencies and returns the computed style object.
Can inline styles override CSS classes?
Technically no—CSS specificity rules apply. A CSS class from an external stylesheet has the same specificity as an inline style, so the order matters. Generally, avoid mixing inline styles and CSS classes on the same element; choose one approach and stick with it. If you must use both, inline styles should override classes due to CSS specificity.
What's the performance difference between inline styles and CSS classes?
In modern React, the performance difference is negligible for most applications. Browsers are optimized for CSS classes, but the overhead of inline styles is so small (microseconds) that it only matters in extreme cases. Use inline styles when they're the right tool (dynamic styling), and use CSS classes for static styles. Clarity and maintainability matter more than this micro-optimization.