CSS3 Coding Standards#
Reference#
CSS3 Coding Standards are based on Airbnb CSS/SASS Styleguide.
Google Style Guides: https://google.github.io/styleguide/
MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/CSS
File Organization#
public/
├── styles/ # Global shared styles
│ ├── variables.css # Shared variables
│ ├── typography.css # Typography rules
│ ├── colors.css # Color definitions
│ └── utilities.css # Shared utilities
│
├── apps/
│ ├── app1/
│ │ ├── components/
│ │ │ └── Button/
│ │ │ ├── Button.tsx
│ │ │ └── Button.module.css
│ │ └── styles/ # App-specific global styles
│ │ └── theme-dark.css
│ │ └── theme-light.css
│ └── app2/
│ └── [similar structure]
Component Style Organization#
Component-Specific CSS - Keep component styles in the same folder as the component - Use the same name as the component - Import styles directly in the component file
// Button/Button.tsx
import './Button.css';
const Button = ({ variant = 'primary' }) => (
<button className={`button button--${variant}`}>
Click me
</button>
);
Global Styles - Use the shared
/public/stylesfor cross-app styles - Keep app-specific global styles inapps/<app-name>/src/styles- Import global styles in the app’s entry pointStyle Hierarchy - Shared variables and utilities (highest level) - App-specific global styles - Component-specific styles (most specific)
Best Practices#
CSS Organization - Keep component styles scoped and specific - Avoid deep nesting
/* Button/Button.css */
.button {
/* Base styles */
}
.button--primary {
/* Primary variant */
}
.button--secondary {
/* Secondary variant */
}
Global Styles - Define shared variables in public/styles - Use CSS custom properties for theming - Keep global styles minimal
/* public/styles/variables.css */
:root {
--color-primary: #007bff;
--font-size-base: 1rem;
}
Importing Styles - Import global styles once at app entry - Import component styles in component files - Maintain consistent import order
// apps/app1/src/index.tsx
import '../../../styles/variables.css';
import '../../../styles/typography.css';
import './styles/theme.css';
Naming Conventions#
File Names#
Component CSS Modules - Match exactly the component name - Use
.module.cssextension - Use PascalCase to match component
Component File: Button.tsx
CSS Module File: Button.module.css
Component File: UserProfile.tsx
CSS Module File: UserProfile.module.css
Global CSS Files - Use lowercase - Use hyphens for spaces - Descriptive and purpose-based names
public/styles/
├── variables.css
├── typography.css
├── color-tokens.css
└── utility-classes.css
apps/app1/src/styles/
├── theme-dark.css
├── theme-light.css
└── app-utilities.css
Class Names#
All CSS Classes - Use lowercase with hyphens (kebab-case) - Be specific and descriptive - Follow same convention for both modules and global styles
/* ❌ Bad */
.buttonPrimary {}
.btn_wrapper {}
.HEADER {}
.userCard {}
.marginTop20 {}
.flex_container {}
/* ✅ Good */
.button {}
.button-primary {}
.button-wrapper {}
.user-card {}
.margin-top-lg {}
.container-flex {}
State Classes - Use lowercase with hyphens - Prefix with ‘is-’ or ‘has-’ - Keep consistent across all styles
/* ❌ Bad */
.active {}
.isHidden {}
.has_error {}
/* ✅ Good */
.is-active {}
.is-hidden {}
.has-error {}
Utility Classes - Use lowercase with hyphens - Start with property or purpose - Use size modifiers consistently
/* ❌ Bad */
.marginLg {}
.p2 {}
.flex {}
/* ✅ Good */
.margin-lg {}
.padding-sm {}
.display-flex {}
Naming Best Practices#
Consistency - Use kebab-case for all class names - Follow naming pattern consistently across all files - Use same conventions in both modules and global styles
Clarity - Names should clearly indicate purpose - Avoid abbreviations unless widely understood - Use full, descriptive names
Modularity - Keep names scoped to their purpose - Avoid overly generic names - Use prefixes for related groups of styles
/* ❌ Bad - Too generic */
.title {}
.container {}
.wrapper {}
/* ✅ Good - Scoped and specific */
.user-profile-title {}
.card-container {}
.form-field-wrapper {}
Styling Approach#
Core Principles#
Component-First - Each component owns its styles via CSS Modules - Styles live alongside their components - Component styles should be self-contained
Global Styles - Minimal global styles - Focus on design tokens and utilities - Shared across all applications
Cascading Order - Design tokens (variables) - Global styles - Component styles - Utility classes (overrides)
Implementation Strategy#
Design Tokens - Define in global variables.css - Use CSS custom properties - Include colors, spacing, typography
/* public/styles/variables.css */
:root {
/* Colors */
--color-primary: #007bff;
--color-secondary: #6c757d;
/* Spacing */
--spacing-unit: 0.25rem;
--spacing-sm: calc(var(--spacing-unit) * 2);
--spacing-md: calc(var(--spacing-unit) * 4);
/* Typography */
--font-family-base: system-ui, sans-serif;
--font-size-base: 1rem;
}
Component Styles - Use CSS Modules for encapsulation - Import global variables - Keep styles focused and specific
// UserCard/UserCard.tsx
import styles from './UserCard.module.css';
const UserCard = ({ user }) => (
<div className={styles.card}>
<h2 className={styles.title}>{user.name}</h2>
<p className={styles.description}>{user.bio}</p>
</div>
);
/* UserCard/UserCard.module.css */
.card {
padding: var(--spacing-md);
border-radius: var(--border-radius);
background: var(--color-background);
}
.title {
font-size: var(--font-size-lg);
color: var(--color-text-primary);
}
Global Utilities - Create focused utility classes - Use for common patterns - Keep utilities minimal
/* public/styles/utility-classes.css */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.text-center {
text-align: center;
}
Responsive Design#
Mobile-First Approach - Start with mobile styles - Add complexity for larger screens - Use consistent breakpoints
/* public/styles/variables.css */
:root {
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
}
/* Component.module.css */
.container {
padding: var(--spacing-sm);
@media (min-width: 768px) {
padding: var(--spacing-md);
}
}
Responsive Utilities - Create responsive utility classes - Use consistent naming patterns - Keep responsive overrides minimal
/* public/styles/utility-classes.css */
@media (min-width: 768px) {
.md\:hidden {
display: none;
}
.md\:block {
display: block;
}
}
Theme Management#
Theme Variables - Define themes using CSS custom properties - Allow easy theme switching - Keep theme definitions separate
/* apps/app1/styles/theme-light.css */
:root {
--color-background: #ffffff;
--color-text: #1a1a1a;
}
/* apps/app1/styles/theme-dark.css */
:root {
--color-background: #1a1a1a;
--color-text: #ffffff;
}
Theme Implementation - Use semantic variable names - Apply themes consistently - Support system preferences
/* Component.module.css */
.container {
background: var(--color-background);
color: var(--color-text);
}
Performance Considerations#
CSS Loading - Load global styles first - Use code splitting for themes - Minimize CSS bundle size
Selector Performance - Keep selectors simple - Avoid deep nesting - Use class selectors primarily
/* ❌ Bad - Complex selector */
.card > div > span.text {
color: var(--color-text);
}
/* ✅ Good - Simple selector */
.cardText {
color: var(--color-text);
}
Animation Performance - Use transform and opacity for animations - Avoid layout-triggering properties - Consider reduced motion preferences
.animatedElement {
transition: transform 0.3s ease;
@media (prefers-reduced-motion: reduce) {
transition: none;
}
}
Best Practices#
CSS Module Usage#
Scoping - Keep styles specific to the component - Avoid global styles in modules - Use composition for shared styles
/* ❌ Bad - Too generic */
.container { }
.title { }
/* ✅ Good - Component-specific */
.user-profile-container { }
.user-profile-title { }
Class Names - Use meaningful, descriptive names - Follow kebab-case convention - Avoid abbreviations
/* ❌ Bad */
.cnt { }
.usr-box { }
.userBox { }
/* ✅ Good */
.container { }
.user-box { }
Component Styling#
Single Responsibility - Each component should own its styles - Avoid styles that affect multiple components - Use composition for shared styles
/* ❌ Bad - Styles affecting multiple components */
.card {
/* styles that might affect other cards */
}
/* ✅ Good - Component-specific styles */
.user-card {
/* styles specific to UserCard component */
}
Props and Variants - Use props to control variants - Keep variant styles in the module - Use meaningful variant names
// ✅ Good - Component with variants
const Button = ({ variant, size }) => (
<button className={`${styles.button} ${styles[variant]} ${styles[size]}`}>
Click me
</button>
);
Global Styles#
CSS Custom Properties - Define tokens at root level - Use semantic names - Group related variables
/* ✅ Good - Semantic variable names */
:root {
--color-primary: #007bff;
--color-primary-hover: #0056b3;
--spacing-unit: 8px;
--spacing-large: calc(var(--spacing-unit) * 2);
}
Utility Classes - Keep utilities focused and single-purpose - Use consistent naming patterns - Document usage
/* ✅ Good - Single-purpose utilities */
.margin-top-md { margin-top: var(--spacing-md); }
.text-center { text-align: center; }
.display-flex { display: flex; }
Responsive Design#
Mobile First - Start with mobile styles - Use min-width media queries - Follow standard breakpoints
.component {
/* Mobile styles by default */
padding: var(--spacing-sm);
/* Tablet and up */
@media (min-width: 768px) {
padding: var(--spacing-md);
}
}
Breakpoint Usage - Use variables for breakpoints - Keep media queries with related styles - Avoid device-specific breakpoints
Performance#
Selector Efficiency - Use class selectors - Avoid deep nesting - Minimize specificity conflicts
/* ❌ Bad - Deep nesting and high specificity */
.container .wrapper div.content span { }
/* ✅ Good - Flat structure */
.content-text { }
Animation Performance - Use transform and opacity - Avoid layout-triggering properties - Consider reduced motion
/* ✅ Good - Performance optimized animation */
.fade-in {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
Maintainability#
Code Organization - Group related styles - Use consistent ordering - Add comments for complex styles
/* ✅ Good - Organized styles */
.component {
/* Layout */
display: flex;
padding: var(--spacing-md);
/* Typography */
font-size: var(--font-size-md);
line-height: 1.5;
/* Theme */
background: var(--color-background);
color: var(--color-text);
}
Documentation - Document complex selectors - Explain non-obvious solutions - Include usage examples
/**
* Component container
* 1. Uses CSS Grid for responsive layout
* 2. Maintains aspect ratio on resize
* 3. Handles overflow content
*/
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--spacing-md);
}
File Size - Keep files under 300 lines - Split large components - Use composition
Accessibility#
Color Contrast - Meet WCAG guidelines - Test with color contrast tools - Provide sufficient contrast ratios
Focus States - Always visible focus indicators - Consistent focus styles - Support keyboard navigation
/* ✅ Good - Clear focus states */
.button:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
Motion - Respect reduced motion preferences - Provide alternatives to animations - Keep animations subtle
@media (prefers-reduced-motion: reduce) {
.animate {
animation: none;
transition: none;
}
}
Theming#
Theme Structure#
Base Variables - Define in global variables.css - Use semantic naming - Include fallback values
/* public/styles/variables.css */
:root {
/* Colors */
--color-primary: #007bff;
--color-secondary: #6c757d;
--color-success: #28a745;
--color-error: #dc3545;
/* Semantic Colors */
--color-text-primary: var(--color-gray-900);
--color-text-secondary: var(--color-gray-700);
--color-background: var(--color-white);
--color-border: var(--color-gray-200);
/* Typography */
--font-family-base: system-ui, sans-serif;
--font-size-base: 1rem;
--line-height-base: 1.5;
/* Spacing */
--spacing-unit: 0.25rem;
--spacing-sm: calc(var(--spacing-unit) * 2);
--spacing-md: calc(var(--spacing-unit) * 4);
--spacing-lg: calc(var(--spacing-unit) * 6);
/* Border Radius */
--border-radius-sm: 0.25rem;
--border-radius-md: 0.5rem;
--border-radius-lg: 1rem;
}
Theme Implementation#
Theme Files - Separate theme definitions - Override base variables - Keep themes modular
/* apps/app1/styles/theme-light.css */
:root {
/* Background Colors */
--color-background-primary: var(--color-white);
--color-background-secondary: var(--color-gray-100);
--color-background-tertiary: var(--color-gray-200);
/* Text Colors */
--color-text-primary: var(--color-gray-900);
--color-text-secondary: var(--color-gray-700);
--color-text-tertiary: var(--color-gray-500);
/* Border Colors */
--color-border-primary: var(--color-gray-200);
--color-border-secondary: var(--color-gray-300);
/* Interactive Colors */
--color-hover: rgba(0, 0, 0, 0.05);
--color-active: rgba(0, 0, 0, 0.1);
--color-focus-ring: rgba(0, 123, 255, 0.25);
}
/* apps/app1/styles/theme-dark.css */
:root {
/* Background Colors */
--color-background-primary: var(--color-gray-900);
--color-background-secondary: var(--color-gray-800);
--color-background-tertiary: var(--color-gray-700);
/* Text Colors */
--color-text-primary: var(--color-gray-100);
--color-text-secondary: var(--color-gray-300);
--color-text-tertiary: var(--color-gray-500);
/* Border Colors */
--color-border-primary: var(--color-gray-700);
--color-border-secondary: var(--color-gray-600);
/* Interactive Colors */
--color-hover: rgba(255, 255, 255, 0.05);
--color-active: rgba(255, 255, 255, 0.1);
--color-focus-ring: rgba(0, 123, 255, 0.25);
}
Theme Switching#
System Preference - Support prefers-color-scheme - Provide manual override - Use data attributes for theme switching
/* Auto dark mode */
@media (prefers-color-scheme: dark) {
:root {
/* Dark theme variables */
}
}
/* Manual theme switching */
[data-theme="dark"] {
/* Dark theme variables */
}
[data-theme="light"] {
/* Light theme variables */
}
Theme Application - Use semantic variable names - Apply consistently across components - Avoid hard-coded values
/* ❌ Bad - Hard-coded colors */
.button {
background-color: #007bff;
color: white;
}
/* ✅ Good - Theme variables */
.button {
background-color: var(--color-primary);
color: var(--color-text-on-primary);
}
Component Theming#
Theme-Aware Components - Use CSS custom properties - Support theme overrides - Maintain accessibility
.card {
/* Base styles using theme variables */
background-color: var(--color-background-primary);
color: var(--color-text-primary);
border: 1px solid var(--color-border-primary);
/* Component-specific theme variables */
--card-padding: var(--spacing-md);
--card-border-radius: var(--border-radius-md);
padding: var(--card-padding);
border-radius: var(--card-border-radius);
}
Theme Variants - Use modifiers for variants - Maintain theme consistency - Support dark/light modes
.card-elevated {
background-color: var(--color-background-primary);
box-shadow: var(--shadow-md);
}
.card-outlined {
background-color: transparent;
border: 2px solid var(--color-border-primary);
}
Best Practices#
Variable Organization - Group related variables - Use consistent naming patterns - Document variable purposes
Accessibility - Maintain sufficient contrast ratios - Test themes with screen readers - Support high contrast modes
@media (forced-colors: active) {
.button {
border: 1px solid ButtonText;
}
}
Performance - Minimize theme-switching flicker - Use efficient selectors - Consider initial load performance
Maintainability - Keep theme definitions DRY - Document theme structure - Use consistent variable naming
Linting and Formatting#
Formatting Rules#
Indentation and Spacing - Use soft tabs (2 spaces) for indentation - One space before the opening brace - One space after each colon - No space before semicolons - One selector per line - One blank line between rules - No trailing whitespace
/* ❌ Bad */
.avatar{
border-radius:50%;
border:2px solid white;}
.example , .example2{padding:10px;}
/* ✅ Good */
.avatar {
border-radius: 50%;
border: 2px solid white;
}
.example,
.example2 {
padding: 10px;
}
Selectors - Prefer classes over IDs - Use kebab-case naming - Avoid deep nesting - Keep selectors concise
/* ❌ Bad */
#header .navigation div.menu-item span { }
.userProfile { }
.user_avatar { }
/* ✅ Good */
.header-nav-item { }
.user-profile { }
.user-avatar { }
Properties - Group related properties - Use shorthand when possible - Include leading zero - Use lowercase colors - Use hex or rgb(a)
/* ❌ Bad */
.element {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;
color: #FFFFFF;
border-color: rgb(0,0,0);
opacity: .5;
}
/* ✅ Good */
.element {
margin: 10px 20px;
color: #fff;
border-color: rgb(0, 0, 0);
opacity: 0.5;
}
Property Order#
Follow a consistent property order:
Positioning
Box Model
Typography
Visual
Animation
Misc
.element {
/* Positioning */
position: absolute;
top: 0;
right: 0;
z-index: 10;
/* Box Model */
display: block;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
/* Typography */
font-family: sans-serif;
font-size: 16px;
line-height: 1.4;
text-align: center;
/* Visual */
background-color: #fff;
border: 1px solid #ccc;
border-radius: 3px;
/* Animation */
transition: all 0.3s;
/* Misc */
cursor: pointer;
}
Linting Configuration#
Stylelint Rules - Use stylelint for consistent formatting - Extend recommended configs - Customize for project needs
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": 2,
"string-quotes": "single",
"no-duplicate-selectors": true,
"color-hex-case": "lower",
"color-hex-length": "short",
"selector-combinator-space-after": "always",
"declaration-block-trailing-semicolon": "always",
"declaration-colon-space-before": "never",
"declaration-colon-space-after": "always",
"property-no-vendor-prefix": true,
"value-no-vendor-prefix": true,
"number-leading-zero": "always",
"function-url-quotes": "always"
}
}
Editor Configuration - Use .editorconfig for basic formatting - Configure IDE/editor settings - Share configurations with team
# .editorconfig
root = true
[*.css]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
Comments#
Section Comments - Use consistent formatting - Describe section purpose - Add visual separation
Component Comments - Document component purpose - Note dependencies - Explain complex solutions