CSS Best Practices Guide: Write Better, Cleaner CSS
Hey there, code quality enthusiast! 👋 Ready to level up your CSS game? Today, we’re diving into CSS best practices that will make your code cleaner, more maintainable, and easier to scale. Let’s turn that CSS spaghetti into a well-organized feast!
The Foundation: Organization and Structure
1. File Organization
/* style.css */
/* 1. Settings/Variables */
@import 'settings/variables.css';
@import 'settings/breakpoints.css';
/* 2. Base Styles */
@import 'base/reset.css';
@import 'base/typography.css';
/* 3. Layout */
@import 'layout/grid.css';
@import 'layout/containers.css';
/* 4. Components */
@import 'components/buttons.css';
@import 'components/cards.css';
/* 5. Utilities */
@import 'utilities/spacing.css';
@import 'utilities/colors.css';
2. Component-Based Structure
/* components/card.css */
.card {
/* Base card styles */
}
.card__header {
/* Card header styles */
}
.card__content {
/* Card content styles */
}
.card--featured {
/* Featured card variant */
}
Naming Conventions
BEM (Block Element Modifier) Methodology
/* Block */
.button {
padding: 1rem 2rem;
border-radius: 4px;
}
/* Element */
.button__icon {
margin-right: 0.5rem;
}
/* Modifier */
.button--large {
padding: 1.5rem 3rem;
}
.button--primary {
background-color: var(--color-primary);
}
ITCSS (Inverted Triangle CSS) Architecture
/* 1. Settings - Variables, config */
:root {
--primary-color: #3498db;
}
/* 2. Tools - Mixins, functions */
@mixin center-flex {
display: flex;
justify-content: center;
align-items: center;
}
/* 3. Generic - Reset, normalize */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 4. Elements - Bare HTML elements */
body {
font-family: sans-serif;
line-height: 1.6;
}
/* 5. Objects - Design patterns */
.container {
max-width: 1200px;
margin: 0 auto;
}
/* 6. Components - UI components */
.card {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* 7. Utilities - Helper classes */
.text-center {
text-align: center;
}
Selectors and Specificity
Good Practices
/* ✅ Good - Low specificity */
.nav-item {
color: blue;
}
.nav-item.active {
color: red;
}
/* ❌ Bad - High specificity */
#header nav ul li a.nav-item.active {
color: red;
}
Using Classes Over IDs
/* ✅ Good - Reusable */
.header-nav {
background: #fff;
}
/* ❌ Bad - Not reusable, high specificity */
#header-nav {
background: #fff;
}
Maintainable Media Queries
Mobile-First Approach
/* Base styles (mobile) */
.card {
padding: 1rem;
}
/* Tablet */
@media (min-width: 768px) {
.card {
padding: 2rem;
}
}
/* Desktop */
@media (min-width: 1024px) {
.card {
padding: 3rem;
}
}
Media Query Mixins (with preprocessors)
// _breakpoints.scss
@mixin tablet {
@media (min-width: 768px) {
@content;
}
}
@mixin desktop {
@media (min-width: 1024px) {
@content;
}
}
// Usage
.element {
width: 100%;
@include tablet {
width: 50%;
}
@include desktop {
width: 33.333%;
}
}
CSS Custom Properties Best Practices
:root {
/* Use semantic names */
--color-primary: #3498db;
--color-text: #333;
/* Use scales */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
/* Component-specific variables */
--header-height: 60px;
--sidebar-width: 250px;
}
/* Scoped variables */
.card {
--card-padding: var(--spacing-md);
padding: var(--card-padding);
}
Performance Optimization
1. Efficient Selectors
/* ✅ Good - Direct and efficient */
.nav-item {
color: blue;
}
/* ❌ Bad - Descendant selector, less efficient */
.nav ul li a {
color: blue;
}
2. Reusable Utility Classes
/* Spacing utilities */
.m-1 { margin: 0.25rem; }
.m-2 { margin: 0.5rem; }
.m-3 { margin: 1rem; }
/* Flex utilities */
.d-flex { display: flex; }
.justify-center { justify-content: center; }
.align-center { align-items: center; }
3. Reducing File Size
/* ✅ Good - Grouping similar selectors */
.btn-primary,
.btn-secondary,
.btn-tertiary {
padding: 1rem 2rem;
border-radius: 4px;
border: none;
}
/* ❌ Bad - Repetitive code */
.btn-primary {
padding: 1rem 2rem;
border-radius: 4px;
border: none;
}
.btn-secondary {
padding: 1rem 2rem;
border-radius: 4px;
border: none;
}
Documentation and Comments
/* ==========================================================================
Component: Card
Description: Reusable card component with variants
========================================================================== */
.card {
/* Base card styles */
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Header section of the card
Always place at the top with padding */
.card__header {
padding: 1.5rem;
border-bottom: 1px solid #eee;
}
/* TODO: Add support for card footer */
Real-World Example: Building a Maintainable Component
/* components/button/button.css */
/* Button Base
========================================================================== */
.button {
/* Structure */
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--button-padding-y, 0.5rem) var(--button-padding-x, 1rem);
/* Typography */
font-size: var(--button-font-size, 1rem);
font-weight: var(--button-font-weight, 500);
line-height: 1.5;
text-decoration: none;
/* Visual */
background-color: var(--button-bg, transparent);
border: var(--button-border, 1px solid transparent);
border-radius: var(--button-radius, 4px);
/* Interactive */
cursor: pointer;
transition: all 0.2s ease;
/* Disabled state */
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
/* Button Variants
========================================================================== */
.button--primary {
--button-bg: var(--color-primary);
--button-border: 1px solid var(--color-primary);
color: white;
&:hover:not(:disabled) {
--button-bg: var(--color-primary-dark);
--button-border-color: var(--color-primary-dark);
}
}
/* Button Sizes
========================================================================== */
.button--small {
--button-padding-y: 0.25rem;
--button-padding-x: 0.5rem;
--button-font-size: 0.875rem;
}
.button--large {
--button-padding-y: 0.75rem;
--button-padding-x: 1.5rem;
--button-font-size: 1.125rem;
}
Common Anti-Patterns to Avoid
- !important Abuse
/* ❌ Bad */
.element {
color: red !important;
}
/* ✅ Good - Use more specific selectors or better architecture */
.text-danger {
color: red;
}
- Deep Nesting
/* ❌ Bad */
.header .nav .nav-item .link {
color: blue;
}
/* ✅ Good */
.nav-link {
color: blue;
}
- Magic Numbers
/* ❌ Bad */
.element {
top: 37px;
}
/* ✅ Good */
.element {
--element-offset: 2.3125rem;
top: var(--element-offset);
}
CSS Code Review Checklist
- Structure
- Is the code organized logically?
- Are components modular and reusable?
- Is the naming consistent?
- Specificity
- Are selectors as simple as possible?
- Is specificity kept low and manageable?
- Are there any unnecessary ID selectors?
- Maintainability
- Is the code DRY (Don’t Repeat Yourself)?
- Are variables used for repeated values?
- Is the code well-documented?
- Performance
- Are selectors efficient?
- Is the file size optimized?
- Are there any unused styles?
What’s Next?
Now that you’re equipped with CSS best practices, you can explore:
- CSS Architectures (SMACSS, OOCSS)
- CSS Modules and CSS-in-JS
- CSS Preprocessors
- Build Tools and Optimization
Remember, writing good CSS is about finding the right balance between maintainability, scalability, and performance. These practices will help you create better stylesheets, but don’t forget to adapt them to your specific needs!
Got questions about CSS best practices? Drop them in the comments below! Happy coding! ✨