I choose styling tools based on the project’s complexity, team preferences, scalability, and performance needs.
| Technique | Pros | Cons |
|---|---|---|
| CSS-in-JS(e.g., Emotion, styled-components) | Scoped styles, dynamic theming, colocated with components | Runtime overhead, harder to extract critical CSS |
| Styled Components | Component-driven, theming support, autoscoping | Bundle size, runtime parsing, toolchain complexity |
| Sass (SCSS) | Nesting, variables, mixins, mature tooling | Global scope by default, manual BEM or conventions needed |
| TailwindCSS | Utility-first, fast prototyping, responsive by default | Verbose class names, learning curve, poor separation of concerns |
My default : Tailwind for fast-moving teams or design systems; Styled Components for themeable component libraries.
rem, %, vh/vw) and media queries.sm:, md:) for breakpoint-driven styling.useWindowSize hook or libraries like react-responsive when needed for behavior, not just style.Use a theme state (or context), toggle a class on the body or html, and style conditionally.
CSS-in-JS example : Use a ThemeProvider with light/dark themes.
import styled from 'styled-components';
const Button = styled.button`
padding: 0.5rem 1rem;
border-radius: 4px;
font-weight: bold;
background: ${({ variant }) =>
variant === 'primary' ? '#007bff' : '#6c757d'};
color: white;
border: none;
cursor: pointer;
&:hover {
opacity: 0.9;
}
`;
// Usage:
<Button variant="primary">Save</Button>
<Button variant="secondary">Cancel</Button>
Pros:
Cons:
clsx, cva).Styling logic embedded in JSX—harder to reuse if not abstracted properly.
Mitigation : Use helper utilities (clsx, tailwind-variants) and design tokens to reduce duplication.
body.my-app) and avoid generic selectors.!important unless absolutely necessary.import "./Fade.css"; // .fade { opacity: 0; transition: opacity 0.3s } .fade.show { opacity: 1; }
const FadeComponent = ({ visible }) => (
<div className={`fade ${visible ? "show" : ""}`}>Hello</div>
);