I'm working on a Bootstrap website that has light and dark mode, functioning through JavaScript. And I've integrated Google reCAPTCHA (v2) (I'm not a robot) into my project successfully.
But I want to be able to change reCAPTCHA theme dynamically through the theme toggle switch. As the documentation has an attribute data-theme
which we can set value to dark
or light
.
The main div
of reCAPTCHA container through which the theme could be toggled by changing class (rc-anchor-light / rc-anchor-dark
) is located inside an iframe
.
I tried by adding and removing classes (rc-anchor-light / rc-anchor-dark
) from the theme switch JavaScript function to change the reCAPTCHA theme dynamically, but it's not working and I'm not able to figure out why.
While reCAPTCHA v2 doesn't natively support dynamic theme switching, here's a workaround using multiple reCAPTCHA containers and JavaScript:
HTML structure for two reCAPTCHA containers with different themes
<div class="rg-recaptcha border rounded hide" id="grecaptchaLight" data-callback="recaptchaVe" data-expired-callback="recaptchaEx" data-theme="light"></div>
<div class="rg-recaptcha border rounded hide" id="grecaptchaDark" data-callback="recaptchaVe" data-expired-callback="recaptchaEx" data-theme="dark"></div>
JavaScript:
// Function to determine the preferred theme (light or dark)
function getPreferredThemeFunction() {
// Implement your logic to determine the preferred theme here
// This function should return 'light' or 'dark'
}
// Variable to store the preferred theme
var preferredTheme = getPreferredThemeFunction();
// Variables to store the reCAPTCHA widget IDs
var grecaptchaDarkWD, grecaptchaLightWD;
// Variable to track whether reCAPTCHA has been rendered
var gCapthaRendered = false;
// Callback function triggered when reCAPTCHA is loaded
var onloadCallback = function () {
// Render reCAPTCHA widgets with dark and light themes
grecaptchaDarkWD = grecaptcha.render('grecaptchaDark', {
'sitekey': '1234567890',
'theme': 'dark'
});
grecaptchaLightWD = grecaptcha.render('grecaptchaLight', {
'sitekey': '1234567890',
'theme': 'light'
});
// Mark reCAPTCHA as rendered
gCapthaRendered = true;
// If a preferred theme is set, switch to it
if (preferredTheme) {
changeReCaptcha(preferredTheme);
}
};
// Function to dynamically change the reCAPTCHA theme
function changeReCaptcha(theme = 'light') {
if (gCapthaRendered) {
// Reset and hide the inactive reCAPTCHA container
if (theme == 'dark') {
document.getElementById('grecaptchaLight').innerHTML = "";
grecaptcha.reset(grecaptchaDarkWD);
document.getElementById('grecaptchaLight').classList.add("hide");
document.getElementById('grecaptchaDark').classList.remove("hide");
} else if (theme == 'light') {
document.getElementById('grecaptchaDark').innerHTML = "";
grecaptcha.reset(grecaptchaLightWD);
document.getElementById('grecaptchaDark').classList.add("hide");
document.getElementById('grecaptchaLight').classList.remove("hide");
}
}
}