I am working on my first Magento 2 theme and all over the place, I find creators hard coding some of their home page blocks into themes. I've found a few examples of custom data in themes where they set this as their home page which is basically some hard coded sections and then styles in CSS for the home page:

    <div class="blocks-promo">
   <a href="{{store url=""}}collections/yoga-new.html" class="block-promo home-main">
       <img src="{{media url="wysiwyg/home/home-main.jpg"}}" alt="" />
       <span class="content bg-white">
           <span class="info">New Luma Yoga Collection</span>
           <strong class="title">Get fit and look fab in new seasonal styles</strong>
           <span class="action more button">Shop New Yoga</span>
   <div class="block-promo-wrapper block-promo-hp">
       <a href="{{store url=""}}promotions/pants-all.html" class="block-promo home-pants">
           <img src="{{media url="wysiwyg/home/home-pants.jpg"}}" alt="" />
           <span class="content">
               <strong class="title">20% OFF</strong>
               <span class="info">Luma pants when you shop today*</span>
               <span class="action more icon">Shop Pants</span>
       <a href="{{store url=""}}promotions/tees-all.html" class="block-promo home-t-shirts">
           <span class="image"><img src="{{media url="wysiwyg/home/home-t-shirts.png"}}" alt="" /></span>
           <span class="content">
               <strong class="title">Even more ways to mix and match</strong>
               <span class="info">Buy 3 Luma tees get a 4th free</span>
               <span class="action more icon">Shop Tees</span>
       <a href="{{store url=""}}collections/erin-recommends.html" class="block-promo home-erin">
           <img src="{{media url="wysiwyg/home/home-erin.jpg"}}" alt="" />
           <span class="content">
               <strong class="title">Take it from Erin</strong>
               <span class="info">Luma founder Erin Renny shares her favorites!</span>
               <span class="action more icon">Shop Erin Recommends</span>
       <a href="{{store url=""}}collections/performance-fabrics.html" class="block-promo home-performance">
           <img src="{{media url="wysiwyg/home/home-performance.jpg"}}" alt="" />
           <span class="content bg-white">
               <strong class="title">Science meets performance</strong>
               <span class="info">Wicking to raingear, Luma covers&nbsp;you</span>
               <span class="action more icon">Shop Performance</span>
       <a href="{{store url=""}}collections/eco-friendly.html" class="block-promo home-eco">
           <img src="{{media url="wysiwyg/home/home-eco.jpg"}}" alt="" />
           <span class="content bg-white">
               <strong class="title">Twice around, twice as nice</strong>
               <span class="info">Find conscientious, comfy clothing in our <nobr>eco-friendly</nobr> collection</span>
               <span class="action more icon">Shop Eco-Friendly</span>
<div class="content-heading">
   <h2 class="title">Hot Sellers</h2>
   <p class="info">Here is what`s trending on Luma right now</p>

My question is, as a Magento 2 developer (still learning though but can dig into the code and I understand the backend & templates), how can I create a more non-coder friendly home page/widget sections for my clients that will be going in and wanting to change out some images and text for each block on the home page?

I want to create something like this on my home page: enter image description here

But want to make sure my client can easily change out the image and text.

So I've gone through a bunch of articles and tried to learn more about widgets, blocks and the custom layout XML part of the cms pages.

So far I've only seen that I need to create a block and insert my image and text in there: enter image description here

Then format the <h1> and <image> with CSS, do this for each cta box I want and then add those to the home page layout update XML section of the cms home page by referencing the container and the blocks I've created:

<referenceContainer name="content.main">
   <block class="Magento\Cms\Block\Block" name="home-cta-one">
            <argument name="block_id" xsi:type="string">homepage_cta_one</argument>

<block class="Magento\Cms\Block\Block" name="home-cta-two">
            <argument name="block_id" xsi:type="string">homepage_cta_two</argument>

<block class="Magento\Cms\Block\Block" name="home-cta-three">
            <argument name="block_id" xsi:type="string">homepage_cta_three</argument>

Then say my client wants to go in an edit the text or image, they can at least change the image but what if they change the heading, or remove the image (then I'd like to have a default image) or any other formatting? There is too much risk of it not looking nice after a client goes in to edit.

Is there no better way to have blocks edited by a non-coder?

Is there a way to have a block where a user can choose an image and the text? Kind of how they choose any of the default block options?

I came across this article on how to create your own custom widget so I'd like to see if I could hard code it to ask for an image and a title & content text. Is that possible?

Or should I create my own module? I've read about this a bit but have no idea how to add fields or dynamic uploads for the image and title/content fields.

Please let me know if I'm explaining this correctly.


Without coding a custom mod, I would recommend placing each individual image and text in separate blocks that your clients can modify individually. That way they can change the images and text but not affect the styling and structure. However, it won't be able to deal with setting a default image if they accidentally delete an image.

I use this particular method so that my content/graphics people don't mess up the rest of the code.

You can either do the main block code on the home page or you can place the code into the main container block.

For example, I would create 7 blocks:

  • 1 main block that you call into the homepage and contains all of the structuring code that calls the title and images blocks
  • 3 blocks for the image titles
  • 3 blocks for the images themselves

Sample code:

<referenceContainer name="content.main">
    <block class="Magento\Cms\Block\Block" name="home-cta-one">
            <argument name="block_id" xsi:type="string">homepage_cta_one</argument>


<div class="container-fluid">
    <div class="row">
        <div class="col-xs-12 text-center">
            <span class="cts-title">{{block class="Magento\Cms\Block\Block" block_id="hp-cta-one-title"}}</span>
            <br />
            <span class="cts-img">{{block class="Magento\Cms\Block\Block" block_id="hp-cta-one-image"}}</span>

block samples are self-explanatory.

block: hp-cta-one-title

My Image Title

block: hp-cta-one-img

<img src="blahblah.png">


  • this can be simplified to 6 blocks by hard coding the main block structure code onto your homepage template in the cms (not .phtml)
  • I would set the max height and width on the image to retain the structure even if they were to upload an incorrectly sized image.
  • make each block name obvious and clear for your client so they immediately know which blocks to modify
  • This is great Blitzo. A crazy work around for the editable blocks in my themes but makes it so I can have my clients easily edit their home page. I'll start to implement this and see how it comes together. – kia4567 Sep 6 '17 at 16:36
  • @kia4567 good luck, im glad i could offer a potential solution. – Blitzo Sep 7 '17 at 5:23
  • I'm just now working on this and finishing it up but I need a but more info from you. I understand all of this except where I can call the structuring code that calls the title and images blocks for the main block? It doesn't work when I put that in the content box. I'd also like to see how I might go about just putting it all in the layout xml section of the homepage? As any css I put in there isn't valid. Thanks! – kia4567 Oct 18 '17 at 20:52
  • @kia4567 you need to call {{block class="Magento\Cms\Block\Block" block_id="hp-cta-one-title"}} and {{block class="Magento\Cms\Block\Block" block_id="hp-cta-one-image"}} in your main content page or another block. These will pull the blocks you created for the title and the image. You write your css code in the main content page or block around these calls. If you want to use the layout xml to add it to the homepage, you would have to do the css in the blocks themselves which will leave them vulnerable to being deleted or edited on accident by your client. – Blitzo Oct 20 '17 at 7:09
  • @kia4567 im sure you inputted the correct block_id but just double check it to make sure as at the very least they should show up in your main block / home page. (wherever you called it.) – Blitzo Oct 20 '17 at 7:11

I would recommend creating a basic theme options and having it run through a helper so easily called globally




<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="Vendor_Themeoptions::config_vendor_themeoptions" title="themeoptions"/>


<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_Themeoptions" setup_version="1.0.0"/>


<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">


<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
        <tab id="vendor" sortOrder="1" translate="label">
            <label>Vendor Name</label>
        <section id="themeoptions" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="1" translate="label">
            <label>Theme Options</label>
            <group id="general" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="1" translate="label">
                <field id="textfield" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="1" translate="label" type="text">
                    <label>Text Field</label>
                <field id="textarea" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="2" translate="label" type="textarea">
                    <label>Text Area</label>


 * @category Config
 * @package Davagordon_Brandpages
 * @author Dava Gordon <davagordonuk@gmail.com>

namespace Vendor\Themeoptions\Helper;

use \Magento\Framework\App\Helper\Context;
use \Magento\Framework\Exception\LocalizedException as IntegrationException;
use \Magento\Framework\Module\Dir\Reader as ModuleDirReader;

class Config extends \Magento\Framework\App\Helper\AbstractHelper

    protected $_config = null;
    protected $scopeConfig;
    protected $_moduleManager;

    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\Module\Manager $moduleManager
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->_moduleManager = $moduleManager;

    public function getThemeOption($config_path)
        return $this->scopeConfig->getValue(
  • Thanks for this Dava! It's what I want in functionality but was hoping to stick with the blocks section of the site so I can keep it all in one place. This is very handy to have though for when I need to configure something else for my theme though. :) – kia4567 Sep 6 '17 at 16:37
  • if you want to keep it in the same block just add \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, to the construct and call the xml setting you setup in your custom module – Dava Gordon Sep 6 '17 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.