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:


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:


add_action('elementor/element/call-to-action/button_style/after_section_start', function ($instance) {
      '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:


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:


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.


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


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.



de către



0 răspunsuri la „Customizing Elementor’s default widgets”

  1. Avatar Tanner

    I spent quite a long time trying to get it to work with before_render_content, then finding out it’s not possible. Since you’re using Zend to traverse the content, can you provide a tutorial to install Zend?

    1. Avatar Ionuț Staicu
      Ionuț Staicu

      Hey Tanner. The only way I can recommend is to use

      composer require zendframework/zend-dom

      Other install methods can lead to various issues (e.g. not installing the right dependencies).

Lasă un răspuns

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

Acest site folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.

windows apple dropbox facebook twitter