Note 1: This will always assume you are extending magento-blank
.
Note 2: <theme-dir>
is app/design/frontend/Vendor/theme/
The basics: Changing Base Variables
(for tl;dr, skip to conclusion)
Most guides I found only cover this step in theming with LESS, so I will try to keep this short. Magento 2 has a base set of Variables that define commonly used aspects of a theme. Colors, fonts, style of page titles, and so on are defined in these variables.
In <magento-root>/lib/web/css/source/lib/variables/
you will find a number of intuitively named LESS files. In each of these you can find values assigned to variables for many of the common elements in Magento 2.
To change any of these variables, simply create a file in <theme-dir>/web/css/source/_theme.less
.
Example:
@newPrimary: #1980fe;
@primary__color: @newPrimary;
@link__color: @newPrimary;
@link__visited__color: lighten(@link__color, 10%);
Technically, you can put any CSS or LESS in here, and it will successfully apply to your site (but don't do this). I will explain how this works in a moment.
Adding new CSS file
You can add new CSS to the head of all your template pages.
Create <theme-dir>/Magento_Theme/layout/default_head_blocks.xml
:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="css/myStyle.css" />
</head>
</page>
And then you create a file with your new CSS or LESS:
<theme-dir>/web/css/myStyle.less
. You can write LESS or CSS here.
Overriding Existing Styles
I found that Magento 2 LESS is not easily superseded by simply adding a new CSS file. And this is where I began to get lost, and I will explain how Magento 2 finds its LESS files.
By default, Magento 2 will includes (and ultimately falls back to) these files:
<Magento_Blank_theme_dir>/web/css/styles-m.less //Mobile Styles
<Magento_Blank_theme_dir>/web/css/styles-l.less //Desktop enhancements
<Magento_Blank_theme_dir>/web/css/print.less //Print Styles
These files include (import) other LESS files, which often include even more LESS files. And this is where other guides became unhelpful to me and I will explain what I found, as best I could.
The source/lib Magic
In styles-m.less
, there is the line: @import 'source/lib/_responsive.less';
. You'll notice that there is no source/lib
directory in the magento-blank
theme. It's evident that Magento 2 styles ultimately fall back to <magento-root>/lib/web/css/
. It's there you find source/lib/_responsive.less
.
The variables you use in _theme.less
are available because of a source/lib
file imported in the magento-blank
theme. Note: _theme.less
is an empty file in the default themes. Continue reading to learn why this is important to note.
"Automatically included" LESS files
A few guides I found insisted that you can create <theme-dir>/web/css/_styles.less
because Magento automatically looks for, and includes, that file. I found this to be bad advice.
If you create <theme-dir>/web/css/_styles.less
, your site will break. theme-frontend-blank/web/css/styles-m.less
imports _styles.less
, which in turn imports 3 more .less files, which each import even more .less files.
If you create a _styles.less
, you are overriding it. By overriding _styles.less
, you are overriding all the files it imports, and all the files those files import, and so on.
Note about _theme.less
: This file is empty in default themes, and therefore is safe to simply create and start adding to if you are basing your theme on a default. However, if you are extending a theme that already extends a default, chances are _theme.less
is already used. Creating that again will override it.
The magical @magento_import
In styles-m.less
you will see a couple of commented out lines:
//@magento_import 'source/_module.less'; // Theme modules
//@magento_import 'source/_widgets.less'; // Theme widgets
These lines not actually commented out! Magento 2 has special handling for lines that start with //@magento_import
. These lines can only be included in files at <theme-dir>/web/css
.
The lines above instruct Magento 2 to include any file within the theme that follows the given pattern. So the above lines will automatically include:
'<theme-dir>/Magento_Catalog/web/css/source/_widgets.less';
'<theme-dir>/Magento_Catalog/web/css/source/_module.less';
'<theme-dir>/Magento_Cms/web/css/source/_widgets.less';
'<theme-dir>/Magento_Cms/web/css/source/_module.less';
'<theme-dir>/Magento_Reports/web/css/source/_widgets.less';
'<theme-dir>/Magento_Reports/web/css/source/_module.less';
...and so on
Adding files names _widgets.less
and _module.less
will be automatically found and included, even if its a new module or a module that doesn't already have that file.
Be aware that Magento-Blank includes those files for most Modules, and if you want to use this method, you will need to copy-paste the originals (unless you're doing a complete re-write).
Conclusion
(Read: don't use _styles.less
).
When you're looking to change the CSS of an element, you want to do the best you can to find what file that style is defined in. Sometimes all you need to do is change a variable in _theme.less
. Most times, I suspect, you will simply need to copy-paste the _module.less
or _widgets.less
into your theme and make the changes.
If you've created a new module, or have new HTML elements, you may need to create a LESS file and have it separately included in the <head>
of every page.
In complicated cases, you may need to create a new @import
or @magento_import
. You want to find the lowest child that makes sense for what you're doing, so you're not copy-pasting a bunch of unnecessary files or adding confusing @import
lines that appear to lead nowhere.