Customizing Elementor’s default widgets

If you’re using Elementor for client work, probably you’ll hit some limits soon enough. Like, for example, you can’t customize buttons aspects on all widgets. Although is never documented, it is possible and I’ll show you a way of doing this. The example? Call to action widget (available only on Elementor Pro).

By default, you can only customize some basic stuff and if you want to reuse same style again, you’re kind of screwed.

This is a bit of nonsense, because Elementor already has a button component that you can use it outside of this widget! Why can’t I just use it here?

So, in order to make it work, we will need a couple of things. Elementor uses two ways of rendering content: one is JS based and is used only when you edit the page, the other one is PHP based and is used… everywhere else.

Side note: Customizing existing controls

In case you wonder, yes, you can customize existing controls. E.g. here is how you can add a custom button style:

<?php

add_action('elementor/element/button/section_button/before_section_end', function ($instance) {
  $controls = $instance->get_controls();
  $controls['button_type']['options'] += [
    'hallow' => __('Hallow'),
  ];
  $instance->update_control('button_type', $controls['button_type']);
});

(obviously enough, you need to take care of adding extra CSS!)

Extra Control

The first thing you need to do is to add an extra control to the button style section, within the Call to Action widget:

<?php

add_action('elementor/element/call-to-action/button_style/after_section_start', function ($instance) {
  $instance->add_control(
    'ntz_button_type',
    [
      'label' => __('Button Type', 'elementor'),
      'type' => \Elementor\Controls_Manager::SELECT,
      'default' => '',
      'options' => [
        '' => __('Default', 'elementor'),
        'info' => __('Info', 'elementor'),
        'success' => __('Success', 'elementor'),
        'warning' => __('Warning', 'elementor'),
        'danger' => __('Danger', 'elementor'),
      ],
    ]
  );
});

After you do this, the above image will be slightly different:

Sweet!

Unfortunately there is no way of extracting default button styles, so we need to duplicate the default styling options. I’ve created a PR, but now we’re playing the waiting game…

JS Template

As I said, the editor render is 100% javascript and is a huge, 130+ lines method. The best way I found of dealing with this is using search & replace:

<?php

add_filter('elementor/widget/print_template', function ($tpl, $instance) {
  if ($instance->get_name() !== 'call-to-action') {
    return $tpl;
  }

  $buttonWrapperClass = 'elementor-element elementor-button-{{ settings.ntz_button_type }}';

  $tpl = str_replace('<{{ buttonTag }}', "<div class='elementor-widget-button {$buttonWrapperClass}'><div class='elementor-button'><{{ buttonTag }}", $tpl);
  $tpl = str_replace('</{{ buttonTag }}>', '</{{ buttonTag }}></div><div>', $tpl);
  
  return $tpl;
}, 10, 2);

Only by adding these few lines, you’ll be able to see the changes as you make it (but forget not, you actually need to make a change in order to have this template rendered!)

PHP Template

Here is where the weird kicks in. Since regex on html is usually a bad idea, I preferred to use Zend’s DOM package. If you’re using Composer (and you are, right?), that’s only a matter of composer require zendframework/zend-dom.

<?php

add_filter('elementor/widget/render_content', function ($content, $instance) {
  if ($instance->get_name() !== 'call-to-action') {
    return $content;
  }

  $dom = new \Zend\Dom\Query($content);
  $buttons = $dom->execute('.elementor-cta__button-wrapper');

  foreach ($buttons as $button) {
    $buttonTag = $button->ownerDocument->saveXML($button);
    $className = 'elementor-element elementor-button-' . $instance->get_settings('ntz_button_type');

    $content = str_replace(
      $buttonTag,
      sprintf('<div class="elementor-widget-button %s"><div class="elementor-button">%s</div></div>', $className, $buttonTag),
      $content
    );
  }
  
  return $content;
}, 10, 2);

Done

And that’s about all. You’ll have the button styling, ready to use, outside of a button widget! How cool is that? 😀

Extra notes

There are few things you should consider though:

  • Adding custom styles to the button dropdown will not show them into the dropdown we added here;
  • You need to tweak some CSS rules in order to have this look really good.

Publicat de

Ionuț Staicu

este frontend & WordPress developer, iar în timpul liber administrează DevForum.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *