# Widget DOM Optimization

Elementor Core Intermediate

Elementor widgets define their own markup in the render() method. However, Elementor wraps each widget in two <div> elements; the outer <div class="elementor-widget"> element, and the inner <div class="elementor-widget-container"> element. These additional wrappers allow Elementor to add additional styles like background, margins, borders, motion effects, etc.

Two wrappers for each widget increases the overall DOM size, reducing page performance. To overcome this, developers can use the has_widget_inner_wrapper() method to control the number of wrapper elements the widget has.

By switching to a single wrapper, a widget can reduce the DOM size and optimize its footprint on the page. However, existing widgets that rely on the inner .elementor-widget-container wrapping element to style widgets, can maintain backwards compatibility.

# Widget Markup

The current, unoptimized widget markup, includes two wrapping elements:

<div class="elementor-widget elementor-widget-{widget-name}">
	<div class="elementor-widget-container">
		...
	</div>
</div>
1
2
3
4
5

The optimized markup has only one wrapping element:

<div class="elementor-widget elementor-widget-{widget-name}">
	...
</div>
1
2
3

By default, Elementor uses the unoptimized markup for backwards compatibility.

# Examples

# Optimized Widget DOM

To reduce the DOM size, developers can use the has_widget_inner_wrapper() method in the widget class, as shown below:

<?php
class Elementor_Test_Widget extends \Elementor\Widget_Base {

	public function has_widget_inner_wrapper(): bool {
		return false;
	}

}
1
2
3
4
5
6
7
8

This implementation instructs Elementor to render the widget with a single <div> wrapper.

# Retaining Unoptimized Widget DOM (for BC)

Legacy widgets that rely on the .elementor-widget-container class can continue using the unoptimized DOM by setting the method to return true:




 
 
 









 














<?php
class Elementor_Test_Widget extends \Elementor\Widget_Base {

	public function has_widget_inner_wrapper(): bool {
		return true;
	}

	protected function register_controls(): void {

		$this->add_control(
			'color',
			[
				'label' => esc_html__( 'Color', 'textdomain' ),
				'type' => \Elementor\Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} > .elementor-widget-container h3' => 'color: {{VALUE}};',
				],
			]
		);
	}

	protected function render(): void {
		?>
		<h3>
			...
		</h3>
		<?php
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

This widget can't use the optimized DOM capability as it uses the inner .elementor-widget-container CSS class to style the widget. Therefore, setting has_widget_inner_wrapper() to true will make sure that Elementor doesn't remove the inner wrapper for this widget.

# Notes

Please note that retaining unoptimized DOM is a temporary solution that allows addon developers to maintain compatibility while updating their code. The ultimate goal is to transition all widgets to use the optimized single-wrapper structure.

Optimized DOM for widget wrappers is not only setting has_widget_inner_wrapper() to false, it requires removal of .elementor-widget-container from all files, including PHP, CSS and JS.