Open craigfrancis opened 5 years ago
As a high-level critique: this doesn't belong on a pseudo-class, as it isn't something that'll vary by element. It belongs in a MQ, like (page-state: loading)
or something.
I'd have to go archive-diving, but I'm pretty sure we've discussed something like this in the past. I think there were two big strikes against it:
Like you said tho, it is true that JS cannot both (a) have things invisible immediately on page load, and (b) fail-open by having them become visible if JS is blocked or errors. That would be a decent argument for providing this functionality in a MQ, with examples and warning text telling you how to use it "safely". (Which I suspect would be more natural anyway, as hiding things feels like an "exception" and thus is more natural to segregate away inside a MQ block, rather than hiding by default and putting your normal styles there.)
A big question is thus, what loading transitions would we want to care about? Almost certainly the 'DOMContentLoaded' event, and maybe the 'load' event; anything else? The benefit of those two is that it maps cleanly to the document.readyState
enum; a page starts in "loading", goes to "interactive" when DOMContentLoaded
fires, and goes to "complete" when load
fires.
Thanks @tabatkins.
This probably should be a Media Query.
I originally thought about a pseudo-class because it might help keep rules together:
html:before-load .member_fields,
html[data-member="no"] .member_fields {
display: none;
}
But I doubt I would actually do this, as the initial load would be a display: none
, and after setup I would probably use other styles (e.g. height for animation).
I like your idea of using document.readyState
(loading, interactive, complete); but I think we need another state to cover async JavaScript.
As in, if you use:
<script src="./script.js" async="async"></script>
That JavaScript might run after DOMContentLoaded
, which is why I use something like:
;(function(document, window, undefined) {
'use strict';
if (!document.addEventListener || !document.querySelector) {
return;
}
document.documentElement.className += ' js_register_enabled';
function init() {
var inputs = document.querySelectorAll('.member_fields');
// ...
}
if (document.readyState !== 'loading') {
init();
} else {
document.addEventListener('DOMContentLoaded', init);
}
})(document, window);
Now I could use loading
or interactive
:
@media (page-state: loading), (page-state: interactive) {
.member_fields {
display: none;
}
}
Which would work, but it would involve waiting for all resources to load (images might be a while).
So is there is a state we can define, a bit like how the load
event works, but it just waits for <script>
resources; which could be sync, defer, or async?
Page layout will often change when using async JavaScript, which is annoying, especially on a slow internet connection.
Would it be possible to have a CSS selector that's only applied when the JavaScript is being downloaded, and during initial execution.
I'm always reluctant to do something like
display: none
on some content, then get the JavaScript to show it, as the JavaScript may have a problem (fails to load due to network or ad-blocker, parsing issues, finding the element, etc).I realise async JavaScript introduces an issue here, because it can download after
DOMContentLoaded
. And theload
event is probably too late (waiting for loads of images), so the exact definition of this pseudo-class is up for debate.As an example...
On a registration form, it asks if you're a member, and if you select "yes", then additional fields appear.
Today I'd do that by getting the JavaScript to hide the fields on
DOMContentLoaded
, but this means the additional fields appear while loading.I'd like to create a rule, that's in a normal
<link>
style sheet, such as:So the fields are initially hidden, then my JavaScript can set more specific styles; and if I don't, it will fall back to the fields being shown.
As it's async, and the DOM might not contain the fields yet, I suspect my initial JavaScript code would do something like the following (after any compatibility checks):