Skip to content
css-standards logo

CSS Standards

css-standards

CSS coding standards for Oh My Brand! theme. BEM methodology, custom properties, theme.json integration, responsive design, and accessibility. Use when styling blocks, templates or components.

SKILL.md

Full skill instructions

CSS Standards

CSS coding standards and patterns for the Oh My Brand! WordPress FSE theme.


When to Use

  • Styling block components
  • Writing responsive layouts
  • Defining CSS custom properties
  • Implementing accessible focus states
  • Working with WordPress design tokens

Reference Files

FilePurpose
gallery-block.cssComplete block styling example
theme-json-tokens.cssWordPress design token usage
accessibility.cssFocus, reduced motion, contrast

BEM Naming

BEM (Block, Element, Modifier) naming convention:

.block                    → Component container
.block__element           → Child element
.block--modifier          → Block variation
.block__element--modifier → Element variation

Block Class Prefix

Block TypePrefixExample
Native blockswp-block-theme-oh-my-brand-.wp-block-theme-oh-my-brand-gallery
ACF blockswp-block-acf-.wp-block-acf-gallery

BEM Examples

/​* Block */
.wp-block-theme-oh-my-brand-gallery { }

/​* Elements */
.wp-block-theme-oh-my-brand-gallery__track { }
.wp-block-theme-oh-my-brand-gallery__slide { }
.wp-block-theme-oh-my-brand-gallery__button { }

/​* Block modifiers */
.wp-block-theme-oh-my-brand-gallery--fullwidth { }

/​* Element modifiers */
.wp-block-theme-oh-my-brand-gallery__button--prev { }
.wp-block-theme-oh-my-brand-gallery__slide--active { }

Custom Properties

Define custom properties at the block root:

.wp-block-theme-oh-my-brand-gallery {
    /​* Layout */
    --visible-images: 3;
    --block-gap: 1rem;

    /​* Animation */
    --transition-duration: 300ms;
    --transition-timing: ease-out;

    /​* Colors (use theme tokens) */
    --button-bg: var(--wp--preset--color--primary);
    --button-text: var(--wp--preset--color--base);
}

See gallery-block.css for complete example.


Theme.json Tokens

Use WordPress design tokens from theme.json:

Token TypeCSS Variable Pattern
Colorsvar(--wp--preset--color--{slug})
Spacingvar(--wp--preset--spacing--{size})
Font Familyvar(--wp--preset--font-family--{slug})
Font Sizevar(--wp--preset--font-size--{slug})
Layoutvar(--wp--style--global--content-size)

See theme-json-tokens.css for examples.


Responsive Design

Mobile-first approach using min-width breakpoints:

NameWidthTarget
Mobile< 768pxPhones (base styles)
Tablet≥ 768pxTablets
Desktop≥ 1024pxLaptops
Large≥ 1280pxDesktops

Example

/​* Base (mobile) styles */
.wp-block-theme-oh-my-brand-gallery {
    grid-template-columns: 1fr;
}

/​* Tablet */
@media (min-width: 768px) {
    .wp-block-theme-oh-my-brand-gallery {
        grid-template-columns: repeat(2, 1fr);
    }
}

/​* Desktop */
@media (min-width: 1024px) {
    .wp-block-theme-oh-my-brand-gallery {
        grid-template-columns: repeat(3, 1fr);
    }
}

Accessibility

Focus Styles

.wp-block-theme-oh-my-brand-gallery__button:focus-visible {
    outline: 2px solid var(--wp--preset--color--primary);
    outline-offset: 2px;
}

Reduced Motion

@media (prefers-reduced-motion: reduce) {
    .wp-block-theme-oh-my-brand-gallery__track {
        transition: none;
    }
}

Screen Reader Only

.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;
}

See accessibility.css for complete patterns.

Color Contrast (WCAG 2.1 AA)

Content TypeMinimum Ratio
Normal text4.5:1
Large text (18px+ bold, 24px+)3:1
UI components3:1

Stylelint Rules

This project uses Stylelint for CSS linting. Key rules to follow:

No Empty Blocks

Stylelint disallows empty rule blocks. Never create a rule with only a comment:

/​* ❌ Bad - empty block causes stylelint error */
@media (prefers-reduced-motion: reduce) {
    .my-component {
        /​* No styles needed */
    }
}

/​* ❌ Bad - empty block */
.my-component__element {
}

/​* ✅ Good - omit the rule entirely if no styles needed */
/​* (Simply don't include the rule) */

/​* ✅ Good - if you need the media query, include actual styles */
@media (prefers-reduced-motion: reduce) {
    .my-component {
        transition: none;
        animation: none;
    }
}

No Duplicate Selectors

Stylelint disallows duplicate selectors within a stylesheet. Consolidate all styles for a selector in one place:

/​* ❌ Bad - duplicate selector causes stylelint error */
.my-component__number {
    font-size: 2rem;
    font-weight: 700;
}

.my-component__label {
    font-size: 1rem;
}

.my-component__number {
    order: 0;  /​* This duplicates the selector above! */
}

/​* ✅ Good - all styles consolidated in one selector */
.my-component__number {
    font-size: 2rem;
    font-weight: 700;
    order: 0;
}

.my-component__label {
    font-size: 1rem;
}

Hex Color Length

Use shorthand hex colors when possible:

/​* ❌ Bad - can be shortened */
color: #0066cc;
background: #ffffff;

/​* ✅ Good - use shorthand */
color: #06c;
background: #fff;

Key Principles

  1. If a rule block would be empty (even with just a comment), do not include it
  2. Consolidate all styles for a selector in one place - no duplicate selectors
  3. Use shorthand hex colors when all pairs are identical (e.g., #aabbcc → #abc)

Validation

Always run stylelint after making CSS changes:

pnpm run lint:css

Fix any issues before committing. This ensures consistent code style and catches common errors.


Related Skills


References