π§ Mastering Styling in React: From Basics to Custom Components
When building React applications, a key part of creating visually appealing and maintainable UIs is styling. This post walks you through the fundamentals of styling in React, how JSX relates to the DOM, and how to create a custom reusable <Box />
component that encapsulates consistent styling behavior.
React supports two main methods for styling:
style
propclassName
propEach approach has its strengths and tradeoffs, and understanding how JSX relates to HTML and the DOM is key to using them effectively.
In HTML, you work with attributes like this:
<div class="my-class"></div>
But in React (JSX), you use DOM property names, not HTML attributes:
<div className="my-class" />
Why? Because JSX is syntactic sugar for JavaScript function calls (React.createElement
). And React uses the DOM property equivalents under the hood. Here are a few key differences:
HTML Attribute | JSX Prop |
---|---|
class | className |
for | htmlFor |
tabindex | tabIndex |
readonly | readOnly |
This distinction is important, especially when youβre debugging or dynamically setting properties.
In HTML:
<div style="margin-top: 20px; background-color: blue;"></div>
In JSX, you pass an object, not a string:
<div style={{ marginTop: 20, backgroundColor: 'blue' }} />
A few key notes:
{}
tells JSX youβre injecting a JavaScript expression.{}
defines the actual object.camelCase
instead of kebab-case
.β Example:
const myStyles = { marginTop: 20, backgroundColor: 'blue' }<div style={myStyles} />
β οΈ Limitations: No pseudo-classes (:hover
, :focus
) or media queries. For those, stick with regular CSS.
className
The most common way to style elements is still with CSS classes.
Step 1: Define your class in a CSS file:
/* index.css */.my-class {margin-top: 20px;background-color: blue;}
Step 2: Use it in your JSX:
<div className="my-class" />
Step 3: Make sure your CSS is loaded:
<link rel="stylesheet" href="index.css" />
In a real app, this might be handled automatically by your build tool (e.g., Vite, CRA, or Webpack).
<Box />
ComponentLetβs reduce repetition and increase reusability by building a Box
component that:
className="box"
and style={{ fontStyle: 'italic' }}
className
and style
props from the user<Box className="box--small" style={{ backgroundColor: 'lightblue' }}>small lightblue box</Box>
<divclassName="box box--small"style={{ fontStyle: 'italic', backgroundColor: 'lightblue' }}>small lightblue box</div>
type BoxProps = React.ComponentProps<'div'>function Box({ className = '', style = {}, ...props }: BoxProps) {return (<divclassName={`box ${className}`}style={{ fontStyle: 'italic', ...style }}{...props}/>)}
To inherit all props from a native HTML element (like div
), use:
React.ComponentProps<'div'>
This gives you full type safety and IntelliSense support in your custom component.
size
Prop for Better API DesignNow letβs improve the DX (Developer Experience) by replacing manual class names with a semantic size
prop:
<Box size="small" style={{ backgroundColor: 'lightblue' }}>small lightblue box</Box>
'small' | 'medium' | 'large'
box--small
) internallytype BoxSize = 'small' | 'medium' | 'large'type BoxProps = {size?: BoxSize} & React.ComponentProps<'div'>function Box({ size, className = '', style = {}, ...props }: BoxProps) {const sizeClassName = size ? `box--${size}` : ''return (<divclassName={`box ${sizeClassName} ${className}`.trim()}style={{ fontStyle: 'italic', ...style }}{...props}/>)}
By learning how JSX maps to the DOM and mastering both className
and style
usage in React, youβre now equipped to:
size
This is a foundational skill every React developer should master. Keep exploring and experimenting β youβll build beautiful, scalable UIs in no time!
π Resources
Happy styling! π¨β¨
Quick Links
Legal Stuff
Social Media