The latest versions of Magento Commerce and Magento Open Source v2.4 are now available. More info: https://bit.ly/3h5P28D

8 Steps for Theme Development in Magento 2

Magento 2

In this blog post, know about the steps how to create a new theme based on the new Magento “Blank” theme. First, you would create a new folder in ‘app/design/frontend’ called, for example, ‘sparsh/mytheme’. Being a Magento development company – identifying the issues and requirements of Magento developers and project, in this section we are trying to share insights regarding the steps for developing Magento 2 theme.

Then create theme.xml file in this directory (it is suggestible to copy it from app/design/frontend/Magento/blank/theme.xml’), name your theme, and choose any parent. In this case, we can create a Magento 2’s blank theme. To create Magento 2 theme, below is the hierarchy of steps to be followed in chronological order –

  • Create theme folder
  • Define your theme
  • Composer package
  • registration.php file
  • Creating static folders and files
  • Configure catalog product images
  • Define the theme logo
  • Activate theme
Theme structure
app/design/frontend/sparsh/
├── mytheme/
│ ├── etc/
│ │ ├── view.xml
│ ├── web/
│ │ ├── images
│ │ │ ├── logo.svg
│ ├── registration.php
│ ├── theme.xml
│ ├── composer.json

As here you can see that ‘sparsh’ is the vendor name and ‘mytheme’ is the theme name.

Step I – Creating Theme Folder
  • Go to app/design/ frontend
  • Creating a vendor folder app/design/frontend/<vendor_name> for example app/design/frontend/sparsh
  • Create a theme folder app/design/frontend/<vendor_name>/<theme_name> for example app/design/frontend/sparsh/mytheme
Step II – Defining Theme

We created the theme folder, i.e. – ‘app/design/frontend/sparsh/mytheme’, create theme.xml file that define basic information about theme such as Name, Parent theme, Preview image, etc.

Include the below-mentioned code for defining the theme for Magento 2 application development –

	<!-- your theme's name -->
	My Theme
	<!-- the parent theme, in case your theme inherits from an existing theme -->
	Magento/blank
 
		<!-- the path to your theme's preview image -->
		media/mytheme.jpg
Step III – Composer Package

A composer is a tool for dependency management in PHP. It allows to declare the libraries your project depends on and it manages install/update. Add a composer.json file to the theme directory.

To know more about composer please refer https://getcomposer.org/

Include the below code for creating the compose package:

{
    "name": "sparsh/mytheme",
    "description": "This is custom theme which inherit Magento/blank theme",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/theme-frontend-blank": "100.0.*",
        "magento/framework": "100.0.*"
    },
    "type": "magento2-theme",
    "version": "100.0.1",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [
            "registration.php"
        ]
    }
}
Step IV – registration.php file

Add the following content to register the theme to Magento 2

	app/design/frontend/sparsh/mytheme/registration.php

Include the below code in the registration.php file:

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'frontend/sparsh/mytheme',
    __DIR__
);
Step V – Creating Static Folders & Files

Theme design contains many static files such as JavaScript, CSS, images and fonts. They are stored in separate folders in web of theme package. Here are the structure

app/design/
/sparsh/mytheme/
├── web/
│ ├── css/
│ │ ├── source/
│ ├── fonts/
│ ├── images/
│ ├── js/

When you update any files in ‘app/design/{area}/sparsh/mytheme/web’ folder, you have to execute below commands in command line otherwise there will be no any changes reflected on frontend side.

	php bin/magento setup:upgrade
	php bin/magento setup:static-content:deploy -f
	php bin/magento cache:flush
Step VI – Configure Catalogue Product Images

This is configuration file that contains magnifier, breakpoints, gallery, file, product image, etc. configuration details. This file is required for Magento theme but it is optional if exists in parent theme.

Go to app/design/{area}/sparsh/mytheme and create a folder etc and file view.xml. You can copy the view.xml file in parent theme such as Blank theme app/design/frontend/Magento/blank/etc/view.xml.

Include below code for configuring catalogue product images –

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 -->
 
<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
    <media>
        <images module="Magento_Catalog">
        	<image id="bundled_product_customization_page" type="thumbnail">
                <width>140</width>
                <height>140</height>
            </image>
            <image id="cart_cross_sell_products" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="cart_page_product_thumbnail" type="small_image">
                <width>110</width>
                <height>160</height>
            </image>
            <image id="category_page_grid" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="category_page_list" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="customer_account_my_tags_tag_view" type="small_image">
                <width>100</width>
                <height>100</height>
            </image>
            <image id="customer_account_product_review_page" type="image">
                <width>285</width>
                <height>285</height>
            </image>
            <image id="customer_shared_wishlist" type="small_image">
                <width>113</width>
                <height>113</height>
            </image>
            <image id="gift_messages_checkout_small_image" type="small_image">
                <width>75</width>
                <height>75</height>
            </image>
            <image id="gift_messages_checkout_thumbnail" type="thumbnail">
                <width>100</width>
                <height>100</height>
            </image>
            <image id="mini_cart_product_thumbnail" type="thumbnail">
                <width>78</width>
                <height>78</height>
            </image>
            <image id="new_products_content_widget_grid" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="new_products_content_widget_list" type="small_image">
                <width>270</width>
                <height>270</height>
            </image>
            <image id="new_products_images_only_widget" type="small_image">
                <width>78</width>
                <height>78</height>
            </image>
            <image id="product_base_image" type="image">
                <width>265</width>
                <height>265</height>
            </image>
            <image id="product_comparison_list" type="small_image">
                <width>140</width>
                <height>140</height>
            </image>
            <image id="product_page_image_large" type="image"/>
            <image id="product_page_image_large_no_frame" type="image">
                <frame>false</frame>
            </image>
            <image id="product_page_image_medium" type="image">
                <width>700</width>
                <height>700</height>
            </image>
            <image id="product_page_image_medium_no_frame" type="image">
                <width>700</width>
                <height>700</height>
                <frame>false</frame>
            </image>
            <image id="product_page_image_small" type="thumbnail">
                <width>90</width>
                <height>90</height>
            </image>
            <image id="product_page_main_image" type="image">
                <width>700</width>
                <height>700</height>
            </image>
            <image id="product_page_main_image_default" type="image">
                <width>700</width>
                <height>700</height>
            </image>
            <image id="product_page_more_views" type="thumbnail">
                <width>90</width>
                <height>90</height>
            </image>
            <image id="product_stock_alert_email_product_image" type="small_image">
                <width>76</width>
                <height>76</height>
            </image>
            <image id="product_small_image" type="small_image">
                <width>135</width>
                <height>135</height>
            </image>
            <image id="product_thumbnail_image" type="thumbnail">
                <width>75</width>
                <height>75</height>
            </image>
            <image id="recently_compared_products_grid_content_widget" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="recently_compared_products_images_names_widget" type="thumbnail">
                <width>75</width>
                <height>90</height>
            </image>
            <image id="recently_compared_products_images_only_widget" type="thumbnail">
                <width>76</width>
                <height>76</height>
            </image>
            <image id="recently_compared_products_list_content_widget" type="small_image">
                <width>270</width>
                <height>207</height>
            </image>
            <image id="recently_viewed_products_grid_content_widget" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
            <image id="recently_viewed_products_images_names_widget" type="small_image">
                <width>75</width>
                <height>90</height>
            </image>
            <image id="recently_viewed_products_images_only_widget" type="small_image">
                <width>76</width>
                <height>76</height>
            </image>
            <image id="recently_viewed_products_list_content_widget" type="small_image">
                <width>270</width>
                <height>270</height>
            </image>
            <image id="related_products_list" type="small_image">
                <width>140</width>
                <height>140</height>
            </image>
            <image id="review_page_product_image" type="small_image">
                <width>285</width>
                <height>285</height>
            </image>
            <image id="rss_thumbnail" type="thumbnail">
                <width>75</width>
                <height>75</height>
            </image>
            <image id="sendfriend_small_image" type="small_image">
                <width>75</width>
                <height>75</height>
            </image>
            <image id="shared_wishlist_email" type="small_image">
                <width>135</width>
                <height>135</height>
            </image>
            <image id="side_column_widget_product_thumbnail" type="thumbnail">
                <width>75</width>
                <height>90</height>
            </image>
            <image id="upsell_products_list" type="small_image">
                <width>140</width>
                <height>140</height>
            </image>
            <image id="wishlist_sidebar_block" type="thumbnail">
                <width>75</width>
                <height>90</height>
            </image>
            <image id="wishlist_small_image" type="small_image">
                <width>113</width>
                <height>113</height>
            </image>
            <image id="wishlist_thumbnail" type="small_image">
                <width>240</width>
                <height>300</height>
            </image>
        </images>
    </media>
    <vars module="Magento_Catalog">
 
        <!-- Gallery and magnifier theme settings. Start -->
        <var name="gallery">
            <var name="nav">thumbs</var> <!-- Gallery navigation style (false/thumbs/dots) -->
            <var name="loop">true</var> <!-- Gallery navigation loop (true/false) -->
            <var name="keyboard">true</var> <!-- Turn on/off keyboard arrows navigation (true/false) -->
            <var name="arrows">true</var> <!-- Turn on/off arrows on the sides preview (true/false) -->
            <var name="caption">false</var> <!-- Display alt text as image title (true/false) -->
            <var name="allowfullscreen">true</var> <!-- Turn on/off fullscreen (true/false) -->
            <var name="navdir">horizontal</var> <!-- Sliding direction of thumbnails (horizontal/vertical) -->
            <var name="navarrows">true</var> <!-- Turn on/off on the thumbs navigation sides arrows(true/false) -->
            <var name="navtype">slides</var> <!-- Sliding type of thumbnails (slides/thumbs) -->
            <var name="transition">
                <var name="effect">slide</var> <!-- Sets transition effect for slides changing (slide/crossfade/dissolve) -->
                <var name="duration">500</var> <!-- Sets transition duration in ms -->
            </var>
            <var name="fullscreen">
                <var name="nav">thumbs</var> <!-- Fullscreen navigation style (false/thumbs/dots) -->
                <var name="loop">true</var> <!-- Fullscreen navigation loop (true/false/null) -->
                <var name="arrows">false</var> <!-- Turn on/off arrows on the sides preview in fullscreen (true/false/null) -->
                <var name="caption">false</var> <!-- Display alt text as image title in fullscreen(true/false) -->
                <var name="navdir">horizontal</var> <!--Sliding direction of thumbnails in fullscreen(horizontal/vertical)  -->
                <var name="navtype">slides</var> <!-- Sliding type of thumbnails (slides/thumbs) -->
                <var name="transition">
                    <var name="effect">dissolve</var> <!-- Sets transition effect for slides changing (slide/crossfade/dissolve) -->
                    <var name="duration">500</var> <!-- Sets transition duration in ms -->
                </var>
            </var>
        </var>
 
        <var name="magnifier">
            <var name="fullscreenzoom">20</var>  <!-- Zoom for fullscreen (integer)-->
            <var name="top"></var> <!-- Top position of magnifier -->
            <var name="left"></var> <!-- Left position of magnifier -->
            <var name="width"></var> <!-- Width of magnifier block -->
            <var name="height"></var> <!-- Height of magnifier block -->
            <var name="eventType">hover</var> <!-- Action that atcivates zoom (hover/click) -->
            <var name="enabled">false</var> <!-- Turn on/off magnifier (true/false) -->
        </var>
 
        <var name="breakpoints">
            <var name="mobile">
                <var name="conditions">
                    <var name="max-width">767px</var>
                </var>
                <var name="options">
                    <var name="options">
                        <var name="nav">dots</var>
                    </var>
                </var>
            </var>
        </var>
        <!-- end. Gallery and magnifier theme settings -->
 
        <var name="product_small_image_sidebar_size">100</var>  <!-- Override for small product image -->
        <var name="product_base_image_size">275</var>           <!-- Override for base product image -->
        <var name="product_base_image_icon_size">48</var>       <!-- Base product image icon size -->
        <var name="product_list_image_size">166</var>           <!-- New Product image size used in product list -->
        <var name="product_zoom_image_size">370</var>           <!-- New Product image size used for zooming -->
        <var name="product_image_white_borders">0</var>
    </vars>
    <vars module="Magento_Bundle">
        <var name="product_summary_image_size">58</var>         <!-- New Product image size used for summary block-->
    </vars>
    <vars module="Js_Bundle">
        <var name="bundle_size">1MB</var>
    </vars>
    <exclude>
        <item type="file">Lib::jquery/jquery.min.js</item>
        <item type="file">Lib::jquery/jquery-ui-1.9.2.js</item>
        <item type="file">Lib::jquery/jquery.ba-hashchange.min.js</item>
        <item type="file">Lib::jquery/jquery.details.js</item>
        <item type="file">Lib::jquery/jquery.details.min.js</item>
        <item type="file">Lib::jquery/jquery.hoverIntent.js</item>
        <item type="file">Lib::jquery/colorpicker/js/colorpicker.js</item>
        <item type="file">Lib::requirejs/require.js</item>
        <item type="file">Lib::requirejs/text.js</item>
        <item type="file">Lib::date-format-normalizer.js</item>
        <item type="file">Lib::legacy-build.min.js</item>
        <item type="file">Lib::mage/captcha.js</item>
        <item type="file">Lib::mage/dropdown_old.js</item>
        <item type="file">Lib::mage/list.js</item>
        <item type="file">Lib::mage/loader_old.js</item>
        <item type="file">Lib::mage/webapi.js</item>
        <item type="file">Lib::mage/zoom.js</item>
        <item type="file">Lib::mage/translate-inline-vde.js</item>
        <item type="file">Lib::mage/requirejs/mixins.js</item>
        <item type="file">Lib::mage/requirejs/static.js</item>
        <item type="file">Magento_Customer::js/zxcvbn.js</item>
        <item type="file">Magento_Catalog::js/zoom.js</item>
        <item type="file">Magento_Ui::js/lib/step-wizard.js</item>
        <item type="file">Magento_Ui::js/form/element/ui-select.js</item>
        <item type="file">Magento_Ui::js/form/element/file-uploader.js</item>
        <item type="file">Magento_Ui::js/form/components/insert.js</item>
        <item type="file">Magento_Ui::js/form/components/insert-listing.js</item>
        <item type="directory">Magento_Ui::js/timeline</item>
        <item type="directory">Magento_Ui::js/grid</item>
        <item type="directory">Magento_Ui::js/dynamic-rows</item>
        <item type="directory">Magento_Ui::templates/timeline</item>
        <item type="directory">Magento_Ui::templates/grid</item>
        <item type="directory">Magento_Ui::templates/dynamic-rows</item>
        <item type="directory">Magento_Swagger::swagger-ui</item>
        <item type="directory">Lib::modernizr</item>
        <item type="directory">Lib::tiny_mce</item>
        <item type="directory">Lib::varien</item>
        <item type="directory">Lib::jquery/editableMultiselect</item>
        <item type="directory">Lib::jquery/jstree</item>
        <item type="directory">Lib::jquery/fileUploader</item>
        <item type="directory">Lib::css</item>
        <item type="directory">Lib::lib</item>
        <item type="directory">Lib::extjs</item>
        <item type="directory">Lib::prototype</item>
        <item type="directory">Lib::scriptaculous</item>
        <item type="directory">Lib::less</item>
        <item type="directory">Lib::mage/adminhtml</item>
        <item type="directory">Lib::mage/backend</item>
    </exclude>
</view>
Step VII – Defining Theme Logo

In Magento 2 default uses/{area}/web/images/logo.svg, in your theme, you can change to different file format such as png, jpg but you have to declare it. You can define theme logo at below path,

<theme_dir>/Magento_Theme/layout/default.xml

Include the below mentioned code to define the theme logo –

<?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">
    <body>
        <referenceBlock name="logo">
            <arguments>
                <argument name="logo_file" xsi:type="string">images/logo.png</argument>
                <argument name="logo_img_width" xsi:type="number">50</argument>
                <argument name="logo_img_height" xsi:type="number">50</argument>
            </arguments>
        </referenceBlock>
 
    </body>
</page>
Step VIII – Activate Theme

After following all above steps you can see your developed theme preview from admin login Content => Theme. Here you can see your developed theme is listed.

Magento Developed Theme

To activate your developed theme goto Content => Configuration => Edit => Select your daveloped theme name and click on Save Configuration.

Content Configuration

Now in Applied Theme drop down select your developed theme name and click on Save Configuration button.

Save Configuration
CSS & LESS

One of the most advantages of LESS is that it simplifies the management of a large volume of CSS styles and makes CSS more flexible. Moreover, this stylesheet language adds multiple dynamic features to CSS; it introduces variables, nesting, operators, functions, and mixins.

To know more about less CSS please refer http://lesscss.org/

In Magento, you can add external CSS by layout overriding. For example, here any Magento developers can override Magento theme default_head_blocks.xml layout file and add ‘common.css’ as external CSS. Content of default_head_blocks.xml file would be:

<?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/common.css"/>
    </head>
</page>

In Magento 2 we need to write CSS in less format and after that Magento 2 compiler converts it into CSS format. We have defined external CSS ‘common.css’ in default_head_blocks.xml, it is located at below path.

pub/static/frontend/sparsh//en_US/css/common.css

common.css file will be automatically generated at above path. We don’t need to write anything in common.css

We need to add the common.less file at below path and write CSS in less format.

App/design/frontend/sparsh//web/css/.less

Run the below command in command line to apply external added css changes,

php bin/magento cache:flush
php bin/magento setup:static-content:deploy -f

Tell us about your project

Hire dedicated Magento developer from the vast and talented pool of resources.