Use the Elementor HTML widget to create a clickable toggle checkbox. See below for the HTML and CSS code.
The result with the moon icon will look like this:
/* Your selector here */
selector .switch {
position: relative;
display: inline-block;
width: 50px;
height: 26px;
}
selector .switch input {
opacity: 0;
width: 0;
height: 0;
}
selector .slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: grey; /* Sun color */
border: 1px solid #FFF; /* White border */
-webkit-transition: .4s;
transition: .4s;
}
selector .slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 2px;
bottom: 3px;
background-color: white;
-webkit-transition: .2s;
transition: .2s;
}
selector .slider::before {
position: absolute;
content: ""; /* Unicode sun symbol Alternative 2600, 263C,\2B24, 25CB */
font-size: 8px;
left: 4px;
bottom: 3px;
color: #FFF; /* White color for sun */
opacity: 1; /* Show the sun by default */
transition: opacity .2s ease, transform .2s ease; /* Smooth transitions */
}
selector .slider::after {
position: absolute;
content: "\263E"; /* Unicode moon symbol */
font-size: 20px;
font-weight: bold;
left: 27px; /* Adjust the position for the moon */
bottom: 3px;
color: #FFF; /* White color for moon */
opacity: 0; /* Hide the moon by default */
transition: opacity .2s ease, transform .2s ease; /* Smooth transitions */
}
selector input:checked + .slider {
background-color: #222; /* Dark background for moon */
}
selector input:checked + .slider::before {
opacity: 0; /* Hide the sun when checked */
}
selector input:checked + .slider::after {
opacity: 1; /* Show the moon when checked */
}
/* Rounded sliders */
selector .slider.round {
border-radius: 500px;
}
selector .slider.round::before {
border-radius: 500px;
}
selector .slider.round::after {
border-radius: 0px;
}
selector .switch {
position: relative;
display: inline-block;
width: 50px;
height: 26px;
}
selector .switch input {
opacity: 0;
width: 0;
height: 0;
}
selector .slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: grey;
border: 1px solid white;
-webkit-transition: .4s;
transition: .4s;
}
selector .slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 2px;
bottom: 3px;
background-color: white;
-webkit-transition: .2s;
transition: .2s;
}
selector input:checked + .slider {
background-color: black;
}
selector input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
selector input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
selector .slider.round {
border-radius: 34px;
}
selector .slider.round:before {
border-radius: 50%;
}
You will need to install a plugin to store the javascript, which you can see in the next step. I also tried adding the code directly to the functions.php file of my hello-elementor theme, as well as uploading the .js file to the theme and then executing it with “wp-enqueue_script”. But I did not choose this solution and I would not recommend modifying the functions.php file directly.
The following plugins worked for me:
The following solutions have not worked for me:
I decided to use WPCode Lite
;(function(){
let chck_if_gsap_loaded = setInterval(function(){
const eleBuilder = document.querySelector('body').classList.contains("elementor-editor-active");
if(window.gsap && window.ScrollTrigger && !eleBuilder){
gsap.registerPlugin(ScrollTrigger);
light_dark_mode();
clearInterval(chck_if_gsap_loaded);
}
}, 500);
function light_dark_mode(){
const darkmode = gsap.timeline({paused:true});
const tl = gsap.timeline();
//tl.to('body', {backgroundColor: '#000', duration:0.00}); // Body Background color
tl.to(".dm-container-1", {backgroundColor: '#07090A', duration:0.1}, "<"); // Container Type 1 Background color
tl.to(".dm-container-2", {backgroundColor: '#30353A', duration:0.1}, "<"); // Container Type 2 Background color
tl.to(".dm-container-3", {backgroundColor: '#404040', duration:0.1}, "<"); // Container Type 3 Background color
tl.to(".dm-container-border", {borderColor: '#a9acb4', duration:0.1}, "<"); // Container Border color
tl.to(".dm-container-gradient", {background: 'linear-gradient(140deg, #090727 400px, #8d0022 70%)', duration:0}); // Container with gradient fill
tl.to(".dm-image-brightness", { filter: "brightness(0.9)", duration:0.1}, "<"); // Reduce image brightness
tl.to(".dm-icon svg", {fill: '#ffffff', duration:0.1}, "<"); // Change icon SVG color
tl.to(".dm-icon i", {color: '#ffffff', duration:0.1}, "<"); // Change icon i color
tl.to(".dm-text h1", {color: '#ffffff', duration:0.1}, "<"); // Change Text color
tl.to(".dm-text h2", {color: '#ffffff', duration:0.1}, "<");
tl.to(".dm-text h3", {color: '#ffffff', duration:0.1}, "<");
tl.to(".dm-text h4", {color: '#ffffff', duration:0.1}, "<");
tl.to(".dm-text p", {color: '#ffffff', duration:0.1}, "<");
tl.set(".dm-text a", {color: '#ffffff', duration:0.1}, "<");
tl.set(".dm-text span", {color: '#ffffff', duration:0.1}, "<"); // Specific Text color class
tl.to(".dm-text div", {color: '#ffffff', duration:0.1}, "<");
darkmode.add(tl);
// Getting the checkbox by the Id
const toggleCheckbox = document.getElementById("darkmode-checkbox");
// Function to set the theme
function setTheme(theme) {
if (theme === "dark") {
// Apply dark theme styles here
document.body.classList.add("darkmode"); // Add a class to the body for dark mode styles
toggleCheckbox.checked = true; // Check the checkbox for dark mode
darkmode.play(); // Assuming darkmode.play() handles theme transition
} else {
// Apply light theme styles here
document.body.classList.remove("darkmode"); // Remove the class for light mode styles
toggleCheckbox.checked = false; // Uncheck the checkbox for light mode
darkmode.reverse(); // Assuming darkmode.reverse() handles theme transition
}
}
// Function to initialize theme based on localStorage
function initializeTheme() {
let currentTheme = localStorage.getItem("theme");
if (currentTheme) {
setTheme(currentTheme);
// Update the checkbox state based on the current theme
if (currentTheme === "dark") {
toggleCheckbox.checked = true;
} else {
toggleCheckbox.checked = false;
}
} else {
// If no theme is set in localStorage, default to light mode
setTheme("light");
}
}
// Initialize the theme when the page loads
initializeTheme();
// Event listener for the checkbox toggle
toggleCheckbox.addEventListener("click", () => {
if (toggleCheckbox.checked) {
setTheme("dark");
localStorage.setItem("theme", "dark");
} else {
setTheme("light");
localStorage.setItem("theme", "light");
}
});
}
})();
In the JavaScript, the classes are defined as “dm-[name]”. This has the advantage that you can create different colours for the same element in elementor. For example, container type 1 can get black and container type 2 can get dark grey after pressing the dark mode toggle. Not all containers need to have the same behaviour. Just add different CSS classes that you define in the javascript above.
For the accordion widgets I added “dm-text dm-icon” to change the icon colour as well as the text.
By pressing F12 in Chrome it is possible to use the console to get live information about the toggle checkbox or the active theme. This can help when you need to debug the dark mode javascript
const c1 = document.getElementById("darkmode-checkbox").checked
const c2 = localStorage.getItem("theme")
const c3 = document.getElementById("darkmode-checkbox").classList
console.log("c1:", c1, "c2:", c2, "c3:", c3);
There is a bug I was not able to fix until now. If, for example, the user switches to the non-default theme on my page, in my case the light theme, and then reloads the page, the default theme is loaded first and half a second later, it automatically switches to the desired light mode. It’s flickering.
I think it has something to do with when the JavaScript code is executed. I was not able to execute the JavaScript first and then render the website.
I found the twenty-twenty-one theme which has a dark mode toggle included. I analysed the dark theme implementation but had to realise that it is more complex than just adding one javascript file. I think the two relevant files are:
There are different solutions you can find, but none of them worked for me: