Magento 2(M2) is vastly different in its structure than Magento 1.x. When you first crack the surface of this new platform, it can seem a little daunting. You might be asking yourself “Where do I start?”, at least I did. Once you dive into M2 you will see, not only how much more organized the file structure is, but also the improvement in ability to override content/layout XML and extend JS without having to load all its dependencies. Some other improvements include the addition of HTML5 tags built into the templates, the intro of CSS3, and the use of LESS over Sass (as well as a built-in LESS preprocessor). Notably, M2 has also switched from Prototype to a jQuery library. If you have ever worked with prototype before, this is a welcomed change!
With all that being said, there are not too many resources out there for us Frontend Dev’s. I have mostly relied on the Magento 2 development docs and trial and error. My goal here is to create a well explained process of theming in Magento 2. This will be a 3 part blog series to guide you through setting up your M2 install, creating a child theme, and customizing it (and I mean really customizing it).
Installing Magento 2
As you may be aware, there are a few different ways to install Magento 2. Please refer to the Magento installation guide first if this is your first M2 install. It is also very important to check whether your server meets the minimal Magento 2 requirements:
Apache: 2.2 or 2.4
PHP: 5.5.x or 5.6.x
I suggest using composer when installing Magento 2. Composer enables you to manage the Magento components and their dependencies. Here are some resources to walk you through your install:
There are number of differences and improvements to theme structure and the fallback system in Magento 2. The fallback system in M2 works in a similar way to Magento 1.x, but now has the added advantage of being able to create unlimited parent themes. In this tutorial, we will be creating a new theme based on M2’s ‘Blank’ theme.
M2 fallback system explained
In M2, the fallback system is defined by the theme.xml file. It tells your theme which parent to fallback on. The great thing in M2 is we can declare our own fallback system within our themes.
Magento 2 has a different folder naming convention for themes than Magento 1. In Magento 1, you would create your theme within app/design/frontend/<package>/<theme>. For Magento 2, you create your theme in app/design/frontend/<vendor>/<theme>. Lets take a closer look at the pieces of the new naming convention, and therefore how you should chose your folder names:
Vendor: This is the name of the individual or company developing the code for this theme.
Theme: This can be any name that you would like to call your theme.
Above, indicates a new vendor folder with theme ‘default’. This is based off M2’s ‘Blank’ theme. There can be multiple themes and store views under one vendor. I chose default as the base theme so when we create multiple store views the global assets for the stores will remain here.
Above, indicates a new vendor folder, ‘Myothercompany’, using ‘Mycompany’ as its parent theme. In this theme you can override global assets from ‘Mycompany/default’, otherwise they will fallback in hierarchy respectively.
In Magento 1.x, the last place Magento would look in it’s fallback system is base/default. In M2, base/default is the module. Modules are now all encapsulated. This means, instead of having all your site wide assets, js, templates, blocks and controllers in different locations, they are now organized within the module. The location of the default versions of each module can be found in app/code/Magento. The folders in the image below represent the default modules in Magento 2.
Now, let’s take a look at the structure of one of a default modules. In this case we are looking at the layered navigation module:
Here, you see that the template and layout xml files now exist in view/frontend of the module. If you want to override/extend the modules’ templates, styling or JS, you will need to create an equivalent module folder in your theme that matches the path(s) of the file(s) you wish to override/extend. If we were extending the layered navigation module, you would create a folder named Magento_LayeredNavigation and place it in your theme folder eg. <vendor>/<theme>/Magento_LayeredNavigation.
Magento_LayeredNavigation is an example of a <Namespace_Module>. Magento being the namespace and the module being LayeredNavigation separated by an underscore. If you were extending the checkout module, it would be Magento_Checkout. The process of extending <Namespace_Module>(s) will be covered in detail later in this blog series.
*Note that you can only override the contents of the view/frontend portion of the module within your theme. If you need to override Controllers and Blocks, this is done in a different location in the file structure and will not be covered in this blog series.
Creating a New Magento theme
Creating theme.xml to declare fallback system
Navigate to app/design/frontend
Create a new vendor folder in app/design/frontend/ and name it ‘Mycompany’ eg. app/design/frontend/Mycompany
Create a theme folder in within your new vendor folder named ‘default’ eg. app/design/frontend/MyCompany/default
This is what your theme structure should resemble:
Next, create a theme.xml file in this directory. Copy it directly from app/design/frontend/Magento/blank/theme.xml. We are now going to declare our theme, ‘Mycompany’ and choose the appropriate parent. In this case, we are choosing /Magento/blank.
In our case, copy the composer.json file to the theme directory app/design/frontend/Mycompany/default and edit the orange text as follow:
You can find details about the Composer integration in the Magento system here.
Registering our theme
The next step is to register our theme. In your theme directory add a registration.php file. I suggest copying the file from app/design/frontend/Magento/blank/registration.php and editing. Your file should look like this:
Next, we will create _theme.less and folder structure where we will extend/override our theme LESS files. Create app\design\frontend\<Vendor>\<theme>\web\css\source\_theme.less. In this case our _theme.less will be in app\design\frontend\Mytheme\default\web\css\source\_theme.less
Installing and configuring Grunt
Magento has built-in Grunt tasks configured, but there are still several prerequisite steps you need to take to be able to use it. Make sure that you set your Magento application to developer in your .htaccess.
SetEnv MAGE_MODE developer
You’ll be running Magento in developer mode. In developer mode, Magento’s much more strict about PHP errors, will display raw exceptions, and make it easier to develop modules.
Next, install node.js to globally on your machine.
Install Grunt CLI tool globally. To do this, run the following in a command line:
npm install -g grunt-cli
Install (or refresh) the node.js project dependency, including Grunt, for your Magento instance. To do this, run the following in a command line:
Add your theme to Grunt configuration. To do this, in the dev/tools/grunt/configs/themes.js file, add your theme to module.exports as follows:
In the .../web/images general theme related static files are stored. For example, a theme logo is stored in .../web/images. It is likely that your theme will also contain module-specific files, which are stored in the corresponding sub-directories, like .../<Namespace_Module>/web/css and similar.
Declaring theme logo
To declare a theme logo, add an extending default.xml to /Mycompany/de/Magento_Theme/layout/default.xml.
For example, if your logo file is my_logo.png sized 300x300px, you need to declare it as follows:
Declaring the logo size is optional.
Your theme directory structure
At this point your theme file structure looks as follows: