Skip to main content
skill CX Codex

less-best-practices — Claude Code skill: what it does, how to install

This skill guides coding assistants on Less architecture, modular project layout, variable scales, and reusable mixins. Keep stylesheet specificity low and maintainable.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add Mindrally/skills --skill less-best-practices -a claude-code
Open on GitHub

What less-best-practices does

The skill instructs the agent to structure stylesheets into dedicated directories: abstracts/, base/, components/, layout/, and pages/. Everything compiles through a unified main.less manifest. It sets explicit variable scales for typography, z-indexes, breakpoints, and an 8px spacing baseline.

Inside are parametric mixins for button states and media query wrappers like .respond-to(). Flexbox shortcuts are included too. Accessibility helpers provide .visually-hidden() and :focus-visible styling. Because these rules use Less-specific variable syntax and mixin syntax, they will not work in vanilla CSS or SCSS projects.

What it helps with

  • organize Less stylesheets into dedicated directory folders and a manifest
  • define consistent scales for spacing, z-index, and responsive breakpoints
  • generate parametric mixins for interactive button states
  • apply accessibility mixins for hidden text and focus indicators

Example prompts for the agent

  • Organize our Less files using the modular directory structure with main.less
  • Write a responsive mixin using @breakpoint-lg for card components
  • Create a parametric button mixin with hover and disabled state handling

How to install less-best-practices

1Skills CLI (Vercel)

npx skills add Mindrally/skills --skill less-best-practices -a claude-code

2Manually: put the files in place

~/.claude/skills/less-best-practices/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/less-best-practices/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about less-best-practices

How to install less-best-practices in Claude Code?

Run npx skills add Mindrally/skills --skill less-best-practices -a claude-code. Alternatively, place the instruction file into ~/.claude/skills/less-best-practices/SKILL.md.

What does less-best-practices do?

It teaches AI agents structured Less architecture, covering modular file splits, semantic variable scales, and reusable mixins.

Which responsive mixins does this skill provide?

It provides .respond-to(), .respond-below(), and .respond-between(), which wrap media queries around variable breakpoints and arbitrary style blocks.

Source text

SKILL.md · Apache-2.0
---
name: less-best-practices
description: Less CSS best practices and coding guidelines for maintainable, modular stylesheets
metadata:
  maintainer: Mindrally
  source: https://github.com/Mindrally/skills
---

# Less CSS Best Practices

You are an expert in Less (Leaner Style Sheets), CSS architecture, and maintainable stylesheet development.

## Key Principles

- Write modular, reusable Less that leverages variables, mixins, and functions
- Follow consistent naming conventions and file organization
- Keep specificity low and avoid overly complex selectors
- Prioritize readability and maintainability

## File Organization

### Project Structure
```
less/
├── abstracts/
│   ├── variables.less      # Global variables
│   ├── mixins.less         # Reusable mixins
│   └── functions.less      # Less functions
├── base/
│   ├── reset.less          # CSS reset/normalize
│   ├── typography.less     # Typography rules
│   └── base.less           # Base element styles
├── components/
│   ├── buttons.less        # Button components
│   ├── cards.less          # Card components
│   └── forms.less          # Form components
├── layout/
│   ├── header.less         # Header layout
│   ├── footer.less         # Footer layout
│   ├── grid.less           # Grid system
│   └── navigation.less     # Navigation layout
├── pages/
│   ├── home.less           # Home page specific
│   └── contact.less        # Contact page specific
├── themes/
│   └── default.less        # Default theme
├── vendors/
│   └── normalize.less      # Third-party styles
└── main.less               # Main manifest file
```

### Main Manifest
```less
// main.less

// Abstracts
@import "abstracts/variables";
@import "abstracts/mixins";
@import "abstracts/functions";

// Vendors
@import "vendors/normalize";

// Base
@import "base/reset";
@import "base/typography";
@import "base/base";

// Layout
@import "layout/grid";
@import "layout/header";
@import "layout/navigation";
@import "layout/footer";

// Components
@import "components/buttons";
@import "components/cards";
@import "components/forms";

// Pages
@import "pages/home";

// Themes
@import "themes/default";
```

## Variables

### Naming Convention
```less
// variables.less

// Colors - use semantic names
@color-primary: #3498db;
@color-primary-light: lighten(@color-primary, 15%);
@color-primary-dark: darken(@color-primary, 15%);
@color-secondary: #2ecc71;
@color-text: #333333;
@color-text-muted: #666666;
@color-background: #ffffff;
@color-border: #e0e0e0;
@color-error: #e74c3c;
@color-success: #27ae60;
@color-warning: #f39c12;
@color-info: #17a2b8;

// Typography
@font-family-base: 'Helvetica Neue', Arial, sans-serif;
@font-family-heading: 'Georgia', serif;
@font-family-mono: 'Consolas', monospace;
@font-size-base: 1rem;
@font-size-small: 0.875rem;
@font-size-large: 1.25rem;
@font-size-h1: 2.5rem;
@font-size-h2: 2rem;
@font-size-h3: 1.75rem;
@font-weight-normal: 400;
@font-weight-medium: 500;
@font-weight-bold: 700;
@line-height-base: 1.5;
@line-height-heading: 1.2;

// Spacing Scale
@spacing-unit: 8px;
@spacing-xs: (@spacing-unit * 0.5);   // 4px
@spacing-sm: @spacing-unit;            // 8px
@spacing-md: (@spacing-unit * 2);      // 16px
@spacing-lg: (@spacing-unit * 3);      // 24px
@spacing-xl: (@spacing-unit * 4);      // 32px
@spacing-xxl: (@spacing-unit * 6);     // 48px

// Breakpoints
@breakpoint-sm: 576px;
@breakpoint-md: 768px;
@breakpoint-lg: 992px;
@breakpoint-xl: 1200px;
@breakpoint-xxl: 1400px;

// Z-index Scale
@z-index-dropdown: 1000;
@z-index-sticky: 1020;
@z-index-fixed: 1030;
@z-index-modal-backdrop: 1040;
@z-index-modal: 1050;
@z-index-popover: 1060;
@z-index-tooltip: 1070;

// Transitions
@transition-base: 0.3s ease;
@transition-fast: 0.15s ease;
@transition-slow: 0.5s ease;

// Border Radius
@border-radius-sm: 2px;
@border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-pill: 50px;
@border-radius-circle: 50%;

// Shadows
@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);

// Container widths
@container-sm: 540px;
@container-md: 720px;
@container-lg: 960px;
@container-xl: 1140px;
```

### Variable Interpolation
```less
// Use interpolation for dynamic property names
@property: margin;
@position: top;

.element {
  @{property}-@{position}: @spacing-md;
}

// Output: margin-top: 16px;
```

## Mixins

### Basic Mixins
```less
// mixins.less

// Clearfix
.clearfix() {
  &::after {
    content: '';
    display: table;
    clear: both;
  }
}

// Flexbox utilities
.flex-center() {
  display: flex;
  align-items: center;
  justify-content: center;
}

.flex-between() {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.flex-column() {
  display: flex;
  flex-direction: column;
}

// Usage
.container {
  .flex-center();
  min-height: 100vh;
}
```

### Parametric Mixins
```less
// Mixins with parameters
.button-variant(@bg-color, @text-color: white) {
  background-color: @bg-color;
  color: @text-color;
  border: none;

  &:hover {
    background-color: darken(@bg-color, 10%);
  }

  &:active {
    background-color: darken(@bg-color, 15%);
  }

  &:disabled {
    background-color: lighten(@bg-color, 20%);
    cursor: not-allowed;
  }
}

// Usage
.btn-primary {
  .button-variant(@color-primary);
}

.btn-secondary {
  .button-variant(@color-secondary);
}

.btn-danger {
  .button-variant(@color-error);
}
```

### Responsive Mixins
```less
// Media query mixins
.respond-to(@breakpoint, @rules) {
  @media (min-width: @breakpoint) {
    @rules();
  }
}

.respond-below(@breakpoint, @rules) {
  @media (max-width: (@breakpoint - 1px)) {
    @rules();
  }
}

.respond-between(@min, @max, @rules) {
  @media (min-width: @min) and (max-width: (@max - 1px)) {
    @rules();
  }
}

// Usage
.element {
  width: 100%;

  .respond-to(@breakpoint-md, {
    width: 50%;
  });

  .respond-to(@breakpoint-lg, {
    width: 33.333%;
  });
}
```

### Typography Mixins
```less
.font-size(@size, @line-height: @line-height-base) {
  font-size: @size;
  line-height: @line-height;
}

.truncate(@lines: 1) when (@lines = 1) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.truncate(@lines) when (@lines > 1) {
  display: -webkit-box;
  -webkit-line-clamp: @lines;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

// Heading styles
.heading(@size) {
  font-family: @font-family-heading;
  font-size: @size;
  font-weight: @font-weight-bold;
  line-height: @line-height-heading;
  margin-bottom: @spacing-md;
}

// Usage
h1 {
  .heading(@font-size-h1);
}

.card-title {
  .truncate(2);
}
```

### Accessibility Mixins
```less
.visually-hidden() {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.focus-visible() {
  &:focus-visible {
    outline: 2px solid @color-primary;
    outline-offset: 2px;
  }
}

// Usage
.sr-only {
  .visually-hidden();
}

.interactive-element {
  .focus-visible();
}
```

## BEM Naming Convention

```less
// Block Element Modifier pattern
.card {
  // Block styles
  background: @color-background;
  border-radius: @border-radius-md;
  box-shadow: @shadow-md;
  overflow: hidden;

  // Element: child of block
  &__header {
    padding: @spacing-md;
    border-bottom: 1px solid @color-border;
  }

  &__title {
    margin: 0;
    font-size: @font-size-large;
    font-weight: @font-weight-bold;
  }

  &__image {
    width: 100%;
    height: auto;
    display: block;
  }

  &__body {
    padding: @spacing-md;
  }

  &__footer {
    padding: @spacing-md;
    border-top: 1px solid @color-border;
    background: lighten(@color-border, 5%);
  }

  // Modifier: variant of block
  &--featured {
    border: 2px solid @color-primary;
  }

  &--horizontal {
    display: flex;

    .card__image {
      width: 200px;
      flex-shrink: 0;
    }
  }

  &--compact {
    .card__header,
    .card__body,
    .card__footer {
      padding: @spacing-sm;
    }
  }
}
```

## Nesting Rules

### Keep Nesting Shallow
```less
// BAD: Too deep nesting
.nav {
  .nav-list {
    .nav-item {
      .nav-link {
        .nav-icon {
          // 5 levels - creates high specificity
        }
      }
    }
  }
}

// GOOD: Flat BEM structure with shallow nesting
.nav {
  display: flex;
  align-items: center;
}

.nav__list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__item {
  margin: 0 @spacing-sm;
}

.nav__link {
  color: @color-text;
  text-decoration: none;
  transition: color @transition-base;

  // Acceptable: state nesting
  &:hover,
  &:focus {
    color: @color-primary;
  }

  // Acceptable: modifier nesting
  &--active {
    color: @color-primary;
    font-weight: @font-weight-bold;
  }
}
```

### Acceptable Nesting Patterns
```less
.component {
  // Pseudo-elements
  &::before,
  &::after {
    content: '';
    position: absolute;
  }

  // State pseudo-classes
  &:hover,
  &:focus,
  &:active {
    // State styles
  }

  // BEM modifiers
  &--variant {
    // Modifier styles
  }

  // Media queries
  .respond-to(@breakpoint-md, {
    // Responsive styles
  });
}
```

## Functions

### Built-in Functions
```less
// Color functions
.element {
  // Lighten/darken
  background: lighten(@color-primary, 20%);
  border-color: darken(@color-primary, 10%);

  // Saturation
  color: saturate(@color-primary, 20%);

  // Mix colors
  background: mix(@color-primary, @color-secondary, 50%);

  // Fade (opacity)
  background: fade(@color-primary, 50%);

  // Color extraction
  @hue: hue(@color-primary);
  @saturation: saturation(@color-primary);
  @lightness: lightness(@color-primary);
}

// Math functions
.element {
  width: percentage(1/3);        // 33.33333%
  height: round(10.5px);         // 11px
  margin: ceil(4.2px);           // 5px
  padding: floor(4.8px);         // 4px
  font-size: abs(-10px);         // 10px
  z-index: min(5, 10, 3);        // 3
  z-index: max(5, 10, 3);        // 10
}

// String functions
@selector: e(".my-class");      // Escape
@path: %("url(%s)", "image.png"); // Format
```

### Custom Functions (Using Mixins)
```less
// Less doesn't have true functions, use mixins with output
.spacing(@multiplier) {
  @result: (@spacing-unit * @multiplier);
}

// Usage with variable scope
.element {
  .spacing(3);
  padding: @result; // 24px
}

// Alternative: use variables directly
.padding(@multiplier) {
  padding: (@spacing-unit * @multiplier);
}

.margin(@multiplier) {
  margin: (@spacing-unit * @multiplier);
}

.element {
  .padding(2);
  .margin(1);
}
```

## Loops

### Generating Classes
```less
// Generate column classes
.generate-columns(@n, @i: 1) when (@i =< @n) {
  .col-@{i} {
    width: percentage(@i / @n);
  }
  .generate-columns(@n, (@i + 1));
}

// Usage: generates .col-1 through .col-12
.generate-columns(12);

// Generate spacing utilities
.generate-spacing(@i: 0) when (@i =< 8) {
  .m-@{i} {
    margin: (@spacing-unit * @i);
  }
  .mt-@{i} {
    margin-top: (@spacing-unit * @i);
  }
  .mb-@{i} {
    margin-bottom: (@spacing-unit * @i);
  }
  .p-@{i} {
    padding: (@spacing-unit * @i);
  }
  .pt-@{i} {
    padding-top: (@spacing-unit * @i);
  }
  .pb-@{i} {
    padding-bottom: (@spacing-unit * @i);
  }
  .generate-spacing((@i + 1));
}

.generate-spacing();
```

### Loop Over Lists
```less
// Define color list
@color-names: primary, secondary, success, danger, warning, info;
@color-values: @color-primary, @color-secondary, @color-success, @color-error, @color-warning, @color-info;

// Generate color utilities
.generate-colors(@names, @values, @i: 1) when (@i =< length(@names)) {
  @name: extract(@names, @i);
  @value: extract(@values, @i);

  .text-@{name} {
    color: @value;
  }
  .bg-@{name} {
    background-color: @value;
  }
  .border-@{name} {
    border-color: @value;
  }

  .generate-colors(@names, @values, (@i + 1));
}

.generate-colors(@color-names, @color-values);
```

## Guards (Conditionals)

```less
// Mixin with guards
.button-size(@size) when (@size = small) {
  padding: @spacing-xs @spacing-sm;
  font-size: @font-size-small;
}

.button-size(@size) when (@size = medium) {
  padding: @spacing-sm @spacing-md;
  font-size: @font-size-base;
}

.button-size(@size) when (@size = large) {
  padding: @spacing-md @spacing-lg;
  font-size: @font-size-large;
}

// Usage
.btn-sm {
  .button-size(small);
}

.btn-md {
  .button-size(medium);
}

.btn-lg {
  .button-size(large);
}

// Guards with comparison operators
.set-color(@lightness) when (@lightness > 50%) {
  color: black;
}

.set-color(@lightness) when (@lightness =< 50%) {
  color: white;
}
```

## Namespacing

```less
// Group related mixins
#utils {
  .clearfix() {
    &::after {
      content: '';
      display: table;
      clear: both;
    }
  }

  .visually-hidden() {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }
}

#buttons {
  .base() {
    display: inline-flex;
    align-items: center;
    border: none;
    cursor: pointer;
    transition: all @transition-base;
  }

  .primary() {
    #buttons.base();
    background: @color-primary;
    color: white;
  }
}

// Usage
.container {
  #utils.clearfix();
}

.btn-primary {
  #buttons.primary();
}
```

## Performance Best Practices

- Avoid deeply nested selectors (max 3 levels)
- Keep specificity low - prefer single class selectors
- Never use `!important` except for utility overrides
- Use mixins for vendor prefixes (or autoprefixer)
- Minimize use of `extend` as it can increase file size
- Compile to compressed CSS in production
- Enable source maps in development only

## Code Style Guidelines

- Use 2 spaces for indentation
- Use single quotes for strings
- Add a space after colons in declarations
- Add a space before opening braces
- Put closing braces on new lines
- Separate rule sets with blank lines
- Comment complex logic
- Order properties consistently

## Property Order

```less
.element {
  // Positioning
  position: relative;
  top: 0;
  right: 0;
  z-index: @z-index-dropdown;

  // Display & Box Model
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: @container-md;
  padding: @spacing-md;
  margin: @spacing-sm auto;

  // Typography
  font-family: @font-family-base;
  font-size: @font-size-base;
  font-weight: @font-weight-normal;
  line-height: @line-height-base;
  color: @color-text;
  text-align: left;

  // Visual
  background-color: @color-background;
  border: 1px solid @color-border;
  border-radius: @border-radius-md;
  box-shadow: @shadow-sm;

  // Animation
  transition: all @transition-base;

  // Misc
  cursor: pointer;
  overflow: hidden;
}
```

© Mindrally · Apache-2.0 · Mindrally/skills

Similar skills

Everything for Frontend and UI →

From the same set214

auth0-authentication A skill that gives your coding agent Auth0 guidelines: auth flows, Actions, token validation and redirect safety. CX Codex +1 700installs esbuild-bundler Teaches agents best practices for esbuild across browser and Node.js environments. Useful when configuring TypeScript, bundles, and dev servers. CX Codex +1 697installs supabase-development Gives the agent a working set of Supabase rules: schema design, RLS policies, auth, realtime subscriptions and Edge Functions. CX Codex +1 699installs monorepo A skill that hands your agent a rulebook for monorepos built on TypeScript, React, Next.js and Expo with Turbo. Useful when several apps and shared packages live in one repo. CX Codex +1 694installs llamaindex-development Guides coding assistants in building Python RAG applications with LlamaIndex. Helps generate document parsers, vector indexes, and query engines. CX Codex +1 691installs meta-prompt A skill with meta-prompting templates that critique model responses, walk through a solution path and give it a score. Handy when you need to check answer quality. CX Codex +1 691installs cloudflare-development A skill that hands your agent Cloudflare edge practices: Workers, Pages, KV, D1, R2 and Durable Objects. Useful when the agent writes worker code or edits wrangler.toml. CX Codex +1 689installs remix A skill that turns your coding agent into a Remix and TypeScript helper, with ready patterns for data loading, mutations and nested routes. CX Codex +1 686installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor