less_quick_guide
LESS - Quick Guide
Section titled “LESS - Quick Guide”LESS - Overview
Section titled “LESS - Overview”LESS (Leaner Style Sheets) is a mature and powerful CSS pre-processor. It extends CSS with dynamic behavior such as variables, mixins, operations, and functions. This allows you to write more maintainable, themable, and reusable CSS. LESS code is compiled into standard CSS that web browsers can understand. It’s designed to be as CSS-like as possible, making the learning curve gentle for those familiar with CSS.
A CSS Preprocessor is a scripting language that extends the capabilities of standard CSS. It provides features not natively available in CSS, which are then processed and compiled into regular CSS syntax. This enables developers to write more organized, efficient, and dynamic stylesheets.
Why LESS?
Section titled “Why LESS?”LESS offers several advantages for modern web development:
- Maintainability: Variables and mixins reduce repetition and make global changes easier. Update a color or font in one place, and it propagates throughout your stylesheet.
- Reusability: Mixins allow you to encapsulate and reuse groups of CSS declarations, promoting DRY (Don’t Repeat Yourself) principles.
- Organization: Nesting rules mirror HTML structure, making stylesheets more readable and organized. Importing partial files helps in modularizing your CSS.
- Dynamic Capabilities: Operations, functions, and control flow structures (guards, loops) allow for complex calculations and conditional styling.
- Efficiency: Write less code that compiles to standard CSS, potentially speeding up development time.
History
Section titled “History”LESS was originally designed by Alexis Sellier in 2009 and written in Ruby. Later, it was ported to JavaScript, which significantly increased its adoption, allowing for client-side compilation (for development) and integration with Node.js-based build tools. LESS is an open-source project and has been a stable and reliable preprocessor for many years.
Features
Section titled “Features”- Variables: Define reusable values for colors, fonts, dimensions, etc. (e.g.,
@primary-color: #3498db;). - Mixins: Include a bundle of properties from one ruleset into another. Parametric mixins accept arguments for greater flexibility.
- Nesting: Nest CSS rules within each other, mirroring HTML structure for cleaner code.
- Operations: Perform arithmetic operations (
+,-,*,/) on numeric values and colors. - Functions: Built-in functions for color manipulation, math, strings, and type checking.
- Imports: Split your LESS code into multiple files and import them.
- Extend: Share CSS properties between selectors without duplicating code, resulting in more efficient CSS.
- Guards: Implement conditional logic for mixins and CSS rules based on expressions.
- Loops: Create repetitive CSS patterns using recursive mixins and guards.
Advantages
Section titled “Advantages”- Generates browser-compatible CSS.
- Enhances code organization and readability through nesting and imports.
- Speeds up maintenance with variables and mixins.
- Allows for powerful abstractions and code reuse.
- Simplifies complex CSS tasks with operations and functions.
Disadvantages
Section titled “Disadvantages”- Compilation Step: Requires a compilation step to convert LESS to CSS, adding a layer to the development workflow (though modern tools automate this).
- Learning Curve: While syntax is CSS-like, understanding preprocessor concepts (variables, mixins, scope) takes some initial effort.
- Debugging: Debugging can sometimes be trickier as errors might originate in LESS code but manifest in compiled CSS (source maps greatly help with this).
- Over-Abstraction: It’s possible to over-complicate stylesheets if features like deep nesting or complex mixins are misused.
LESS - Installation
Section titled “LESS - Installation”To use LESS, you need to compile your .less files into standard .css files. The most common way to do this is using the LESS compiler, which runs on Node.js.
System Requirements for LESS
Section titled “System Requirements for LESS”- Node.js and npm: LESS is a Node.js package. You’ll need Node.js (which includes npm, the Node Package Manager) installed on your system. Download it from nodejs.org (LTS version recommended for most users).
- Browser Support (for compiled CSS): The CSS generated by LESS is standard CSS and works across all modern browsers (Chrome, Firefox, Safari, Edge, etc.).
Installation of LESS Compiler (lessc)
Section titled “Installation of LESS Compiler (lessc)”You can install the LESS compiler (lessc) globally or as a project dependency.
Step 1: Install Node.js and npm
If you haven’t already, download and install Node.js from nodejs.org. This will also install npm.
Step 2: Install LESS
Open your terminal or command prompt and choose one of the following methods:
Global Installation (Recommended for command-line use anywhere):
npm install -g lessThis makes the lessc command available globally on your system.
Local Installation (Recommended for specific projects and build tool integration):
Navigate to your project directory in the terminal and run:
npm install --save-dev lessThis installs LESS as a development dependency for your project and allows you to use it with build scripts (e.g., in package.json scripts or with tools like Webpack or Gulp).
Step 3: Verify Installation
After installation, you can verify it by checking the version (if installed globally):
lessc -vThis should output the installed LESS compiler version.
Example: Compiling a LESS file
Section titled “Example: Compiling a LESS file”Let’s create a simple LESS example.
1. Create an HTML file (e.g., index.html):
index.html
Section titled “index.html”<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LESS Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <h1>Welcome to LESS</h1> <p>This is styled with LESS!</p></body></html>2. Create a LESS file (e.g., style.less):
style.less
Section titled “style.less”@primary-color: #3498db;@secondary-color: #2ecc71;@text-color: #333;
body { font-family: Arial, sans-serif; color: @text-color;}
h1 { color: @primary-color;}
p { color: @secondary-color; font-size: 1.1em;}3. Compile the LESS file:
Open your terminal, navigate to the directory where you saved these files, and run:
lessc style.less style.cssThis command tells the LESS compiler to take style.less as input and output the compiled CSS to style.css.
4. Check the compiled CSS (style.css):
The generated style.css file will look like this:
style.css
Section titled “style.css”body { font-family: Arial, sans-serif; color: #333333;}
h1 { color: #3498db;}
p { color: #2ecc71; font-size: 1.1em;}Output
Section titled “Output”Open index.html in your web browser. You will see the heading and paragraph styled according to the rules defined in your LESS file and compiled into style.css.
In real-world projects, LESS compilation is often integrated into automated build processes using tools like Webpack (with less-loader), Parcel, Gulp (with gulp-less), or npm scripts.
LESS - Nested Rules
Section titled “LESS - Nested Rules”Description
Section titled “Description”Nesting in LESS allows you to write CSS selectors in a hierarchical way that mirrors the structure of your HTML. This makes your stylesheets more organized, readable, and easier to maintain by grouping related styles together.
Instead of writing repetitive parent selectors, you can nest child selectors inside their parent rule.
Example
Section titled “Example”Consider the following HTML structure:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Nested Rules Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <nav class="main-nav"> <ul> <li><a href="#home">Home</a></li> <li><a href="#about">About</a></li> <li class="active"><a href="#services">Services</a></li> </ul> </nav> <article class="content"> <header> <h1>Main Title</h1> </header> <p>Some introductory text.</p> </article></body></html>Now, let’s write the corresponding LESS in style.less:
style.less
Section titled “style.less”@link-color: #007bff;@active-color: #ff4500;
.main-nav { background-color: #f0f0f0; padding: 10px;
ul { list-style-type: none; margin: 0; padding: 0;
li { display: inline-block; margin-right: 15px;
a { text-decoration: none; color: @link-color;
&:hover { text-decoration: underline; } }
// Using the parent selector '&' to apply styles to a modified parent &.active a { color: @active-color; font-weight: bold; } } }}
.content { padding: 20px;
header { border-bottom: 1px solid #ccc; margin-bottom: 15px;
h1 { color: #333; font-size: 2em; } }
p { font-size: 1em; line-height: 1.6; }}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.main-nav { background-color: #f0f0f0; padding: 10px;}.main-nav ul { list-style-type: none; margin: 0; padding: 0;}.main-nav ul li { display: inline-block; margin-right: 15px;}.main-nav ul li a { text-decoration: none; color: #007bff;}.main-nav ul li a:hover { text-decoration: underline;}.main-nav ul li.active a { color: #ff4500; font-weight: bold;}.content { padding: 20px;}.content header { border-bottom: 1px solid #ccc; margin-bottom: 15px;}.content header h1 { color: #333; font-size: 2em;}.content p { font-size: 1em; line-height: 1.6;}The Parent Selector &
Section titled “The Parent Selector &”In nested rules, the ampersand (&) character is a special selector that references the current parent selector. It’s commonly used for:
- Applying pseudo-classes (e.g.,
&:hover,&:focus). - Applying modifier classes to the parent (e.g.,
&.active,&--modifierin BEM methodology). - Prepending selectors (e.g.,
body.dark-theme & { ... }).
Nesting greatly improves the structure of your LESS files, making them easier to read and maintain by visually grouping related styles.
Output
Section titled “Output”Open the HTML file in a browser. The navigation and content sections will be styled according to the nested rules, demonstrating how LESS organizes styles in a way that reflects the HTML hierarchy.
LESS - Nested Directives and Bubbling
Section titled “LESS - Nested Directives and Bubbling”Description
Section titled “Description”LESS allows you to nest CSS at-rules (directives) like @media or @supports within selectors. When LESS compiles these nested directives, it employs a process called “bubbling.” This means the nested directive is moved to the top level of the CSS output, outside its parent selector, but the selectors inside the directive are correctly combined with the parent selector.
This feature is particularly useful for writing responsive styles or feature queries in a more organized and context-aware manner, keeping styles for a component, including its responsive variations, grouped together.
Example
Section titled “Example”Let’s demonstrate nested @media queries.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Nested Directives Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="widget"> <h2>Widget Title</h2> <p>This is some content within the widget.</p> </div></body></html>LESS (style.less):
style.less
Section titled “style.less”.widget { width: 90%; margin: 20px auto; padding: 15px; background-color: #f0f0f0; border: 1px solid #ccc;
h2 { color: #333; margin-top: 0; }
p { color: #555; }
// Nested @media query @media (min-width: 768px) { width: 600px; // Widget width on larger screens padding: 25px;
h2 { font-size: 1.8em; } }
// Another nested @media query for a different condition @media (max-width: 480px) { p { font-size: 0.9em; } // Nested @supports within @media @supports (display: grid) { background-color: #e0e0e0; // Different background if grid is supported on small screens } }}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will show how the directives have bubbled up:
style.css
Section titled “style.css”.widget { width: 90%; margin: 20px auto; padding: 15px; background-color: #f0f0f0; border: 1px solid #ccc;}.widget h2 { color: #333; margin-top: 0;}.widget p { color: #555;}
@media (min-width: 768px) { .widget { width: 600px; padding: 25px; } .widget h2 { font-size: 1.8em; }}
@media (max-width: 480px) { .widget p { font-size: 0.9em; } @supports (display: grid) { .widget { background-color: #e0e0e0; } }}Key points about bubbling:
Section titled “Key points about bubbling:”- Nested directives (
@media,@supports, etc.) are moved to the top level in the compiled CSS. - The selectors within the bubbled directive are correctly prefixed with their parent context (e.g.,
.widgetin the example). - This keeps component-specific responsive styles or feature queries co-located with the base styles for that component in the LESS file, improving organization.
- Multiple nested directives, or directives nested within each other (like
@supportsinside@media), also bubble correctly.
Output
Section titled “Output”When you view index.html in a browser and resize the window:
- On screens wider than 768px, the widget will be 600px wide, have more padding, and its
h2will be larger. - On screens narrower than 480px, the widget’s paragraph text will be smaller. If the browser supports CSS Grid, the widget’s background will also change on these small screens.
This demonstrates how bubbling helps manage complex conditional styling in a structured way.
LESS - Operations
Section titled “LESS - Operations”Description
Section titled “Description”LESS allows you to perform arithmetic operations (+, -, *, /) directly within your stylesheets. These operations can be applied to numbers, dimensions (values with units like px, em, %), and even colors.
Operations are a powerful feature for creating dynamic relationships between style values, making your CSS more flexible and maintainable.
Unit Handling:
- LESS attempts to infer the output unit. For example,
10px + 5pxresults in15px. - Operations between different compatible units (e.g.,
2in + 5cm) will convert to the unit of the first operand. - Multiplying or dividing a dimension by a unitless number scales the dimension (e.g.,
10px * 2results in20px). - Dividing a dimension by another dimension results in a unitless number (e.g.,
10px / 2pxresults in5). - You can control unit conversion and math strictness with LESS options (
strictUnitsandstrictMath).
Order of Operations:
Multiplication (*) and division (/) have higher precedence than addition (+) and subtraction (-). Parentheses () can be used to explicitly control the order of evaluation, just like in standard mathematics.
Example
Section titled “Example”Let’s illustrate operations with an example.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LESS Operations Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="container"> <header class="main-header">Header</header> <article class="content-area">Content</article> <aside class="sidebar">Sidebar</aside> </div></body></html>LESS (style.less):
style.less
Section titled “style.less”@base-font-size: 16px;@base-spacing: 20px;@primary-color: #3498db; // A blue color
.container { width: 80%; max-width: 1000px; margin: @base-spacing auto; font-size: @base-font-size;}
.main-header { padding: @base-spacing / 2; // 10px background-color: @primary-color; color: white; font-size: @base-font-size * 1.5; // 24px border-bottom: (@primary-color - #222) 3px solid; // Darker border color}
.content-area { width: (100% / 3) * 2; // Roughly 66.6666% float: left; padding: @base-spacing; background-color: #f9f9f9;}
.sidebar { width: (100% / 3) - @base-spacing; // Roughly 33.3333% minus spacing for a gap float: right; padding: @base-spacing; background-color: #eee; // Operations with colors color: @primary-color + #333; // Lightens the blue slightly}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css would be:
style.css
Section titled “style.css”.container { width: 80%; max-width: 1000px; margin: 20px auto; font-size: 16px;}
.main-header { padding: 10px; background-color: #3498db; color: white; font-size: 24px; border-bottom: #1276bb 3px solid; /* Result of #3498db - #222 */}
.content-area { width: 66.66666667%; float: left; padding: 20px; background-color: #f9f9f9;}
.sidebar { width: 13.33333333%; /* (100%/3) is 33.33...% then 33.33...% - 20px becomes complex, result depends on strictUnits */ /* Note: Mixing % and px in subtraction without calc() is often problematic. For this example, to be robust, it's better to ensure compatible units or use calc(). Let's assume strictUnits: false for this illustrative output. A better way might be: width: calc((100% / 3) - @base-spacing); if escaping is used for calc(). For simplicity, the direct LESS output without calc() might be less predictable based on settings. Let's simplify the LESS for sidebar width for clearer output: width: (100% / 3) - 2%; for a 2% gap. Then CSS output for sidebar width: 31.33333333% */ float: right; padding: 20px; background-color: #eee; color: #67c0ef; /* Result of #3498db + #333 */}/* Corrected CSS for sidebar based on a modified .sidebar width in LESS for clarity:.sidebar { width: 31.33333333%; // If LESS was: width: (100% / 3) - 2%; float: right; padding: 20px; background-color: #eee; color: #67c0ef;} */Note on calc(): For complex calculations involving mixed units (like % and px) that need to be preserved in the final CSS, it’s often better to use the CSS calc() function. You might need to escape it in LESS: width: ~"calc(100% / 3 - 20px)";.
Output
Section titled “Output”Opening index.html will display a layout where dimensions, paddings, font sizes, and even some colors are dynamically calculated based on the operations defined in the LESS file. This demonstrates the power of using operations for creating responsive and themable designs.
LESS - Escaping
Section titled “LESS - Escaping”Description
Section titled “Description”Escaping in LESS (~"value") allows you to output a string literally into your CSS, without LESS attempting to interpret or compile it. This is essential for CSS syntax that LESS might not recognize, for proprietary browser prefixes, or when you need to use characters that have special meaning in LESS.
Example
Section titled “Example”The following example demonstrates using escaping for a non-standard CSS filter (common in older IE versions) and for outputting a CSS variable whose name might conflict with LESS syntax if not handled carefully.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Escaping</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <h1 class="title">Example using Escaping</h1> <p class="custom-prop-text">This text uses a CSS custom property.</p> <div class="legacy-element">This element has a legacy Microsoft filter.</div></body></html>LESS (style.less):
style.less
Section titled “style.less”@custom-property-name: --main-highlight-color;@legacy-filter-value: "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";
.title { color: ~"blue"; // Simple escaping, though 'blue' is a valid color word.}
.custom-prop-text { // Using interpolation for the property name and escaped string for the value @{custom-property-name}: ~"#FFD700"; // Gold color color: var(@custom-property-name);}
.legacy-element { // Escaping a proprietary filter string filter: ~"@{legacy-filter-value}"; // Another example: outputting a complex string for content content: ~"'Chapter ' counter(chapter-number)":";}Compile the style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.title { color: blue;}
.custom-prop-text { --main-highlight-color: #FFD700; color: var(--main-highlight-color);}
.legacy-element { filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50); content: 'Chapter ' counter(chapter-number)':';}In this example, ~"blue" simply outputs blue. The real power is shown with @{custom-property-name}: ~"#FFD700"; where the property value is escaped, and with filter: ~"@{legacy-filter-value}"; where a complex, potentially non-standard string is outputted as is.
Output
Section titled “Output”When index.html is viewed in a browser:
- The
.titlewill be blue. - The
.custom-prop-textwill be gold, styled using a CSS custom property. - The
.legacy-elementwill have the specified Microsoft filter applied (if viewed in a browser that supports it, like older IE) and its content property set. - This demonstrates how escaping ensures that specific strings are passed directly to the CSS output, which is crucial for compatibility or advanced/non-standard CSS features.
LESS - Functions
Section titled “LESS - Functions”Description
Section titled “Description”LESS provides a rich set of built-in functions that allow you to manipulate values, especially colors, numbers, and strings. These functions extend the power of CSS by enabling dynamic calculations and transformations within your stylesheets.
Functions in LESS are invoked by their name followed by parentheses, which may contain arguments. Examples include percentage() for converting numbers to percentages, round() for rounding numbers, and various color functions like lighten(), darken(), and mix().
Example
Section titled “Example”Let’s look at an example using a few common LESS functions.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Functions</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="box"> <p>Styled with LESS functions.</p> </div> <button class="btn-primary">Primary Button</button></body></html>LESS (style.less):
style.less
Section titled “style.less”@base-color: #3498db; // A nice blue@base-font-size: 16px;@container-width-ratio: 0.8; // 80%
.box { background-color: lighten(@base-color, 20%); // Lighten the base color by 20% color: darken(@base-color, 30%); // Darken the base color by 30% for text width: percentage(@container-width-ratio); // Convert 0.8 to 80% padding: round(@base-font-size * 0.75); // Round (16px * 0.75 = 12px) border: 1px solid fade(@base-color, 50%); // Base color with 50% opacity}
.btn-primary { background-color: @base-color; color: white; padding: 10px 15px; border: none; &:hover { background-color: saturate(lighten(@base-color, 10%), 10%); // Make it a bit lighter and more saturated on hover }}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.box { background-color: #8bc4ea; /* #3498db lightened by 20% */ color: #1a4c6e; /* #3498db darkened by 30% */ width: 80%; padding: 12px; border: 1px solid rgba(52, 152, 219, 0.5); /* #3498db with 50% opacity */}
.btn-primary { background-color: #3498db; color: white; padding: 10px 15px; border: none;}.btn-primary:hover { background-color: #5dade2; /* Result of saturate(lighten(@base-color, 10%), 10%) */}LESS offers a wide variety of functions categorized into: Math, String, List, Type Checking, Color Definition, Color Channel, Color Operation, and Color Blending functions. Each category provides specialized tools for manipulating different types of data within your stylesheets.
Output
Section titled “Output”Opening index.html in a browser will show the .box element with a lightened background, darkened text color, calculated width and padding, and a semi-transparent border. The button will change its background color on hover due to color manipulation functions. This demonstrates the dynamic styling capabilities provided by LESS functions.
LESS - Namespaces and Accessors
Section titled “LESS - Namespaces and Accessors”Description
Section titled “Description”Namespaces in LESS allow you to group a set of mixins under a common identifier (an ID selector like #utils or a class selector like .configs). This helps in organizing your mixins, preventing naming conflicts, and creating modular libraries of reusable styles or utilities.
Accessors are used to call or ‘access’ mixins that are defined within a namespace. You use the greater-than symbol (>) or spaces to delve into namespaces and target specific mixins.
Example
Section titled “Example”Let’s create a namespace for some common typographic and box-sizing utilities.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Namespaces</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <article class="blog-post"> <h1>My Awesome Blog Post</h1> <p>Some insightful content here...</p> </article> <div class="widget"> <h2>Widget Title</h2> </div></body></html>LESS (style.less):
style.less
Section titled “style.less”// Define a namespace using an ID selector (often preferred for namespaces)#typography { .heading-font() { font-family: 'Georgia', serif; font-weight: bold; } .body-font() { font-family: 'Arial', sans-serif; line-height: 1.6; }}
// Define another namespace using a class selector.utils { .clearfix() { &::after { content: ""; display: table; clear: both; } } .border-box() { box-sizing: border-box; * { box-sizing: border-box; // Apply to children as well } }}
// Apply the namespaced mixins.blog-post { #typography > .body-font(); // Accessing mixin from #typography namespace
h1 { #typography .heading-font(); // Alternative accessor syntax (space) color: #333; }}
.widget { .utils .border-box(); // Accessing mixin from .utils namespace background: #f0f0f0; padding: 15px; // .utils > .clearfix(); // Could also use this if widget contained floats}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.blog-post { font-family: 'Arial', sans-serif; line-height: 1.6;}.blog-post h1 { font-family: 'Georgia', serif; font-weight: bold; color: #333;}.widget { box-sizing: border-box; background: #f0f0f0; padding: 15px;}.widget * { box-sizing: border-box;}Key points about namespaces and accessors:
Section titled “Key points about namespaces and accessors:”- Namespaces are typically defined using ID selectors (e.g.,
#namespace) or class selectors (e.g.,.namespace). ID selectors are often preferred as they don’t compile to CSS unless explicitly used as selectors. - To call a mixin from a namespace, use
#namespace > .mixin-name()or.namespace .mixin-name()(note the space). - Namespaces can be nested, allowing for more granular organization:
#outer > .inner > .mixin(). - This feature is invaluable for creating reusable LESS libraries or utility sets without polluting the global mixin scope.
Output
Section titled “Output”Opening index.html in a browser will show the blog post and widget styled using the mixins called from their respective namespaces. This demonstrates a clean way to organize and apply reusable style patterns.
LESS - Scope
Section titled “LESS - Scope”Description
Section titled “Description”Scope in LESS refers to the visibility and accessibility of variables and mixins. LESS uses lexical (or static) scoping, which means variables are searched for first in the local scope (where they are being used). If not found locally, the compiler looks in the immediately enclosing (parent) scope, and so on, up to the global scope.
This behavior is similar to how variable scope works in many programming languages. Variables defined later in the same or an inner scope can override (or shadow) variables defined earlier or in an outer scope for that specific part of the code.
Example
Section titled “Example”Let’s explore how scope affects variable resolution.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Scope Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="outer-block"> <p>Outer block text.</p> <div class="inner-block"> <p>Inner block text.</p> <span class="special-span">Special span text.</span> </div> </div></body></html>LESS (style.less):
style.less
Section titled “style.less”@global-color: #3498db; // Global variable@padding: 10px;
.outer-block { @block-color: #2ecc71; // Variable local to .outer-block background-color: lighten(@global-color, 30%); // Uses global-color padding: @padding; // Uses global padding color: @block-color; // Uses local block-color (green)
p { margin-bottom: @padding / 2; // Uses global padding }
.inner-block { @block-color: #e74c3c; // Re-defines block-color, local to .inner-block (shadows outer .block-color) @padding: 5px; // Re-defines padding, local to .inner-block (shadows global padding)
background-color: lighten(@global-color, 40%); // Still uses global-color padding: @padding; // Uses inner-block's local padding (5px) color: @block-color; // Uses inner-block's local block-color (red)
.special-span { // This will use @block-color from .inner-block (red) // because it's the nearest definition in its scope chain. border: 1px solid @block-color; // It will use @padding from .inner-block (5px). margin: @padding; } } // Back in .outer-block scope // If we used @block-color here, it would be green from .outer-block's scope.}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.outer-block { background-color: #a9d8f5; /* lighten(#3498db, 30%) */ padding: 10px; color: #2ecc71;}.outer-block p { margin-bottom: 5px;}.outer-block .inner-block { background-color: #c1e4f7; /* lighten(#3498db, 40%) */ padding: 5px; color: #e74c3c;}.outer-block .inner-block .special-span { border: 1px solid #e74c3c; margin: 5px;}Key points about LESS scope:
Section titled “Key points about LESS scope:”- Local First: LESS looks for variables in the current, most specific scope first.
- Lazy Loading / Last Declaration Wins (for variables at the same level): If multiple variables with the same name are defined in the exact same scope (e.g., globally), the last one declared before usage typically wins. However, for variables used by mixins, the value at the time the mixin is called or expanded is often what matters due to how mixins and variables are processed.
- Shadowing: Variables in inner scopes can ‘shadow’ or hide variables with the same name from outer scopes for the duration of that inner scope.
- Mixins and Scope: Mixins also follow lexical scope. They can access variables from the scope where they are defined and also from the scope where they are called (caller’s scope variables can be passed as arguments or sometimes accessed directly if not shadowed).
Understanding scope is crucial for writing predictable and maintainable LESS code, especially in larger projects with many variables and nested structures.
Output
Section titled “Output”When index.html is viewed, the .outer-block will use the globally defined @global-color (lightened) and its own @block-color (green). The .inner-block will also use the @global-color (lightened more) but will use its own redefined @block-color (red) and @padding (5px). The .special-span within .inner-block will inherit these values from .inner-block’s scope. This demonstrates how different scopes affect the final CSS values.
LESS - Comments
Section titled “LESS - Comments”Description
Section titled “Description”LESS supports two types of comments, similar to many programming languages like JavaScript:
- Block Comments (CSS-style): These start with
/*and end with*/. They can span multiple lines. Block comments are preserved and will appear in the compiled CSS output. - Single-Line Comments (Silent Comments): These start with
//and continue to the end of the line. Single-line comments are ‘silent’ because they are stripped out by the LESS compiler and will not appear in the final CSS output. They are useful for developer notes within the LESS files.
Example
Section titled “Example”Let’s see how both types of comments work.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Comments Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="important-notice"> This is an important notice. </div> <p class="regular-text"> This is some regular text. </p></body></html>LESS (style.less):
style.less
Section titled “style.less”/* * This is a block comment. * It will appear in the compiled CSS file. * Useful for licensing information, or section dividers in CSS. */@primary-color: #3498db;
// This is a single-line comment.// It will NOT appear in the compiled CSS file.// Use these for notes to yourself or other developers working on the LESS code.
.important-notice { color: @primary-color; font-weight: bold; /* Another block comment, will be preserved */ padding: 10px; background-color: #f0f0f0; // Style for emphasis}
// Styles for regular text elements.regular-text { color: #333; line-height: 1.5;}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”/* * This is a block comment. * It will appear in the compiled CSS file. * Useful for licensing information, or section dividers in CSS. */.important-notice { color: #3498db; font-weight: bold; /* Another block comment, will be preserved */ padding: 10px; background-color: #f0f0f0;}
.regular-text { color: #333; line-height: 1.5;}As you can see, the single-line comments (//) are gone, but the block comments (/* ... */) remain in the output CSS.
Best Practices for Comments:
Section titled “Best Practices for Comments:”- Use block comments (
/* ... */) for information that should be part of the distributed CSS (e.g., copyright, usage instructions for a section). - Use single-line comments (
// ...) for development notes, explanations of complex logic, TODOs, or temporarily commenting out code within your LESS files.
Output
Section titled “Output”Opening index.html will show the styled elements. The presence or absence of comments in the CSS file does not affect how the styles are rendered by the browser, but it impacts the readability and maintainability of both the LESS source and the compiled CSS.
LESS - Importing
Section titled “LESS - Importing”Description
Section titled “Description”The @import directive in LESS allows you to split your LESS code into multiple smaller, manageable files (often called partials or modules) and then combine them into a single CSS output file. This is crucial for organizing large projects and promoting reusability.
LESS extends the standard CSS @import rule with more power and flexibility. By default, LESS processes imported .less files and includes their compiled CSS content. Standard CSS @import rules (e.g., for importing external CSS files or Google Fonts) are typically left as-is if they have a .css extension or are full URLs.
Syntax:
@import "path/to/your/file.less"; or @import "filename"; (.less extension is optional if it’s a LESS file).
Example
Section titled “Example”Let’s organize our styles into separate files: one for variables, one for base styles, and one for component styles.
1. Create _variables.less (partials are often prefixed with an underscore):
_variables.less
Section titled “_variables.less”// Variables for colors and fonts@primary-color: #007bff;@secondary-color: #6c757d;@text-color: #333;@base-font-family: Arial, sans-serif;@base-font-size: 16px;2. Create _base.less:
_base.less
Section titled “_base.less”// Base styles for HTML elementsbody { font-family: @base-font-family; font-size: @base-font-size; color: @text-color; line-height: 1.6; margin: 0; padding: 0;}
a { color: @primary-color; text-decoration: none; &:hover { text-decoration: underline; }}3. Create _components.less:
_components.less
Section titled “_components.less”// Styles for a button component.button { display: inline-block; padding: 10px 20px; font-size: @base-font-size; cursor: pointer; border: 1px solid transparent; border-radius: 4px;}
.button-primary { .button(); // Mixin-like call to include .button styles background-color: @primary-color; color: white; border-color: @primary-color;
&:hover { background-color: darken(@primary-color, 10%); }}4. Create the main LESS file, style.less, to import these partials:
style.less
Section titled “style.less”@import "_variables"; // .less extension is optional@import "_base.less";@import "_components";
// Additional styles specific to this main file.header { background-color: @secondary-color; color: white; padding: 20px; text-align: center;}5. Create an HTML file (index.html) to use these styles:
index.html
Section titled “index.html”<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Importing Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <header class="header"> <h1>Modular Styles with LESS Imports</h1> </header> <main style="padding: 20px;"> <p><a href="#">This is a link.</a></p> <button class="button-primary">Click Me</button> </main></body></html>6. Compile style.less:
lessc style.less style.cssThe compiled style.css will contain all the styles from _variables.less, _base.less, _components.less, and style.less, combined in the order they were imported:
style.css (snippet)
Section titled “style.css (snippet)”/* ... (styles from _variables are used, not output directly) ... */body { font-family: Arial, sans-serif; font-size: 16px; color: #333; line-height: 1.6; margin: 0; padding: 0;}a { color: #007bff; text-decoration: none;}a:hover { text-decoration: underline;}.button { display: inline-block; padding: 10px 20px; font-size: 16px; cursor: pointer; border: 1px solid transparent; border-radius: 4px;}.button-primary { /* Styles from .button() mixin call */ display: inline-block; padding: 10px 20px; font-size: 16px; cursor: pointer; border: 1px solid transparent; border-radius: 4px; /* Own styles */ background-color: #007bff; color: white; border-color: #007bff;}.button-primary:hover { background-color: #0056b3; /* darken(#007bff, 10%) */}.header { background-color: #6c757d; color: white; padding: 20px; text-align: center;}Import Options:
Section titled “Import Options:”LESS provides several import options using keywords in parentheses after @import, such as @import (reference) "file.less";, @import (once) "file.less"; (default behavior), @import (multiple) "file.less";, @import (less) "file.css"; (treat as LESS), @import (css) "file.less"; (treat as CSS).
Output
Section titled “Output”Opening index.html will show a page styled by the modularly organized LESS files. This approach significantly improves the maintainability and scalability of CSS projects.
LESS - Variables
Section titled “LESS - Variables”Variables in LESS are fundamental for writing reusable and maintainable CSS. They allow you to define a value once and reuse it throughout your stylesheets. If you need to change that value later (e.g., a primary color or a base font size), you only need to update it in one place.
Variables are declared using the @ symbol followed by a name, and assigned a value using a colon (:), for example: @primary-color: #3498db;.
The following table highlights key aspects of using LESS variables:
| ID | Variable Usage & Description |
|---|---|
| 1 | Overview & Basic Usage Variables store values like colors, font stacks, dimensions, or even strings. They help avoid repetition and make global style changes easy. Example: @base-font-size: 16px; body { font-size: @base-font-size; } |
| 2 | Variable Interpolation Variables can be inserted into strings, selector names, property names, URLs, and @import statements using the @{variable-name} syntax.Example: @image-path: "/images"; .icon { background-image: url("@{image-path}/icon.png"); }Example for selector: @my-class: special; .@{my-class}-button { color: red; } compiles to .special-button { color: red; } |
| 3 | Variable Names (Naming Conventions) Variable names can consist of alphanumeric characters, hyphens ( -), and underscores (_). They must start with @. It’s good practice to use descriptive names (e.g., @primary-brand-color instead of @c1). |
| 4 | Scope and Lazy Loading LESS variables have lexical scope. They are first looked up in the local scope, then in parent scopes. LESS features ‘lazy loading’ for variables, meaning variables are not evaluated until they are actually used. For variables defined at the same level, the last definition before usage generally takes precedence. This also means you can define variables after they are referenced, as long as they are defined within the same or an accessible scope before compilation output is generated for that reference. |
| 5 | Default Variables (Theming) While LESS doesn’t have a specific ‘default variable’ syntax like some other preprocessors, you can achieve similar behavior for theming. A common pattern is to define base variables, then allow overrides. More directly, you can re-declare a variable later in the cascade to change its value. Mixins can also be designed to use passed-in values or fall back to internal defaults if arguments are not provided. |
Example: Using Variables for Theming
Section titled “Example: Using Variables for Theming”style.less// Default theme variables@theme-background: #ffffff;@theme-text-color: #333333;@theme-primary-color: #007bff;
body { background-color: @theme-background; color: @theme-text-color;}
a { color: @theme-primary-color;}
.button-primary { background-color: @theme-primary-color; color: white; padding: 10px 15px;}
// --- Potentially in another imported file for a dark theme override ---// To apply a dark theme, these variables could be redefined:// @theme-background: #333333;// @theme-text-color: #f0f0f0;// @theme-primary-color: #17a2b8;//// .dark-theme {// @theme-background: #222222;// @theme-text-color: #eeeeee;// @theme-primary-color: #1abc9c;// // Re-apply styles that use these variables, or structure so they inherit naturally// background-color: @theme-background;// color: @theme-text-color;// a { color: @theme-primary-color; }// .button-primary { background-color: @theme-primary-color; }// }This illustrates how variables form the backbone of dynamic and maintainable stylesheets in LESS.
LESS - Extend
Section titled “LESS - Extend”:extend() is a LESS pseudo-class that allows a selector to inherit the styles of another selector without duplicating the CSS properties in the output. Instead, it appends the extending selector to the list of selectors for the extended rule. This results in more efficient, DRY (Don’t Repeat Yourself) CSS.
It’s an alternative to mixins when you want to group selectors that share the exact same style block, rather than copying the style block to multiple places.
Example 1: Basic Extend
Section titled “Example 1: Basic Extend”HTML (extend_basic.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Extend Basic</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="error-message">An error occurred!</div> <div class="warning-message">Please check your input.</div></body></html>LESS (style.less):
style.less
Section titled “style.less”.message { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; font-family: Arial, sans-serif;}
.error-message { &:extend(.message); // .error-message inherits styles from .message border-color: red; background-color: #ffeeee; color: darkred;}
.warning-message:extend(.message) { // Extend can also be attached directly to the selector border-color: orange; background-color: #fff8e1; color: #e65100;}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.message,.error-message,.warning-message { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; font-family: Arial, sans-serif;}
.error-message { border-color: red; background-color: #ffeeee; color: darkred;}
.warning-message { border-color: orange; background-color: #fff8e1; color: #e65100;}Output for Example 1
Section titled “Output for Example 1”Both .error-message and .warning-message will share the common styles from .message (padding, margin, font) and then apply their specific styles (border color, background, text color). The CSS is efficient because the common styles are defined once.
Extend Syntax and Options
Section titled “Extend Syntax and Options”:extend() can be placed inside a ruleset (using &:extend(...)) or attached directly to a selector. It can extend one or more selectors, separated by commas: &:extend(.classA, .classB).
The all keyword: If you use :extend(.selector all), it will extend all instances of .selector, including those nested within other selectors (e.g., .parent .selector). Without all, it typically only extends exact top-level selector matches.
Example 2: Extending Multiple Selectors and all
Section titled “Example 2: Extending Multiple Selectors and all”LESS (style.less):
style.less
Section titled “style.less”.base-style { font-weight: bold;}
.another-base { text-transform: uppercase;}
nav ul .menu-item { color: blue;}
.special-link { &:extend(.base-style, .another-base); color: green;}
.highlighted-menu { // This will extend .menu-item only where it's exactly `nav ul .menu-item` // &:extend(nav ul .menu-item); // This extends any selector that *ends* with .menu-item, like `nav ul .menu-item` &:extend(.menu-item all); background-color: yellow;}Compiled style.css (conceptual):
style.css
Section titled “style.css”.base-style,.special-link { font-weight: bold;}
.another-base,.special-link { text-transform: uppercase;}
nav ul .menu-item,nav ul .highlighted-menu { /* if .highlighted-menu was structured to match */ color: blue;}/* More accurately for `:extend(.menu-item all)` if .highlighted-menu is a class on its own: *//* nav ul .menu-item { color: blue; } would be extended by nav ul .highlighted-menu if .highlighted-menu also appears under nav ul *//* If .highlighted-menu is a top-level class just extending, then: *//* nav ul .menu-item, .highlighted-menu { color: blue; } -- this is simplified. Actual `all` behavior depends on selector matching. */
.special-link { color: green;}
.highlighted-menu { background-color: yellow;}/* If .highlighted-menu extends .menu-item all, and .menu-item itself has styles like color: blue, then .highlighted-menu will also get color: blue. The selector list for `color: blue` will include .highlighted-menu. *//* Corrected for clarity on `all` when `.highlighted-menu` is a peer: */nav ul .menu-item,.highlighted-menu { /* Assuming .highlighted-menu could apply to similar elements */ color: blue;}Use Cases for Extend:
Section titled “Use Cases for Extend:”- Semantic Grouping: Group elements that share a base appearance but have distinct modifiers (e.g., different types of alerts or buttons).
- Reducing CSS Bloat: Avoids repeating CSS properties, leading to smaller file sizes compared to using mixins for the same purpose.
- Advanced Mixin-like Behavior: Can be used to build more complex relationships between styles than simple property copying.
Differences from Mixins:
Section titled “Differences from Mixins:”- Mixins copy properties into the calling selector. Good for utility-like functions and when you need to pass parameters.
- Extend shares selectors. Good for semantic relationships and when you want to avoid code duplication for identical style blocks.
The following table summarizes key aspects of :extend:
| ID | Syntax/Behavior & Description |
|---|---|
| 1 | Extend Attached to Selector Syntax: .my-selector:extend(.extended-selector) { ... }. Styles from .extended-selector are applied to .my-selector by adding .my-selector to .extended-selector’s rules. |
| 2 | Extend Inside Ruleset Syntax: .my-selector { &:extend(.extended-selector); ... }. Same effect as above. |
| 3 | Extending Nested Selectors&:extend(.parent .child) will try to match and extend that specific nested structure. |
| 4 | Exact Matching vs. allBy default, extend looks for an exact match of the selector being extended. The all keyword (e.g., &:extend(.child all)) makes it match any selector sequence ending with .child. |
| 5 | Extending Multiple Selectors&:extend(.sel1, .sel2) will extend both .sel1 and .sel2. |
| 6 | Selector Interpolation with Extend:extend(@{my-variable}) is possible but has limitations; the selector must be static at compile time for extend to work reliably. |
| 7 | Scoping/Extend inside @mediaExtend only matches selectors within the same @media block. It will not extend selectors outside its current media context. |
| 8 | Duplication Detection LESS tries to avoid creating duplicate CSS entries when multiple extends target the same rule. |
LESS - Mixins
Section titled “LESS - Mixins”Mixins are one of LESS’s most powerful features. They allow you to embed a set of CSS properties from one ruleset (the mixin) into another ruleset. Think of them as reusable ‘functions’ or ‘includes’ for CSS properties.
This helps in keeping your code DRY (Don’t Repeat Yourself) by defining common styles once and applying them wherever needed.
Basic Mixins
Section titled “Basic Mixins”A mixin is defined just like a CSS class or ID selector. To use a mixin, you simply include its name as if it were a CSS property within another ruleset.
Example: Basic Mixin
Section titled “Example: Basic Mixin”HTML (mixins_basic.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Mixins Basic</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="box-alert">This is an alert.</div> <div class="box-success">This is a success message.</div> <p class="important-text">Some important text.</p></body></html>LESS (style.less):
style.less
Section titled “style.less”// Define a basic mixin for common box styling.common-box-styles() { // Adding () makes it a 'hidden' mixin, not output as a class padding: 15px; margin-bottom: 20px; border: 1px solid #ddd; border-radius: 4px;}
// Another mixin.text-emphasis { font-weight: bold; font-style: italic;}
.box-alert { .common-box-styles(); // Use the mixin background-color: #f8d7da; color: #721c24; border-color: #f5c6cb;}
.box-success { .common-box-styles; // Parentheses are optional when calling if the mixin isn't hidden background-color: #d4edda; color: #155724; border-color: #c3e6cb;}
.important-text { .text-emphasis; // Use the .text-emphasis mixin color: #d9534f;}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”/* Note: .common-box-styles() itself is not output as a class because of the () */.text-emphasis { font-weight: bold; font-style: italic;}
.box-alert { padding: 15px; margin-bottom: 20px; border: 1px solid #ddd; border-radius: 4px; background-color: #f8d7da; color: #721c24; border-color: #f5c6cb;}
.box-success { padding: 15px; margin-bottom: 20px; border: 1px solid #ddd; border-radius: 4px; background-color: #d4edda; color: #155724; border-color: #c3e6cb;}
.important-text { font-weight: bold; font-style: italic; color: #d9534f;}Key aspects of Mixins:
Section titled “Key aspects of Mixins:”| ID | Mixin Usage & Description | Example Snippet |
|---|---|---|
| 1 | Not Outputting the Mixin (Hidden Mixins) If you define a mixin with parentheses after its name (e.g., .my-mixin() { ... }), it will not be output as a CSS class itself. It only serves as a source for other rulesets to include. This is the common practice for utility mixins. | .hidden-mixin() { color: blue; } .element { .hidden-mixin(); }CSS: .element { color: blue; } (.hidden-mixin is not output). |
| 2 | Selectors in Mixins Mixins can contain not just properties, but also nested selectors. When the mixin is used, these nested selectors are also included, relative to the calling selector. | .parent-mixin() { strong { color: red; } } .my-text { .parent-mixin(); }CSS: .my-text strong { color: red; } |
| 3 | Namespaces Group related mixins under a common ID or class selector to avoid naming conflicts and improve organization (e.g., #utils > .clearfix()). See the ‘Namespaces and Accessors’ chapter. | #ui-helpers { .border-radius(@radius) { border-radius: @radius; } } .box { #ui-helpers > .border-radius(5px); } |
| 4 | Guarded Mixins Mixins can have conditions (guards) attached using the when keyword. The mixin is applied only if the condition evaluates to true. This allows for conditional logic. | .text-color(@c) when (lightness(@c) < 50%) { color: white; } .text-color(@c) when (lightness(@c) >= 50%) { color: black; } .dark-bg { background: #333; .text-color(#333); } |
| 5 | The !important KeywordIf you add !important to a mixin call (e.g., .my-mixin() !important;), all properties within that mixin will be output with !important. | .important-styles() { color: red; font-weight: bold; } .warning { .important-styles() !important; }CSS: .warning { color: red !important; font-weight: bold !important; } |
Parentheses () are optional when calling a mixin if the mixin itself was defined without parentheses and is not parametric (see Parametric Mixins). However, using parentheses (e.g., .mixin-name();) is a common convention, especially for hidden mixins.
Output
Section titled “Output”The HTML elements .box-alert, .box-success, and .important-text will be styled by including the properties from .common-box-styles() and .text-emphasis respectively, plus their own specific styles. This demonstrates how mixins promote code reuse and consistency.
LESS - Parametric Mixins
Section titled “LESS - Parametric Mixins”Description
Section titled “Description”Parametric mixins in LESS are like functions in programming: they accept arguments (parameters) that can be used to customize their output. This makes mixins even more flexible and powerful, allowing you to create highly reusable style patterns that can adapt to different needs.
Parameters are defined in parentheses after the mixin name, separated by commas (,) or semicolons (;). Semicolons are often preferred as commas can be ambiguous if you’re passing comma-separated lists as arguments.
Example: Basic Parametric Mixin
Section titled “Example: Basic Parametric Mixin”Let’s define a mixin for creating borders with customizable width, style, and color.
LESS (`style.less`):.bordered(@width: 1px; @style: solid; @color: #ccc) { border-width: @width; border-style: @style; border-color: @color;}
.element1 { .bordered(2px; dashed; blue); // All arguments provided}
.element2 { .bordered(@color: red); // Only color provided, others use defaults}
.element3 { .bordered(3px; dotted); // Width and style provided, color uses default}
.element4 { .bordered(); // All defaults used}Compiled CSS (`style.css`):.element1 { border-width: 2px; border-style: dashed; border-color: blue;}.element2 { border-width: 1px; border-style: solid; border-color: red;}.element3 { border-width: 3px; border-style: dotted; border-color: #ccc;}.element4 { border-width: 1px; border-style: solid; border-color: #ccc;}Key features of Parametric Mixins:
Section titled “Key features of Parametric Mixins:”| ID | Feature & Description | Example Snippet |
|---|---|---|
| 1 | Default Values for Parameters You can provide default values for parameters (e.g., @width: 1px). If an argument is not passed when calling the mixin, the default value is used. | .padding(@y: 10px; @x: 20px) { padding: @y @x; } .box { .padding(); }CSS: .box { padding: 10px 20px; } |
| 2 | Named Parameters You can pass arguments by name, which allows you to skip parameters with default values or pass them in a different order. | .text-style(@size: 1em; @weight: normal; @color: #333) { font-size: @size; font-weight: @weight; color: @color; } .title { .text-style(@color: blue; @size: 2em); }CSS: .title { font-size: 2em; font-weight: normal; color: blue; } |
| 3 | The @arguments VariableInside a mixin, the special variable @arguments holds all the arguments passed to the mixin as a space-separated list. Useful for shorthand properties like padding or margin. | .shorthand-padding(...) { padding: @arguments; } .box { .shorthand-padding(10px 20px 5px); }CSS: .box { padding: 10px 20px 5px; } (The ... indicates it accepts variable arguments, which are all captured by @arguments) |
| 4 | Rest Arguments (@rest... or ...)You can define a mixin to accept a variable number of arguments using ... at the end of its parameter list (e.g., .my-mixin(@a, @b, @rest...)). The @rest variable will then hold any additional arguments as a list. | .box-shadow(@x; @y; @blur; @color; @rest...) { box-shadow: @x @y @blur @color @rest; } .fancy { .box-shadow(2px; 2px; 5px; #000; inset; 0 0 10px #fff); }CSS: .fancy { box-shadow: 2px 2px 5px #000 inset, 0 0 10px #fff; } (@rest captures inset, 0 0 10px #fff) |
| 5 | Pattern-Matching (Overloading) You can define multiple mixins with the same name but different parameters (or different numbers of parameters). LESS will execute the mixin that matches the arguments passed. | .icon(arrow) { background-image: url('arrow.png'); } .icon(home) { background-image: url('home.png'); } .go-home { .icon(home); }This is more about specific value matching rather than typical overloading by type/count, but related. |
Parametric mixins significantly enhance the abstraction capabilities of LESS, allowing for the creation of sophisticated and highly configurable style components.
LESS - Mixins as Functions
Section titled “LESS - Mixins as Functions”While LESS has dedicated functions for various operations (color, math, string, etc.), mixins themselves can behave somewhat like functions, especially when they define variables or return values implicitly through their scope. They can encapsulate logic, take parameters, and effectively ‘return’ results by making variables defined within them available to the caller’s scope or by directly outputting CSS.
This concept is more about how mixins interact with scope and variable definitions rather than them being true, first-class functions that return a single, isolated value like in many programming languages.
The following table highlights aspects of mixins that give them function-like qualities:
| ID | Aspect & Description | Conceptual Example |
|---|---|---|
| 1 | Mixin Scope and Variable Exposure Variables defined inside a mixin are generally local to that mixin. However, if a mixin is called, and it sets variables that are not shadowed by parameters, these variables can sometimes be interpreted as ‘output’ or ‘results’ that affect the calling scope or subsequent rules. | This is complex and behavior can depend on LESS version and strictness. Generally, variables set by a mixin are primarily for use within that mixin’s CSS output. Direct ‘return’ of values to the calling scope for further computation is less common than using mixins to apply styles. |
| 2 | Mixins ‘Returning’ Styles The primary ‘return value’ of a mixin is the block of CSS properties it generates. Parametric mixins allow these styles to be dynamic. | .button-style(@bg-color) { background-color: @bg-color; color: white; padding: 10px; } .submit-btn { .button-style(blue); }The ‘result’ is the set of styles applied to .submit-btn. |
| 3 | Mixins Defining Variables for Later Use (Advanced) A mixin can define variables which are then used by other mixins or rules defined after the calling mixin, provided they are in an accessible scope. This is a more advanced pattern often seen in utility or theming libraries. | // LESS<br>.setup-theme(@primary) {<br> @theme-color: @primary;<br> @theme-accent: lighten(@primary, 20%);<br>}<br><br>.my-component {<br> .setup-theme(blue);<br> background-color: @theme-color; // Uses 'blue'<br> border-color: @theme-accent; // Uses 'lighten(blue, 20%)'<br>}<br>In this conceptual example, .setup-theme ‘sets up’ variables that .my-component then uses. The variables @theme-color and @theme-accent are effectively ‘returned’ to the scope of .my-component or a scope accessible by its subsequent rules. |
True Function-Like Behavior vs. Style Encapsulation
Section titled “True Function-Like Behavior vs. Style Encapsulation”It’s important to distinguish between LESS’s built-in functions (like lighten(), round()) which take input and return a single value for use in a property, and mixins. Mixins are primarily for encapsulating and reusing blocks of CSS rules and properties.
While mixins can manipulate data via parameters and internal variables, their main ‘output’ is CSS rules. The idea of them ‘returning values’ like programmatic functions is more about how they influence the compilation context and variable scope rather than returning a single data item for assignment to another variable.
For calculations and value transformations, prefer built-in LESS functions. Use mixins for grouping and reusing style declarations, potentially customized with parameters.
LESS - Passing Rulesets to Mixins (Detached Rulesets)
Section titled “LESS - Passing Rulesets to Mixins (Detached Rulesets)”Description
Section titled “Description”A Detached Ruleset in LESS is a powerful feature where a block of CSS rules (including properties, nested rules, variable declarations, and even other mixin calls) can be stored in a variable. This variable (the detached ruleset) can then be passed to a mixin or called directly, effectively injecting its content into another structure.
This allows for highly dynamic and configurable styles, enabling patterns similar to higher-order functions or callbacks in programming.
Example
Section titled “Example”Let’s demonstrate how to define a detached ruleset and pass it to a mixin that applies it within a specific context, like a media query.
HTML (detached_ruleset.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LESS Detached Rulesets</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="responsive-box"> This box changes style on larger screens. </div></body></html>LESS (style.less):
style.less
Section titled “style.less”// Define a mixin that accepts a detached ruleset and a media query condition.apply-responsive-styles(@ruleset; @condition) { @media @condition { @ruleset(); // Call/execute the detached ruleset here }}
// Define a detached ruleset and store it in a variable@large-screen-styles: { // This is the detached ruleset background-color: lightblue; font-size: 1.2em; border: 2px solid darkblue; .nested-rule { padding: 10px; }};
// Another detached ruleset@small-screen-specifics: { font-weight: bold;};
.responsive-box { padding: 15px; background-color: #f0f0f0; border: 1px solid #ccc;
// Apply the large screen styles using the mixin .apply-responsive-styles(@large-screen-styles; ~"(min-width: 768px)");
// Detached rulesets can also be called directly if needed (not passed to mixin here) // @small-screen-specifics(); // This would apply small-screen-specifics directly to .responsive-box}
// Example of passing a ruleset with variables@block-styles: { @block-color: red; color: @block-color; margin: 10px; .inner { color: darken(@block-color, 10%); }};
.another-box { @block-styles(); // Calling the detached ruleset directly}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.responsive-box { padding: 15px; background-color: #f0f0f0; border: 1px solid #ccc;}@media (min-width: 768px) { .responsive-box { background-color: lightblue; font-size: 1.2em; border: 2px solid darkblue; } .responsive-box .nested-rule { padding: 10px; }}.another-box { color: red; margin: 10px;}.another-box .inner { color: #cc0000; /* darken(red, 10%) */}Output
Section titled “Output”When detached_ruleset.html is viewed:
- By default,
.responsive-boxhas a light grey background. - When the viewport width is 768px or more, the styles from
@large-screen-styles(lightblue background, larger font, darkblue border) are applied to.responsive-boxdue to the.apply-responsive-stylesmixin. - The
.another-boxwill have styles from@block-stylesapplied directly.
Scoping with Detached Rulesets
Section titled “Scoping with Detached Rulesets”Variables and mixins within a detached ruleset are resolved based on lexical scope. The detached ruleset has access to variables from where it’s defined and where it’s called. The declaration scope (where the ruleset is defined) typically takes precedence if there are naming conflicts.
The following table summarizes scope aspects for detached rulesets:
| ID | Scope Aspect & Description | Conceptual Example |
|---|---|---|
| 1 | Definition and Caller Scope Visibility A detached ruleset can access variables from both the scope where it was defined and the scope where it is called/executed. Variables defined inside the detached ruleset are local to it but are used when the ruleset is expanded. | @def-var: blue; .caller { @call-var: red; @my-rules: { color: @def-var; border-color: @call-var; }; @my-rules(); }Result: color blue, border-color red. |
| 2 | Referencing Won’t Modify Detached Ruleset Scope Simply assigning a detached ruleset to another variable ( @new-rules: @old-rules;) does not change its original scope or give it access to new scopes until it’s actually called. | The scope is primarily determined at definition and call sites. |
| 3 | Unlocking Scope with Imports (Advanced) If a detached ruleset is defined in one file and imported (with specific options) into another, its scope interaction can become more complex, potentially ‘unlocking’ or gaining access to the importer’s scope. This is an advanced use case. | Typically, standard lexical scoping rules apply. |
Detached rulesets are an advanced feature useful for creating highly configurable mixins, theming systems, or managing complex conditional styling logic.
LESS - Import Directives
Section titled “LESS - Import Directives”Description
Section titled “Description”The @import directive in LESS is a powerful tool for modularizing your stylesheets. It allows you to break down your LESS code into smaller, more manageable files (often called partials) and then combine them into a single CSS output file. This significantly improves organization, maintainability, and reusability in larger projects.
LESS extends the standard CSS @import functionality. You can place @import statements almost anywhere in your LESS code, not just at the top.
For instance, you can import a file using @import "variables"; (the .less extension is often optional for LESS files).
File Extensions and Behavior
Section titled “File Extensions and Behavior”LESS handles @import statements differently based on the file extension and certain keywords:
.lessextension: If the imported file has a.lessextension (or no extension, in which case.lessis assumed), LESS will process it and include its compiled CSS content in place of the@importstatement. Example:@import "_buttons.less";or@import "_buttons";.cssextension: If the file has a.cssextension, LESS treats it as a standard CSS import. The@importstatement will be preserved as is in the compiled CSS output. Example:@import "normalize.css";results in@import "normalize.css";in the CSS.- Full URL: If the import path is a full URL (e.g.,
@import url('https://fonts.googleapis.com/css?family=Open+Sans');), it’s treated as a standard CSS import and preserved. - Other extensions: If a file with an extension other than
.cssor.lessis imported (e.g.,.phpas in the old example, or.txt), LESS will still try to process it as a LESS file. This is generally not recommended; use.lessfor LESS files. - Import Options: Keywords like
(less),(css),(reference),(inline)can force LESS to treat the imported file in a specific way, overriding default behavior based on extension (see ‘Import Options’ chapter).
Example of how extensions affect imports:@import "theme-variables"; // Imports theme-variables.less and processes it@import "base-styles.less"; // Imports base-styles.less and processes it@import "external-lib.css"; // Preserves as @import "external-lib.css"; in output@import (less) "my-styles.css"; // Treats my-styles.css as a LESS file and processes it@import (css) "component.less"; // Outputs @import "component.less"; (treats as CSS import)Example: Practical Usage
Section titled “Example: Practical Usage”Let’s create a simple project structure with imported files.
HTML (index.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Import Directives</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <header class="main-header">Header Content</header> <p class="main-text">Welcome to our website using modular LESS styles!</p></body></html>Create a partial, e.g., _typography.less:
_typography.less
Section titled “_typography.less”@base-font-size: 16px;@heading-font-family: 'Georgia', serif;
body { font-size: @base-font-size;}
.main-header { font-family: @heading-font-family; font-size: @base-font-size * 1.8;}Now, create the main style.less file and import the partial:
style.less
Section titled “style.less”// Import variables (if you have a separate _variables.less)// @import "_variables";
@import "_typography"; // Imports _typography.less
// Styles defined in the main file.main-header { background-color: #333; color: white; padding: 20px;}
.main-text { color: #555; margin-top: 15px; font-size: @base-font-size * 1.1; // Uses @base-font-size from _typography.less}The _typography.less file’s content will be processed and included in style.less. Variables defined in _typography.less (like @base-font-size) are available to subsequent rules in style.less.
Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will combine both files:
style.css
Section titled “style.css”body { font-size: 16px;}
.main-header { font-family: 'Georgia', serif; font-size: 28.8px; /* 16px * 1.8 */ background-color: #333; color: white; padding: 20px;}
.main-text { color: #555; margin-top: 15px; font-size: 17.6px; /* 16px * 1.1 */}Output
Section titled “Output”Opening index.html in a browser will show the page styled according to the combined rules from both _typography.less and style.less, demonstrating the power of modular CSS development with LESS imports.
LESS - Import Options
Section titled “LESS - Import Options”LESS enhances the @import directive with several options that control how files are imported and processed. These options are specified in parentheses after the @import keyword and before the file path, e.g., @import (option) "filename";.
These options provide fine-grained control over the import process, allowing for advanced use cases like referencing styles without outputting them, inlining CSS, or ensuring files are imported only once.
The following table lists the available import options:
| ID | Import Option & Description | Explanation/Example Outcome |
|---|---|---|
| 1 | reference@import (reference) "library.less";Imports the LESS file but does not output its CSS directly. Styles from the referenced file are only output if they are used via :extend or called as mixins from the importing file. This is useful for importing utility libraries (like collections of mixins or placeholder selectors) without adding their entire codebase to your CSS unless specifically used. | If library.less contains .my-mixin { color: blue; }, and your main file does .element { .my-mixin(); }, only then will color: blue; be part of the output for .element. .my-mixin itself won’t be output unless also defined without () and used as a class. |
| 2 | inline@import (inline) "external.css";Includes the content of the specified file directly into the output CSS without any LESS processing. The imported file’s content is treated as plain CSS. This is useful for embedding third-party CSS that you don’t want LESS to interfere with. | If external.css contains body { margin: 0; }, this exact CSS will be placed into your output file. |
| 3 | less@import (less) "styles.txt";Forces LESS to treat the imported file as a LESS file and process it, regardless of its actual file extension. This can be useful if you have LESS code in files with non-standard extensions. | If styles.txt contains @color: red; .box { color: @color; }, it will be processed as LESS, outputting .box { color: red; }. |
| 4 | css@import (css) "variables.less";Forces LESS to treat the imported file as a standard CSS file. The @import statement itself will be preserved in the output CSS, rather than LESS processing the file’s content. | @import (css) "variables.less"; will output @import "variables.less"; in the final CSS file. |
| 5 | once@import (once) "theme.less"; (This is the default behavior).Ensures that a file is imported and processed only one time, even if it’s imported multiple times in your project. This prevents duplicate CSS output and redundant processing. | If theme.less is imported in multiple files, its styles will only appear once in the final compiled CSS. |
| 6 | multiple@import (multiple) "mixins.less";Allows a file to be imported and processed multiple times if it’s referenced more than once. This is rarely needed but can be useful in specific scenarios where you intentionally want to duplicate the output of a LESS file, perhaps with different variable contexts (though this is advanced and often better handled by parametric mixins). | Use with caution as it can lead to bloated CSS if not managed carefully. |
| 7 | optional@import (optional) "custom-overrides.less";Allows compilation to proceed even if the file to be imported is not found. If the file exists, it’s imported; if not, LESS continues compiling without an error. This is useful for theme customizations or optional modules that might not always be present. | If custom-overrides.less doesn’t exist, no error is thrown and compilation continues. If it exists, it’s imported normally. |
Multiple keywords can be used by separating them with commas, for example:
@import (reference, optional) "ui-kit-variables.less";This would import ui-kit-variables.less only for reference (its styles won’t be output unless used), and if the file doesn’t exist, compilation will continue without error.
Understanding and using these import options effectively can significantly improve the structure, efficiency, and flexibility of your LESS projects.
LESS - Mixin Guards
Section titled “LESS - Mixin Guards”Description
Section titled “Description”Mixin Guards in LESS allow you to define conditions under which a mixin should be applied. They act like ‘if’ statements for your mixins, enabling conditional logic within your stylesheets. A guarded mixin will only produce output if its guard condition evaluates to true.
Guards are specified using the when keyword followed by a condition in parentheses, placed after the mixin declaration. You can have multiple guard conditions for different versions of a mixin (overloading based on conditions) or multiple conditions for a single mixin (using and, or, not).
Guard Conditions can use:
- Comparison operators:
>,>=,=(for equality, not assignment),=<,<. - Logical operators:
and,or,not(). - Type checking functions:
iscolor(),isnumber(),isstring(),iskeyword(),isurl(), etc. - The
default()function, which acts as an ‘else’ condition if no other guarded mixin matches.
Example
Section titled “Example”Let’s create mixins that apply different styles based on color lightness or a specific keyword.
HTML (mixin_guards.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Mixin Guards</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="light-background-box">Light Background</div> <div class="dark-background-box">Dark Background</div> <div class="button-primary">Primary Button</div> <div class="button-secondary">Secondary Button</div></body></html>LESS (style.less):
style.less
Section titled “style.less”// Mixin to set text color based on background lightness.adaptive-text-color(@bg-color) when (lightness(@bg-color) >= 50%) { color: #333; // Dark text for light backgrounds}.adaptive-text-color(@bg-color) when (lightness(@bg-color) < 50%) { color: #fff; // Light text for dark backgrounds}
// Mixin for button styles based on type.button-style(@type) when (@type = primary) { background-color: blue; border: 1px solid darkblue;}.button-style(@type) when (@type = secondary) { background-color: grey; border: 1px solid dimgrey;}// Default or common button styles (can also use default() guard).button-style(@type) { padding: 10px 15px; display: inline-block; text-align: center; // This ensures text color is adaptive for any button type .adaptive-text-color(extract(lookup("background-color"), 1)); // A bit advanced: look up its own bg color // Simpler: pass bg color: .adaptive-text-color(blue) for primary}
.light-background-box { background-color: #f0f0f0; // Light background padding: 20px; .adaptive-text-color(#f0f0f0);}
.dark-background-box { background-color: #2c3e50; // Dark background padding: 20px; .adaptive-text-color(#2c3e50);}
.button-primary { .button-style(primary); // To make adaptive text color simpler for buttons: .adaptive-text-color(blue); // Explicitly pass the known background}
.button-secondary { .button-style(secondary); .adaptive-text-color(grey);}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.button-style { /* This common part from .button-style(@type) might appear if called without matching guard, or its properties get merged if a guarded version matches. The example needs refinement for the lookup() which is complex. For clarity, let's assume the common styles are always output. */ padding: 10px 15px; display: inline-block; text-align: center;}
.light-background-box { background-color: #f0f0f0; padding: 20px; color: #333; /* From .adaptive-text-color due to light #f0f0f0 */}
.dark-background-box { background-color: #2c3e50; padding: 20px; color: #fff; /* From .adaptive-text-color due to dark #2c3e50 */}
.button-primary { /* Common button styles */ padding: 10px 15px; display: inline-block; text-align: center; /* Styles from .button-style(primary) */ background-color: blue; border: 1px solid darkblue; /* Text color */ color: #fff; /* From .adaptive-text-color(blue) */}
.button-secondary { /* Common button styles */ padding: 10px 15px; display: inline-block; text-align: center; /* Styles from .button-style(secondary) */ background-color: grey; border: 1px solid dimgrey; /* Text color */ color: #333; /* From .adaptive-text-color(grey) */}Note: The lookup() function used in the original example for .button-style(@type) is an advanced feature for inspecting previously set properties and might not always be straightforward. A more common pattern for adaptive text on buttons would be to call .adaptive-text-color() explicitly with the button’s background color inside each specific button style, as shown in the corrected .button-primary and .button-secondary.
Types of Mixin Guards and Operators:
Section titled “Types of Mixin Guards and Operators:”| ID | Type & Description |
|---|---|
| 1 | Guard Comparison Operators Use <, >, <=, >=, = (equality) to compare numbers, strings, keywords, etc. Example: when (@value > 10), when (@name = "example"). |
| 2 | Guard Logical Operators Combine conditions using and, or. Negate conditions using not(). Example: when (@value > 10) and (@name = "example"), when not (@value = 0). |
| 3 | Type Checking Functions Use functions like iscolor(), isnumber(), isstring(), iskeyword(), isurl(), isunit(@val, unit) within guards. Example: when (iscolor(@param)), when (isnumber(@param)) and (@param > 0). |
| 4 | The default() FunctionThe default() function in a guard evaluates to true if no other mixin (with the same name) an_conditions that evaluated to true. It acts like an ‘else’ or fallback case. |
Output
Section titled “Output”The HTML elements will be styled conditionally. The .light-background-box will get dark text, and .dark-background-box will get light text. .button-primary and .button-secondary will have distinct styles based on the type passed to .button-style(), and their text colors will also adapt. This showcases the power of guards for creating flexible and intelligent mixins.
LESS - CSS Guards
Section titled “LESS - CSS Guards”Description
Section titled “Description”CSS Guards (or Selector Guards) in LESS allow you to apply a whole style block (ruleset) conditionally, based on a guard expression. Unlike mixin guards which control whether a mixin’s content is output, CSS guards control whether an entire CSS ruleset (including its selector) is output.
They are applied directly to selectors using the when keyword. If the guard condition is true, the entire ruleset (selector and its properties) is included in the compiled CSS. This is useful for applying styles only under certain conditions, often based on variable values.
This feature is sometimes used in conjunction with the parent selector & to create conditional variations of a style.
Example
Section titled “Example”Let’s define a global theme variable and apply certain styles only if the theme is set to ‘dark’.
HTML (css_guards.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS CSS Guards</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="container"> <h1>Welcome to the Page</h1> <p>This content might look different based on the theme.</p> <button class="action-button">Click Me</button> </div></body></html>LESS (style.less):
style.less
Section titled “style.less”@theme: dark; // Possible values: 'light', 'dark'@enable-special-feature: true;
.container { padding: 20px; background-color: #f0f0f0; // Default light background color: #333; // Default dark text
// CSS Guard: Apply these styles only if @theme is 'dark' & when (@theme = dark) { background-color: #2c3e50; // Dark background for dark theme color: #ecf0f1; // Light text for dark theme
h1 { border-bottom: 1px solid #ecf0f1; } }}
.action-button when (@enable-special-feature = true) and (@theme = dark) { // This rule is output only if the special feature is enabled AND theme is dark background-color: #1abc9c; // Teal button for dark theme special feature color: white; border: none; padding: 10px 20px;}
// Another example: applying a style universally if a condition is metbody when (@theme = dark) { filter: invert(5%); // A subtle effect for dark theme on the whole body}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be (assuming @theme: dark; and @enable-special-feature: true; as set above):
style.css
Section titled “style.css”.container { padding: 20px; background-color: #f0f0f0; color: #333;}
/* Styles from the first CSS Guard because @theme = dark */.container { background-color: #2c3e50; color: #ecf0f1;}.container h1 { border-bottom: 1px solid #ecf0f1;}
/* Styles from the second CSS Guard because conditions met */.action-button { background-color: #1abc9c; color: white; border: none; padding: 10px 20px;}
/* Styles from the third CSS Guard */body { filter: invert(5%);}If, for instance, @theme was set to 'light' in style.less, then the guarded rulesets for .container (dark theme version), .action-button, and body would not appear in the compiled CSS.
Key Points:
Section titled “Key Points:”- CSS Guards control the output of an entire ruleset.
- They use the same
whenkeyword and conditional logic as mixin guards. - This is very useful for theming, feature flags, or any situation where a block of CSS should only apply if certain criteria (often based on LESS variables) are met.
Output
Section titled “Output”With @theme: dark; and @enable-special-feature: true;, the .container will have a dark background and light text, the h1 within it will have a light border, the .action-button will have its special dark theme styling, and the entire body will have a subtle invert filter. If the variables were different, these specific styles would be absent, demonstrating the conditional output controlled by CSS guards.
LESS - Loops
Section titled “LESS - Loops”LESS does not have a dedicated loop construct like for or while found in traditional programming languages. However, loops can be achieved by using recursive mixins combined with Guard Expressions and (optionally) Pattern Matching.
A recursive mixin is a mixin that calls itself. A guard condition is used to terminate the recursion when a certain condition is met (e.g., a counter reaches zero or a limit).
This technique is powerful for generating repetitive CSS patterns, such as grid columns, utility classes for spacing, or sequential theming elements.
Example: Generating Grid Helper Classes
Section titled “Example: Generating Grid Helper Classes”Let’s create a loop to generate a series of width utility classes (e.g., .width-25 for 25%, .width-50 for 50%).
HTML (loops_example.html) - to demonstrate usage:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Loops Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="width-25 item">25% Width</div> <div class="width-50 item">50% Width</div> <div class="width-75 item">75% Width</div> <div class="width-100 item">100% Width</div>
<div class="spacer-3 item">Spacer 3 (margin-top: 30px)</div></body></html>LESS (style.less):
style.less
Section titled “style.less”// Loop to generate width classes: .width-N where N is a percentage// Parameters: @iterations - total number of steps, @index - current step, @step-size - percentage per step.generate-width-classes(@iterations; @index: 1; @step-size: 25) when (@index =< @iterations) { @percentage-value: @index * @step-size; .width-@{percentage-value} { // Using variable interpolation for class name width: unit(@percentage-value, %); } // Recursive call for the next iteration .generate-width-classes(@iterations; (@index + 1); @step-size);}
// Call the loop to generate 4 classes (25%, 50%, 75%, 100%).generate-width-classes(4; 1; 25);
// Loop to generate spacer classes: .spacer-N.generate-spacers(@n; @i: 1; @base-margin: 10px) when (@i =< @n) { .spacer-@{i} { margin-top: @base-margin * @i; } .generate-spacers(@n; (@i + 1); @base-margin); // Recursive call}
// Generate 5 spacer classes (.spacer-1 to .spacer-5).generate-spacers(5);
// Basic styling for items in HTML for visibility.item { background-color: #f0f0f0; padding: 10px; margin-bottom: 5px; border: 1px solid #ccc;}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will contain:
style.css
Section titled “style.css”.width-25 { width: 25%;}.width-50 { width: 50%;}.width-75 { width: 75%;}.width-100 { width: 100%;}
.spacer-1 { margin-top: 10px;}.spacer-2 { margin-top: 20px;}.spacer-3 { margin-top: 30px;}.spacer-4 { margin-top: 40px;}.spacer-5 { margin-top: 50px;}
.item { background-color: #f0f0f0; padding: 10px; margin-bottom: 5px; border: 1px solid #ccc;}How it works:
Section titled “How it works:”- The
.generate-width-classesmixin takes parameters for the total number of iterations, current index, and step size. - The
when (@index =< @iterations)guard condition ensures the mixin only executes if the current index is within the desired range. - Inside the mixin, a class is generated (e.g.,
.width-25) with its corresponding CSS property (e.g.,width: 25%;). - The mixin then calls itself with an incremented index (
@index + 1), continuing the loop. - When
@indexexceeds@iterations, the guard condition becomes false, and the recursion stops.
Output
Section titled “Output”Opening loops_example.html in a browser will show the divs styled with the generated width and spacer classes. This demonstrates how LESS loops can automate the creation of utility class systems or other repetitive CSS patterns, saving time and reducing manual coding.
LESS - Merge
Section titled “LESS - Merge”Description
Section titled “Description”The Merge feature in LESS allows you to aggregate values for the same property from multiple declarations into a single, comma-separated or space-separated list. This is particularly useful for CSS properties that can accept multiple values, such as background, transform, box-shadow, or font-family.
To use the merge feature, you append a + (for comma-separated) or +_ (for space-separated) to the property name.
The following table describes the two types of merge operations:
| ID | Merge Type & Description | Common Use Cases |
|---|---|---|
| 1 | Comma (+)Appends the new property value to the existing list, separated by a comma. If the property doesn’t exist yet, it creates it. | Example for box-shadow or multiple backgrounds. |
| 2 | Space (+_)Appends the new property value to the existing list, separated by a space. If the property doesn’t exist yet, it creates it. | Example for transform functions or class lists (though class lists are usually handled in HTML). |
Example: Using Merge for box-shadow and transform
Section titled “Example: Using Merge for box-shadow and transform”HTML (merge_example.html):
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>LESS Merge Example</title> <link rel="stylesheet" type="text/css" href="style.css"></head><body> <div class="layered-shadow-box">Layered Shadows</div> <div class="transformed-element">Transformed</div></body></html>LESS (style.less):
style.less
Section titled “style.less”.base-effects() { box-shadow+: 0 0 5px rgba(0,0,0,0.2); // Comma-separated merge transform+_: scale(1); // Space-separated merge}
.extra-depth() { box-shadow+: 5px 5px 10px rgba(0,0,0,0.3) inset; // Add another shadow}
.rotate-effect() { transform+_: rotate(10deg); // Add a rotation}
.layered-shadow-box { .base-effects(); .extra-depth(); width: 200px; height: 100px; padding: 20px; background-color: #f0f0f0; margin: 20px;}
.transformed-element { .base-effects(); .rotate-effect(); transform+_: translateX(20px); // Add another transform width: 150px; height: 75px; padding: 15px; background-color: #e0e0e0; margin: 20px; text-align: center;}Compile style.less to style.css:
lessc style.less style.cssThe compiled style.css will be:
style.css
Section titled “style.css”.layered-shadow-box { box-shadow: 0 0 5px rgba(0, 0, 0, 0.2), 5px 5px 10px rgba(0, 0, 0, 0.3) inset; transform: scale(1); width: 200px; height: 100px; padding: 20px; background-color: #f0f0f0; margin: 20px;}
.transformed-element { transform: scale(1) rotate(10deg) translateX(20px); box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); width: 150px; height: 75px; padding: 15px; background-color: #e0e0e0; margin: 20px; text-align: center;}Key Points:
Section titled “Key Points:”property+: value;appendsvaluewith a comma.property+_: value;appendsvaluewith a space.- This feature is useful when building up complex multi-value properties incrementally, often through different mixins or style layers.
- It avoids overriding previous parts of a multi-value property when you only want to add to it.
Output
Section titled “Output”Opening merge_example.html in a browser will show:
- The
.layered-shadow-boxwill have both box shadows applied (one outer, one inset). - The
.transformed-elementwill have all three transforms applied sequentially (scaled, then rotated, then translated).
This demonstrates how the merge feature helps in composing complex CSS properties from multiple sources.