hCaptcha scrolls to top on invokation

Viewed 158

I've added hCaptcha to my website in invisible mode, and I invoke the challenge when the submit button on my form is pressed by doing

await captcha.execute({ async: true }).catch(() => { // ... }
submitForm();

However, for some reason this causes the page to scroll to the top and then it shows me the hCaptcha challenge.

How can I prevent this scrolling from happening?

Example: https://codepen.io/aisouard/pen/mdxKqZy

2 Answers

There seemed to be a bug on Google's end, but they have fixed it a long time ago.

A workaround could be setting height in html to auto:

html {
    height: auto
}

The scrolling problem appears if you have height: 100%.

It seems to be an issue with Firefox. This workaround can fix it seemlessly.

Make sure you don't have the smooth-scrolling behavior enabled.

html {
  /* Make sure this line is disabled! */
  /* scroll-behavior: smooth; */
}

Create a variable which will be used to store your current Y scroll position later, might be a class attribute too.

let currentScroll = 0;

At the hCaptcha initialization, point it to a callback which will be fired when the challenge will appear.

function onCaptchaOpen() {
  if (('netscape' in window) && / rv:/.test(navigator.userAgent)) {
    window.scrollTo({ top: currentScroll });
  }
}

let widgetId = window.hcaptcha.render('contact-captcha', {
  sitekey: '10000000-ffff-ffff-ffff-000000000001',
  size: 'invisible',
  'open-callback': onCaptchaOpen,
});

Then find the submit button, and store the current scroll position right before triggering a captcha challenge.

function validate(event) {
  event.preventDefault();

  currentScroll = (window.pageYOffset || document.scrollTop) - (document.clientTop || 0);

  window.hcaptcha
    .execute(widgetId, { async: true })
    .then(({ response }) => console.log(response));
}

const submitButton = $('#submit-button').get(0);
submitButton.onclick = validate;

Fixed codepen: https://codepen.io/aisouard/pen/NWYEbpp

Related