This example shows two files: options.less
and bootstrap.less
.
options.less
The first, options.less, contains the global options directive - which defines the global options for a project. In the @options
statement you will see some user-defined properties (yes, user-defined! lol), which give the user the ability to organize their import statements and maintain complete control over how they are compiled.
bootstrap.less
The second file is bootstrap.less
, the commonly used "less manifest" from the Twitter Bootstrap project, the most commonly used Less library and so a good example for this use case.
One of the negatives I hear most often about Bootstrap is the "size of the library". Many folks complain that you can't just use it for any small project because it's overkill. I'll demonstrate why that's incorrect here using our user-defined options.
I think some will argue that this belongs in build systems, I personally disagree. I think build system could do so much more with less if they could leverage this as a native less feature. Most client-side templating engines use contexts to control how templates are compiled, allowing build systems to use configuration data to manipulate variables and change contexts. This give complete control.
@options {
compress: true; /* minify */
concatenate: false; /* output one big file */
process: true; /* treat all files as LESS */
...
/* user-defined properties, or "contexts" */
core: true;
normalize: true;
grid: true;
basecss: true;
common: true;
buttons: false; /* files in this context will be ignored */
navigation: false; /* files in this context will be ignored */
zindex: false; /* files in this context will be ignored */
misc: false; /* files in this context will be ignored */
utility: true;
responsive: false; /* files in this context will be ignored */
/* some experimental styles */
experimental: true;
}
//
// Bootstrap
// -------------------------------------------------
// Core variables and mixins
@options (context: core) {
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
@import "mixins.less";
}
// Reset
@options (context: normalize) {
@import "normalize.less";
}
// Grid system and page structure
@options (context: grid) {
@import "scaffolding.less";
@import "grid.less";
}
// Base CSS
@options (context: basecss) {
@import "type.less";
@import "code.less";
@import "forms.less";
@import "tables.less";
}
// Components: common
@options (context: common) {
@import "glyphicons.less";
@import "dropdowns.less";
@import "wells.less";
@import "component-animations.less";
@import "close.less";
}
// Components: Buttons & Alerts
@options (context: buttons) {
@import "buttons.less";
@import "button-groups.less";
@import "alerts.less";
}
// Components: Nav
@options (context: navigation) {
@import "navs.less";
@import "navbar.less";
@import "breadcrumbs.less";
@import "pagination.less";
@import "pager.less";
}
// Components: Popovers
@options (context: zindex) {
@import "modals.less";
@import "tooltip.less";
@import "popovers.less";
}
// Components: Misc
@options (context: misc) {
@import "thumbnails.less";
@import "media.less";
@import "badges.less";
@import "progress-bars.less";
@import "accordion.less";
@import "carousel.less";
@import "jumbotron.less";
}
// Experimental custom styles
@options (context: experimental) {
@import "experimental.less"; // my custom stuff
}
// Utility classes
@options (context: utilities) {
@import "utilities.less"; // Has to be last to override when necessary
}
// Responsive
// -------------------------------------------------
// Responsive utility classes
@options (context: responsive) {
@import "responsive-utilities.less";
// Media queries
// ------------------
// Large desktops
@import "responsive-1200px-min.less";
// Tablets to regular desktops
@import "responsive-768px-979px.less";
// Phones to portrait tablets and narrow desktops
@import "responsive-767px-max.less";
// Responsive navbar
// From 979px and below, show a button to toggle navbar contents
@import "responsive-navbar.less";
}
Or, here is the same concept with a different approach/syntax (we could approach this lots of different ways, but hopefully I can get the operative point across, which is how easy this would make it to control all of the import statements from the options directive. Think about how this would change working with libs.)
@options {
compress: true; /* minify */
concatenate: false; /* output one big file */
process: true; /* treat all files as LESS */
...
/* user-defined properties, or "contexts" */
core: true;
reset: true;
grid: true;
basecss: true;
common: true;
buttons: false; /* ignored */
navigation: false; /* ignored */
zindex: false; /* ignored */
misc: false; /* ignored */
utility: true;
responsive: false; /* ignored */
/* some experimental styles */
experimental: true;
}
//
// Bootstrap
// -------------------------------------------------
@import (compress: true) {
core: "variables.less", "mixins.less";
reset: "normalize.less";
grid: "scaffolding.less", "grid.less";
basecss: "type.less","code.less", "forms.less", "tables.less";
common: "glyphicons.less", "dropdowns.less", "wells.less", "component-animations.less", "close.less";
buttons: "buttons.less", "button-groups.less", "alerts.less";
navigation: "navs.less", "navbar.less", "breadcrumbs.less", "pagination.less", "pager.less";
zindex: "modals.less", "tooltip.less", "popovers.less";
misc: "thumbnails.less", "media.less", "badges.less", "progress-bars.less", "accordion.less", "carousel.less", "jumbotron.less";
/* some experimental styles */
experimental: "experimental.less";
utility: "utilities.less";
responsive: "responsive-utilities.less", "responsive-1200px-min.less", "responsive-768px-979px.less", "responsive-767px-max.less", "responsive-navbar.less";
}