Skip to main content
This guide covers how to customize the OroCommerce storefront look and feel using themes. Back-office design customization is covered separately in the Back-Office Customization guide.
The OroCommerce storefront does not use the SPA approach (for SEO optimization), but shares the same JavaScript framework as the back-office. Storefront themes are built on the OroLayouts framework, which is more flexible than the placeholder-based approach used in back-office themes. Themes cannot be shared between storefront and back-office.

Topics

Quick Start

Step-by-step guide to building a custom storefront theme with basic styles and layout customizations.

Themes

Define, enable, and activate storefront themes. Reference for all theme.yml configuration options.

Stylesheets (SCSS)

Manage and customize SCSS stylesheets within storefront themes.

JavaScript

JavaScript integration in the OroCommerce storefront.

Layout

The OroLayouts framework: layout blocks, layout updates, and page structure control.

Theme Configuration

Configure theme options exposed in the back-office Theme Configuration UI.

Templates (Twig)

Twig block themes and template overriding in storefront themes.

Image Resizing and Watermarks

Configure image resizing and watermarks for storefront product images.

Customization How-To Guides

Practical recipes: replace logos, change color schemes, modify fonts, and more.

Render Cache

OroCommerce render caching for storefront performance.

Frontend Developer Tools

Debugging tools and the Symfony Profiler layout panel.

Preload Critical Assets

Preload critical CSS and JavaScript to improve page load performance.

Subresource Integrity (SRI)

Enable SRI hashes for stylesheet and script tags.

Icons (SVG)

Use and customize SVG icon sets in storefront themes.

Optimize Assets Build

Techniques for speeding up the asset build process during development.

Quick Start: Build a Custom Theme

This section summarizes the steps to create a new storefront theme.
1

Create a new theme bundle

Create a bundle to hold your theme assets and configuration:
mkdir -p src/Oro/Bundle/DemoThemeBundle && \
touch src/Oro/Bundle/DemoThemeBundle/OroDemoThemeBundle.php
<?php

namespace Oro\Bundle\DemoThemeBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class OroDemoThemeBundle extends Bundle
{
}
2

Register the bundle

Create Resources/config/oro/bundles.yml and register the bundle with a priority:
bundles:
    - { name: Oro\Bundle\DemoThemeBundle\OroDemoThemeBundle, priority: 1024 }
3

Define the theme

Create Resources/views/layouts/demo/theme.yml to define the theme:
label: Demo Theme
description: 'Demo Theme description.'
groups: [ commerce ]
parent: default
icon: bundles/orofrontend/default/images/favicon.ico
favicons_path: bundles/orofrontend/default/favicons/
logo: bundles/orofrontend/default/images/logo/demob2b-logo.svg
logo_small: bundles/orofrontend/default/images/logo/demob2b-logo-small.svg
rtl_support: true
svg_icons_support: true
4

Enable the theme

Add the theme to config/config.yml:
oro_layout:
   enabled_themes:
      - default
      - demo
Then clear and warm the cache:
php bin/console cache:clear --env=prod && bin/console cache:warmup --env=prod
5

Activate the theme in the back-office

Navigate to System > Theme Configurations, create a new theme configuration for your theme, then go to System > Configuration > Commerce > Design > Theme to activate it.

Theme Directory Structure

A typical storefront theme bundle has the following layout:
DemoBundle/
  Resources/
    public/                  # Copied to public/bundles/ during assets:install
      demo/
        scss/
        js/
        images/
    views/
      layouts/
        demo/                # Theme name (theme ID)
          theme.yml          # Theme definition
          config/
            assets.yml       # SCSS configuration
            jsmodules.yml    # JS modules configuration
          layout_update1.yml # Layout updates for all pages
          oro_product_frontend_product_view/
            product.yml      # Layout updates for a specific route

Theme Configuration Options

All options accepted in theme.yml:
OptionRequiredInheritsDescription
labelyesnoLabel shown in the theme management UI
descriptionnonoDescription shown in the theme selection UI
parentnonoParent theme identifier
groupsnonoGroup names (use commerce for OroCommerce)
logononoLogo displayed in the UI
logo_smallnonoSmall logo for narrow screens and burger menus
rtl_supportnonoEnables RTL support and generates *.rtl.css files
iconnonoFavicon displayed in the UI
favicons_pathnonoPath to favicon assets
svg_icons_supportnoyesEnables SVG icon set support
pdf_documentnoyesTwig templates for PDF document generation
fontsnonoFont definitions for the theme
configurationnonoConfigurable theme options exposed in the back-office

Add Stylesheets

Create SCSS files in Resources/public/ and register them in the theme’s config/assets.yml:
# Resources/views/layouts/demo/config/assets.yml
critical_css:
    inputs:
        - 'bundles/orodemotheme/demo/scss/settings/global-settings.scss'
        - 'bundles/orodemotheme/demo/scss/variables/base-config.scss'
    output: 'css/critical.css'
    auto_rtl_inputs:
        - 'bundles/oro*/**'

styles:
    inputs:
        - 'bundles/orodemotheme/demo/scss/settings/global-settings.scss'
        - 'bundles/orodemotheme/demo/scss/variables/base-config.scss'
    output: 'css/styles.css'
    auto_rtl_inputs:
        - 'bundles/oro*/**'
Build the theme:
npm run build -- --env theme=demo

Modify Page Structure with Layout Updates

Layouts define the tree structure of every page. Use layout update YAML actions to add, remove, or move blocks:
# DemoThemeBundle/Resources/views/layouts/demo/slogan.yml
layout:
     actions:
         - '@add':
             id: slogan
             parentId: page_main_content
             siblingId: page_main_header
             prepend: false
             blockType: text
             options:
                 text: Website Slogan!
To target a specific page route, place the layout update file in a folder named after the route:
# layouts/demo/oro_product_frontend_product_view/product.yml
layout:
    actions:
        - '@move':
              id: product_view_primary_container
              parentId: page_title_container
        - '@remove':
              id: product_view_related_products_container
        - '@setOption':
              id: product_view_attribute_group_general_attribute_text_sku
              optionName: attr.class
              optionValue: page-title

Build docs developers (and LLMs) love