How to integrate the new breakpoints with Elementor

This tutorial was created to help some developers who have had difficulty finding somewhat exhaustive documentation to migrate their codes to the new breakpoint features implemented since version 3.2.0 of Elementor.

Overview of breakpoints for Elementor responsive controls

You know how to activate the new breakpoints otherwise consult the official documentation or this help.
You will find constants and methods in ‘Elementor/core/breakpoints/manager.php‘.


Elementor guarantees that when the “Additional Custom Breakpoints” experiment is off, the system works exactly as it did before.

You can therefore migrate to the new features whether the breakpoints are active or not.

The following code does not take into account Laptop and Widescreen but you can extend the examples easily.

 

Pay attention: the following codes have not been tested with the pro version of Elementor.

Easiest way to implement the breakpoints

First the ‘desktop_default‘ attribute nolonger exists. It is replaced by ‘default‘.
As you can see you need to specify the default value of each of the breakpoints and the ‘prefix_class‘ (Line 20) argument to apply the corresponding CSS.

/**
 * Apply breakpoints
 */
$this->add_responsive_control('stm_setting_column',
	[
	    'label'   => __('Nombre de colonnes', 'eac-components'),
		'type'    => Controls_Manager::SELECT,
		'default' => '3',               // Old 'desktop_default'
		'tablet_default' => '2',
		'mobile_default' => '1',
		'tablet_extra_default' => '3',
		'mobile_extra_default' => '2',
		'options'       => [
			'1'    => '1',
			'2'    => '2',
			'3'    => '3',
			'4'    => '4',
			'5'    => '5',
		],
		'prefix_class' => 'responsive%s-',
	]
);

Using inherited responsive values

Mr. Elementor tells us “Elementor uses a concept of cascading through breakpoints, which means changes cascade down and not up”.
You can therefore define a default value which will be inherited by other devices.

 

The default value clearly identifies what it means. All bellow devices (Laptop … Mobile) inherit the default value.
If you change the value of the device ‘Laptop’, all bellow devices will inherit the value of ‘Laptop’.
And if you change the default value of ‘Desktop’, it will not affect bellow devices.

‘Widescreen’ device has a particular behavior in the sense that no other device inherits its value.

 

There is a issue, the default value is well inherited by the other devices but the placeholder is not valued especially the controls that are included in a repeater.

$this->add_responsive_control('al_wrapper_margin',
	[
		'label' => __('Marge entre les items', 'eac-components'),
		'type'  => Controls_Manager::SLIDER,
		'size_units' => ['px'],
		'default' => ['size' => 6, 'unit' => 'px'],
		'range' => ['px' => ['min' => 0, 'max' => 20, 'step' => 1]],
		'selectors' => ['{{WRAPPER}} .al-post__wrapper-inner' => 'margin: {{SIZE}}{{UNIT}};'],
	]
);

Advanced way to implement breakpoints

First we import the necessary classes (Line 1, 2) and then we get the active breakpoints (Line 7).

use Elementor\Core\Breakpoints\Manager as Breakpoints_manager;
use Elementor\Plugin; // use ElementorPro\Plugin;
...
protected function register_controls() {
        
	// Retrieve all active breakpoints
    $active_breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();

We loop on the active breakpoints and we assign the default values for each of them.
We have to add the argument ‘device_args‘ with the array of values (Line 23).

// Set default values for all active breakpoints.
$columns_device_args = [];

foreach($active_breakpoints as $breakpoint_name => $breakpoint_instance) {
    // Exclude Laptop & Widescreen
	if(!in_array($breakpoint_name, [Breakpoints_manager::BREAKPOINT_KEY_WIDESCREEN, Breakpoints_manager::BREAKPOINT_KEY_LAPTOP])) {
	    if($breakpoint_name === Breakpoints_manager::BREAKPOINT_KEY_MOBILE) {
			$columns_device_args[$breakpoint_name] = ['default' => '1'];
		}  else if($breakpoint_name === Breakpoints_manager::BREAKPOINT_KEY_MOBILE_EXTRA) {
			$columns_device_args[$breakpoint_name] = ['default' => '2'];
		} else {
			$columns_device_args[$breakpoint_name] = ['default' => '3'];
		}
	}
}
			
/** Apply the default values of the breakpoints to the control */
$this->add_responsive_control('al_columns',
	[
	    'label'   => __('Nombre de colonnes', 'eac-components'),
		'type'    => Controls_Manager::SELECT,
		'default' => '4',         // Old 'desktop_default'
		'device_args' => $columns_device_args, // New argument
		'options'       => [
		    '1'    => '1',
			'2'    => '2',
			'3'    => '3',
			'4'    => '4',
			'5'    => '5',
			'6'    => '6',
		],
		'prefix_class' => 'responsive%s-',
		'render_type' => 'template',
	]
);

If you are using a third party plugin for rendering, you must force the widget to reload with the argument ‘render_type‘ (Line 33).

Create or update the Stylesheet

For the rule “@media” the “min-width” property only applies to the largest device.
Other rules must use the ‘max-width‘ property.


/** Desktop, Laptop & Widescreen */
@media screen and (min-width: 1200px) {
.responsive-1 .your-class-name { width:100%; }
.responsive-2 .your-class-name { width:50%; }
.responsive-3 .your-class-name { width:33.3333%; }
.responsive-4 .your-class-name { width:25%; }
.responsive-5 .your-class-name { width:20%; }
.responsive-6 .your-class-name { width:16.6666%; }
}

/** Tablet Extra */
@media screen and (max-width: 1200px) {
.responsive-tablet_extra-1 .your-class-name { width:100%; }
.responsive-tablet_extra-2 .your-class-name { width:50%; }
.responsive-tablet_extra-3 .your-class-name { width:33.3333%; }
.responsive-tablet_extra-4 .your-class-name { width:25%; }
.responsive-tablet_extra-5 .your-class-name { width:20%; }
.responsive-tablet_extra-6 .your-class-name { width:16.6666%; }
}

/** Tablet */
@media screen and (max-width: 1024px) {
.responsive-tablet-1 .your-class-name { width:100%; }
...
}

/** Mobile Extra */
@media screen and (max-width: 880px) {
.responsive-mobile_extra-1 .your-class-name { width:100%; }
...
}

/** Mobile */
@media screen and (max-width: 767px) {
.responsive-mobile-1 .your-class-name { width:100%; }
...
}

How to add defaults and options for a control with custom breakpoints

The goal of this exercise is to value the default values ​​and the options of a ‘SELECT2’ type control.
The following code adds the ‘Desktop’ (Line 20 OR 27, 29) device which, as you know, is no longer present for the new custom breakpoints.
‘default’ and ‘options’ arguments are added in the control (Line 43, 44).

use Elementor\Plugin; // use ElementorPro\Plugin;

...

private $active_breakpoints = [];
private $active_devices = [];
private $device_options = [];

...

// Active breakpoints
$this->active_breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();

// Elementor version >= 3.4.0
if(version_compare(ELEMENTOR_VERSION, '3.4.0', '>=')) {
	// Add 'desktop' device
	$args = ['add_desktop' => true, 'reverse' => true];
	
	// Devices list
	$this->active_devices = Plugin::$instance->breakpoints->get_active_devices_list($args);
} else {		
    // Devices need to be ordered from largest to smallest.
    $this->active_devices = array_reverse(array_keys($this->active_breakpoints));
    			
    // Add desktop in the correct position.
    if(in_array('widescreen', $this->active_devices, true)) {
    	$this->active_devices = array_merge(array_slice($this->active_devices, 0, 1), ['desktop'], array_slice($this->active_devices, 1));
    } else {
    	$this->active_devices = array_merge(['desktop'], $this->active_devices);
    }
}

// Control options
foreach($this->active_devices as $device) {
	$label = 'desktop' === $device ? esc_html__('Desktop', 'eac-components') : $this->active_breakpoints[$device]->get_label();
	$this->device_options[$device] = $label;
}

/** Apply breakpoints */
$element->add_control('eac_element_sticky_devices',
	[
	'label'			=> __('Actif avec', 'eac-components'),
	'type'			=> Controls_Manager::SELECT2,
	'multiple'		=> true,
	'label_block'	=> true,
	'default'		=> $this->active_devices, // vs [ 'desktop', 'tablet', 'mobile' ... ]
	'options'		=> $this->device_options,
	]
);
				

How to retrieve the values ​​of active breakpoints in JavaScript

Simple example in Javascript to show how to value variables with breakpoint values ​​assign to each device.
/**
 * Retrieve custom breakpoints in javascript
 */
const activeBreakpoints = elementorFrontend.config.responsive.activeBreakpoints;
let windowWidthMob = 0,	windowWidthMobExtra = 0, windowWidthTab = 0, windowWidthTabExtra = 0, windowWidthLaptop = 0, windowWidthWidescreen = 0;
			
// There are active breakpoints
if(Object.keys(activeBreakpoints).length > 0) {
    $.each(elementorFrontend.config.responsive.activeBreakpoints, function(device) {
    	if(device === 'mobile') { windowWidthMob = activeBreakpoints.mobile.value; } // use 'default_value' for the default value
    	else if(device === 'mobile_extra') { windowWidthMobExtra = activeBreakpoints.mobile_extra.value; }
    	else if(device === 'tablet') { windowWidthTab = activeBreakpoints.tablet.value; }
    	else if(device === 'tablet_extra') { windowWidthTabExtra = activeBreakpoints.tablet_extra.value; }
    	else if(device === 'laptop') { windowWidthLaptop = activeBreakpoints.laptop.value; }
    	else if(device === 'widescreen') { windowWidthWidescreen = activeBreakpoints.widescreen.value; }
    });
}