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

<AdSense position="middle-4" ad-client="ca-pub-3321253719635439" ad-slot="5828892154" ad-format="fluid" />


- 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

<AdSense position="middle-5" ad-client="ca-pub-3321253719635439" ad-slot="4359897813" ad-format="fluid" />


### 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.