Skip to content

CSS Best Practices: Writing High-Quality Maintainable Styles ​

Good CSS code is more than just "functional." It should be clear, maintainable, efficient, and easy for team collaboration.

Imagine you're building a house. You could randomly stack bricks and eventually build a house, but it might not be stable, beautiful, or easily expandable. Professional architects follow architectural principles and best practices to ensure houses are both beautiful and durable.

The same goes for CSS. This article will integrate what we've learned about methodologies, organization, naming, performance, and debugging to provide you with a complete CSS best practices guide.

Code Organization Principles ​

Use Global Border-Box ​

This is the most basic but important practice:

css
/* ✅ First rule: Use border-box */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Why?
   - border-box makes width calculation more intuitive
   - width: 300px is exactly 300px, no need to calculate padding and border
   - Avoids unexpected layout overflow
*/

Comparison:

css
/* ❌ content-box (default value) */
.box {
  width: 300px;
  padding: 20px;
  border: 5px solid black;
  /* Actual width = 300 + 40 + 10 = 350px */
}

/* ✅ border-box */
.box {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 5px solid black;
  /* Actual width = 300px */
}

Use CSS Variables for Design Systems ​

css
:root {
  /* Color system */
  --color-primary: #3498db;
  --color-primary-dark: #2980b9;
  --color-primary-light: #5dade2;

  --color-text: #333;
  --color-text-light: #666;
  --color-text-muted: #999;

  --color-bg: #ffffff;
  --color-bg-secondary: #f8f9fa;
  --color-bg-tertiary: #e9ecef;

  /* Spacing system - 8px baseline */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-2xl: 48px;

  /* Font system */
  --font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-family-mono: "Courier New", monospace;

  --font-size-xs: 12px;
  --font-size-sm: 14px;
  --font-size-base: 16px;
  --font-size-lg: 18px;
  --font-size-xl: 24px;
  --font-size-2xl: 32px;

  /* Shadow system */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15);

  /* Border radius system */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;
  --radius-full: 9999px;

  /* Transitions */
  --transition-fast: 150ms;
  --transition-base: 250ms;
  --transition-slow: 350ms;
}

Using variables:

css
.button {
  padding: var(--spacing-sm) var(--spacing-lg);
  font-size: var(--font-size-base);
  color: white;
  background-color: var(--color-primary);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: all var(--transition-base);
}

.button:hover {
  background-color: var(--color-primary-dark);
  box-shadow: var(--shadow-md);
}

Mobile-First Responsive Design ​

css
/* ✅ Mobile-first: Start with small screens */
.container {
  padding: var(--spacing-md);
}

/* Tablet and up */
@media (min-width: 768px) {
  .container {
    padding: var(--spacing-lg);
  }
}

/* Desktop and up */
@media (min-width: 1024px) {
  .container {
    padding: var(--spacing-xl);
  }
}

/* ❌ Avoid: Desktop-first (needs more style overrides) */
.container {
  padding: var(--spacing-xl);
}

@media (max-width: 1023px) {
  .container {
    padding: var(--spacing-lg);
  }
}

@media (max-width: 767px) {
  .container {
    padding: var(--spacing-md);
  }
}

Selector Best Practices ​

Keep Selectors Simple ​

css
/* ❌ Avoid: Overly specific selectors */
.header .navigation .menu .item .link {
  color: blue;
}

/* ✅ Good: Use single class name */
.nav-link {
  color: blue;
}

/* ❌ Avoid: ID selectors */
#header {
  background: white;
}

/* ✅ Good: Use class selectors */
.header {
  background: white;
}

Avoid Deep Selector Nesting ​

css
/* ❌ Bad: 4 levels of nesting */
.sidebar {
  .widget {
    .title {
      .icon {
        color: blue;
      }
    }
  }
}

/* ✅ Good: Use BEM */
.sidebar-widget__title-icon {
  color: blue;
}

Use Descendant Selectors Appropriately ​

css
/* ✅ Appropriate: Limit scope */
.article-content p {
  line-height: 1.8;
  margin-bottom: 1em;
}

.article-content img {
  max-width: 100%;
  height: auto;
}

/* ✅ But for reusable components, better use class names */
.article-paragraph {
  line-height: 1.8;
  margin-bottom: 1em;
}

Property Writing Guidelines ​

Group Properties Logically ​

css
.button {
  /* Positioning */
  position: relative;
  z-index: 1;

  /* Box model */
  display: inline-block;
  width: auto;
  padding: 10px 20px;
  margin: 0;
  border: 2px solid transparent;

  /* Typography */
  font-family: var(--font-family-base);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;

  /* Visual effects */
  color: white;
  background-color: var(--color-primary);
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

  /* Interaction */
  cursor: pointer;
  transition: all 0.3s;
}

Recommended order:

  1. Positioning (position, top, right, bottom, left, z-index)
  2. Box model (display, width, height, padding, margin, border)
  3. Typography (font, line-height, text-align, etc.)
  4. Visual effects (color, background, box-shadow, etc.)
  5. Other (cursor, transition, animation, etc.)

Use Shorthand Properties ​

css
/* ❌ Verbose */
.box {
  margin-top: 10px;
  margin-right: 20px;
  margin-bottom: 10px;
  margin-left: 20px;
}

/* ✅ Concise */
.box {
  margin: 10px 20px;
}

/* ❌ Verbose */
.box {
  background-color: white;
  background-image: url("pattern.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

/* ✅ Concise */
.box {
  background: white url("pattern.png") no-repeat center / cover;
}

Avoid Magic Numbers ​

css
/* ❌ Bad: Arbitrary values */
.box {
  margin-top: 13px;
  padding: 17px 23px;
  width: 347px;
}

/* ✅ Good: Use design system values */
.box {
  margin-top: var(--spacing-md);
  padding: var(--spacing-md) var(--spacing-lg);
  width: 100%;
  max-width: 350px; /* Or use variables */
}

Maintainability Practices ​

Use Meaningful Class Names ​

css
/* ❌ Avoid */
.btn {
}
.txt {
}
.red {
}
.mb-20 {
}

/* ✅ Recommended */
.button {
}
.text {
}
.error-message {
} /* Instead of .red */
.section-spacing {
} /* Instead of .mb-20 */

Add Explanatory Comments ​

css
/**
 * Card Component
 *
 * Generic card component for displaying content blocks
 * Supports featured and compact variants
 */
.card {
  background: white;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

/**
 * Featured Card
 * Used for important content like homepage recommendations
 */
.card--featured {
  border: 2px solid var(--color-primary);
  box-shadow: var(--shadow-lg);
}

/* Temporary fix, will be improved after design confirmation */
.card__workaround {
  /* TODO: Improve this implementation */
  position: relative;
  z-index: 10;
}

Avoid !important ​

css
/* ❌ Bad: Overuse of !important */
.button {
  background-color: blue !important;
  color: white !important;
  padding: 10px !important;
}

/* ✅ Good: Increase selector specificity */
.button.button--primary {
  background-color: blue;
  color: white;
}

/* âš ī¸ Acceptable: Utility classes */
.u-hidden {
  display: none !important; /* Ensure it can override other styles */
}

The only reasonable use cases for !important:

  • Utility classes (must override all other styles)
  • Overriding third-party library styles (cannot modify source code)

Performance Best Practices ​

Optimize Selector Performance ​

css
/* ❌ Slow: Universal selector */
* {
  margin: 0;
}

.container * {
  box-sizing: border-box;
}

/* ✅ Fast: Specific selectors or inheritance */
html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

/* ❌ Slow: Attribute selector */
input[type="text"] {
  border: 1px solid #ddd;
}

/* ✅ Fast: Class selector */
.input-text {
  border: 1px solid #ddd;
}

Use High-Performance Animations ​

css
/* ❌ Bad: Triggers layout */
@keyframes slide {
  from {
    left: 0;
  }
  to {
    left: 100px;
  }
}

/* ✅ Good: Only triggers composite */
@keyframes slide {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100px);
  }
}

.animated {
  /* Hint to browser that element will change */
  will-change: transform;
  animation: slide 0.3s ease-out;
}

/* Remove will-change after animation completes */
.animated.done {
  will-change: auto;
}

Reduce Repaints and Reflows ​

css
/* ❌ Bad: Frequently changing layout properties */
.item:hover {
  width: 110%;
  height: 110%;
  margin: -5%;
}

/* ✅ Good: Use transform */
.item {
  transition: transform 0.3s;
}

.item:hover {
  transform: scale(1.1);
}

Responsive Design Practices ​

Use Relative Units ​

css
/* ❌ Not flexible enough */
.container {
  width: 1200px;
  font-size: 16px;
  padding: 20px;
}

/* ✅ More flexible */
.container {
  max-width: 1200px;
  width: 90%; /* Or calc(100% - 40px) */
  font-size: 1rem; /* Relative to root element */
  padding: 5%; /* Relative to parent element */
}

Define Reasonable Breakpoints ​

css
/* ✅ Based on common device sizes */
:root {
  --breakpoint-sm: 576px; /* Phone landscape */
  --breakpoint-md: 768px; /* Tablet portrait */
  --breakpoint-lg: 992px; /* Tablet landscape/Small desktop */
  --breakpoint-xl: 1200px; /* Desktop */
}

/* Usage */
@media (min-width: 768px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

Responsive Image Handling ​

css
/* ✅ Responsive images */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* ✅ Use aspect-ratio to avoid layout shift */
.image-container {
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.image-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Accessibility Practices ​

Ensure Sufficient Contrast ​

css
/* ❌ Insufficient contrast */
.text-muted {
  color: #ccc; /* Too low contrast on white background */
}

/* ✅ WCAG AA compliant */
.text-muted {
  color: #666; /* Contrast at least 4.5:1 */
}

Tools for checking:

Don't Rely on Color Alone ​

css
/* ❌ Bad: Only using color to distinguish */
.status-success {
  color: green;
}

.status-error {
  color: red;
}

/* ✅ Good: Combine with icons or text */
.status-success::before {
  content: "✓ ";
}

.status-error::before {
  content: "✗ ";
}

Ensure Focus Visibility ​

css
/* ❌ Bad: Remove focus styles */
*:focus {
  outline: none;
}

/* ✅ Good: Custom but visible focus styles */
*:focus {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

*:focus:not(:focus-visible) {
  outline: none;
}

*:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

Hide Content but Maintain Accessibility ​

css
/* ❌ Bad: Screen readers can't read either */
.hidden {
  display: none;
}

/* ✅ Good: Visually hidden but screen reader accessible */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

Team Collaboration Practices ​

Establish Style Guide ​

Create a STYLE_GUIDE.md for your project:

markdown
# CSS Style Guide

## Naming Conventions

- Use BEM naming
- Use kebab-case for class names
- Use is- prefix for state classes
- Use js- prefix for JavaScript hooks

## File Organization

- Split files by components
- Use 7-1 pattern for Sass organization
- Each file no more than 300 lines

## Code Style

- Use 2-space indentation
- Group properties logically
- Use lowercase for color values
- Use double quotes for property values

## Example

```css
.button {
  display: inline-block;
  padding: var(--spacing-sm) var(--spacing-lg);
  background-color: var(--color-primary);
}
```

Use Linters and Formatters ​

.stylelintrc.json:

json
{
  "extends": "stylelint-config-standard",
  "rules": {
    "indentation": 2,
    "max-nesting-depth": 3,
    "selector-max-id": 0,
    "color-hex-case": "lower",
    "color-hex-length": "short"
  }
}

.prettierrc:

json
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "useTabs": false
}

Code Review Checklist ​

markdown
## CSS Code Review Checklist

### Naming and Organization

- [ ] Class names follow naming conventions?
- [ ] Used semantic class names?
- [ ] File organization reasonable?

### Performance

- [ ] Avoided excessive nesting?
- [ ] Animations use transform and opacity?
- [ ] Removed unused CSS?

### Maintainability

- [ ] Used CSS variables?
- [ ] Has appropriate comments?
- [ ] Avoided magic numbers?

### Accessibility

- [ ] Color contrast sufficient?
- [ ] Focus styles visible?
- [ ] Considered keyboard navigation?

### Responsive

- [ ] Is mobile-first?
- [ ] Breakpoints reasonable?
- [ ] Images responsive?

Browser Compatibility ​

Use Autoprefixer ​

css
/* Your code */
.button {
  display: flex;
  transition: transform 0.3s;
}

/* Compiled by Autoprefixer */
.button {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-transition: -webkit-transform 0.3s;
  transition: -webkit-transform 0.3s;
  transition: transform 0.3s;
  transition: transform 0.3s, -webkit-transform 0.3s;
}

Use @supports for Feature Detection ​

css
/* Base styles */
.grid {
  display: block;
}

/* Browsers that support Grid */
@supports (display: grid) {
  .grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
  }
}

/* Browsers that don't support Grid (fallback) */
@supports not (display: grid) {
  .grid-item {
    float: left;
    width: 33.33%;
    padding: 10px;
  }
}

Common Anti-Patterns ​

Anti-Pattern 1: Overusing !important ​

css
/* ❌ */
.button {
  color: white !important;
  background: blue !important;
  padding: 10px !important;
}

/* ✅ */
.button {
  color: white;
  background: blue;
  padding: 10px;
}

Anti-Pattern 2: Inline Styles ​

html
<!-- ❌ -->
<div style="color: red; font-size: 20px; margin: 10px;">
  <!-- ✅ -->
  <div class="error-message"></div>
</div>

Anti-Pattern 3: Naming Based on Appearance ​

css
/* ❌ */
.blue-text {
  color: blue;
}
.big-box {
  font-size: 24px;
}

/* ✅ */
.primary-text {
  color: blue;
}
.page-title {
  font-size: 24px;
}

Anti-Pattern 4: Overusing Float Layout ​

css
/* ❌ Still using float for layout in 2023 */
.col {
  float: left;
  width: 33.33%;
}

/* ✅ Use modern layout */
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

Anti-Pattern 5: Fixed Pixel Units ​

css
/* ❌ */
.container {
  width: 1200px;
  font-size: 16px;
}

/* ✅ */
.container {
  max-width: 1200px;
  width: 90%;
  font-size: 1rem;
}

Useful Tools and Resources ​

  • VS Code Extensions:

    • Stylelint
    • Prettier
    • CSS Peek
    • IntelliSense for CSS
  • Online Tools:

Learning Resources ​

Checklist ​

Use this checklist to review your CSS code:

markdown
## CSS Quality Checklist

### Basics

- [ ] Use box-sizing: border-box
- [ ] Defined CSS variable system
- [ ] Use mobile-first responsive design

### Naming and Organization

- [ ] Follow naming conventions (BEM, etc.)
- [ ] File organization reasonable
- [ ] Has appropriate comments

### Performance

- [ ] Selectors concise (<3 levels)
- [ ] Animations use transform/opacity
- [ ] Removed unused CSS

### Maintainability

- [ ] Avoid magic numbers
- [ ] Don't overuse !important
- [ ] Consistent code formatting

### Accessibility

- [ ] Contrast meets standards
- [ ] Focus styles obvious
- [ ] Don't rely on color alone

### Compatibility

- [ ] Use Autoprefixer
- [ ] Key features have fallbacks
- [ ] Tested in target browsers

Summary ​

CSS best practices are not rigid rules, but guiding principles to help you write better code.

Core Principles:

  • Consistency: Follow team-agreed guidelines
  • Maintainability: Make code easy to understand and modify
  • Performance: Write efficient selectors and styles
  • Accessibility: Ensure all users can use it

Key Practices:

  • Use border-box and CSS variables
  • Follow naming conventions
  • Avoid excessive nesting
  • Mobile-first responsive design
  • Use tools for automated checking

Remember:

  • Code is written for humans to read, secondarily for machines to run
  • Good code is self-documenting, reducing comment needs
  • Performance and maintainability are equally important
  • Continuous learning and improvement, no perfect code

CSS best practices are an evolving topic. As new features emerge and best practices evolve, keep learning and updating your knowledge. Most importantly, always focus on user experience and code quality, writing code that satisfies yourself and your team.