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

Don't enable polyfill if browser supports ":focus-visible" #237

Open
kutensky opened this issue Aug 28, 2020 · 5 comments · May be fixed by #259
Open

Don't enable polyfill if browser supports ":focus-visible" #237

kutensky opened this issue Aug 28, 2020 · 5 comments · May be fixed by #259

Comments

@kutensky
Copy link

kutensky commented Aug 28, 2020

Currently Chrome with experimental flag enabled supports ":focus-visible" polyfill. It would be nice if polyfill could be enabled only if current browser doesn' support ":focus-visible".
To do that, I propose to check pseudo-class support using this method:

supportsPseudo = function (pseudoClass) {
	// Get the document stylesheet
	var ss = document.styleSheets[0];

	// Create a stylesheet if one doesn't exist
	if (!ss) {
		var el = document.createElement('style');
		document.head.appendChild(el);
		ss = document.styleSheets[0];
		document.head.removeChild(el);
	}

	// Test the pseudo-class by trying to style with it
	var testPseudo = function () {
		try {
			if (!(/^:/).test(pseudoClass)) {
				pseudoClass = ':' + pseudoClass;
			}
			ss.insertRule('html' + pseudoClass + '{}', 0);
			ss.deleteRule(0);
			return true;
		} catch(e) {
			return false;
		}
	};

	// Run the test
	return testPseudo();
};

And then in polyfill modify code on the line 306 with:

if (typeof document !== 'undefined' && !supportsPseudo("focus-visible")) {
	// Apply the polyfill to the global document, so that no JavaScript
	// coordination is required to use the polyfill in the top-level document:
	applyFocusVisiblePolyfill(document);
}

After that we will be able to write css rules for both native ":focus-visible" and polyfill version:

:focus:not(:focus-visible) {
	outline: 0;
}
.js-focus-visible :focus:not(.focus-visible) {
	outline: 0;
}
@emilio
Copy link

emilio commented Aug 29, 2020

Drive by, but that's a really really expensive way to test for a pseudo-element. try { document.querySelector(":focus-visible"); return true; } catch { return false } should be much faster.

@Justineo
Copy link
Contributor

I’m afraid this requires double your style declarations for .focus-visible to make it work with or without the “polyfill” (technically this project isn’t a real polyfill).

@kutensky
Copy link
Author

I’m afraid this requires double your style declarations for .focus-visible to make it work with or without the “polyfill” (technically this project isn’t a real polyfill).

Yeap, that will require a double style declaration. But on the other hand, when browsers start to support his feature (Chrome is going to start supporting it from v.86), no js run will be needed. Currently, polyfill does a lot of background work that isn't good for performance.

@robdodson
Copy link
Collaborator

Very good points from everyone.

It sounds like if we land this then we should use @emilio's implementation, but also land a note in the README which explains the need to double up your style declarations. We could also add a note that if folks would prefer, they can use the postcss plugin (https://github.com/csstools/postcss-focus-visible) which I think will let them write their CSS using :focus-visible and then it'll do the right thing depending on their browser support matrix. I'm not a post-css expert but I think that's how it works :)

@ryuran
Copy link

ryuran commented Nov 15, 2022

Related to #244

This condition could help

if (!window.CSS?.supports?.("selector(:focus-visible)")) { 
  // Apply the polyfill
}

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

Successfully merging a pull request may close this issue.

5 participants