Less Best Practices

作者 mindrally97184105b5da無授權條款269 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫5 週前更新

Less CSS best practices and coding guidelines for maintainable, modular stylesheets

AI 產生的概覽

撰寫可維護、模組化 Less CSS 樣式表的準則。

功能
提供 Less CSS 最佳實務參考,涵蓋檔案組織、變數、mixin、函式、迴圈、guard 與命名空間。也說明了 BEM 命名、巢狀規則、屬性排序與效能建議。產出為指南與程式碼範例,而非產生的檔案。
適用情境
在撰寫或重構 Less 樣式表,並希望維持一致結構與慣例時使用。也適合用於建立模組化樣式表架構或審查 Less 程式碼風格。
執行需求
未包含指令碼或工具,僅為說明性內容。建置其描述的樣式表需要 Less 編譯器。

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;}
// Usageh1 {  .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/skills位於less-best-practices提交9718410

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架