Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autofocus is not working on input rerender in Chrome and Firefox #15261

Open
gyzerok opened this issue Feb 11, 2025 · 6 comments
Open

autofocus is not working on input rerender in Chrome and Firefox #15261

gyzerok opened this issue Feb 11, 2025 · 6 comments

Comments

@gyzerok
Copy link

gyzerok commented Feb 11, 2025

Describe the bug

If you have an input and then rerender your view with another autofocused input, then autofocus does not seem to work. I see this bug in Chrome and Firefox, but in Safari it seems to work fine.

Reproduction

Just click button multiple times in this REPL.

<script>
	let input = $state(0)
</script>

<button onclick={() => (input++)}>click</button>
{#key input}
	<input type="text" placeholder={input} autofocus />
{/key}

System Info

Firefox 135.0 (20250130195129)
Chrome 133.0.6943.53 (Official Build) (arm64)
Safari 18.3 (20620.2.4.11.5)

Severity

annoyance

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Feb 11, 2025

The autofocus global attribute is a Boolean attribute indicating that an element should be focused on page load, or when the that it is part of is displayed.

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus

The autofocus content attribute allows the author to indicate that an element is to be focused as soon as the page is loaded, allowing the user to just start typing without having to manually focus the main element.

When the autofocus attribute is specified on an element inside dialog elements or HTML elements whose popover attribute is set, then it will be focused when the dialog or popover becomes shown.

https://html.spec.whatwg.org/multipage/interaction.html#the-autofocus-attribute

I think what you're seeing is expected behavior. It would be more annoying if an element with [autofocus] would always steal focus from everything.

@brunnerh
Copy link
Member

This does not happen with plain HTML & JS in any browser, including Safari.

There is an $.autofocus(input_1, true) call being generated, presumably to have equivalent behavior for client-side rendered applications. The logic does not check whether this is the first render, though.

This probably needs additional logic to check for first render or the popover/dialog case.

@gyzerok
Copy link
Author

gyzerok commented Feb 11, 2025

@brunnerh you mean the correct thing would be to fix Safari here?

@brunnerh
Copy link
Member

brunnerh commented Feb 11, 2025

No, as noted, Safari seems to behave the same as other browsers for plain HTML/JS (i.e. not focusing on inserting new elements with autofocus set).

Some test code
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Auto-Focus</title>
</head>
<body>
	<button>click</button>
	<input type="text" placeholder="0" autofocus>

	<script>
		let i = 0;
		const button = document.querySelector('button');
		button.addEventListener('click', () => {
			button.nextElementSibling?.remove();

			i++;
			const input = document.createElement('input');
			input.autofocus = true;
			input.type = 'text';
			input.placeholder = i.toString();

			document.body.insertBefore(input, button.nextElementSibling);
		});
	</script>
</body>
</html>

I propose changing Svelte's autofocus function so it no longer focuses things after the initial rendering (exception being the opening of popovers & dialogs).

Looking at the function I did not see anything that would cause it:

export function autofocus(dom, value) {
if (value) {
const body = document.body;
dom.autofocus = true;
queue_micro_task(() => {
if (document.activeElement === body) {
dom.focus();
}
});
}
}

But upon adding a line testing for the activeElement, sure enough, Safari has the <body> as the active element after clicking a button. Just why...

// added at end of click handler:
queueMicrotask(() => console.log(document.activeElement));

Edit: Apparently this is for consistency with Mac software in general, the behavior is noted on MDN.

Whether clicking on a <button> or <input> button types causes it to (by default) become focused varies by browser and OS. Most browsers do give focus to a button being clicked, but Safari does not, by design.

@gyzerok
Copy link
Author

gyzerok commented Feb 11, 2025

Should I close this ticket then, since the behavior I am experiencing isn't a bug?

@brunnerh
Copy link
Member

There arguably is a bug, just a different one.
Would wait for maintainer feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants