When a path is initially navigated to that heavily utilizes Drupal states (think the new development page with Twig debuggin). The page is initially viewable with non-JS styles. Then the JavaScript kicks in and modifies the DOM so that the page layout shifts.
This issue is intended to mitigate or remove this jankiness (as much as possible).
Plan
The plan is to use the new at-media scripting feature to reduce the jank as much as possible in browsers that support this. For older browsers, the current behavior will still persist.
Issue fork drupal-3404217
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
kostyashupenkoRegarding this issue here is a list of states which can really damage layout shifting:
First two states can be used for any thing, while the last two states are for the
detailshtml element (playing around open html attribute).Now about visible/invisible states. We can have something like
With the code above we adding state `visible` directly to the container fieldset.
While with this code:
we adding state directly to checkbox. But rendering system in Drupal provides form_element hook theme which is actually a wrapper of form elements. And according to states.js
we are not actually hiding/showing checkbox itself. We hiding/showing container (form-element container) element.
=====
What i want to say is that we can't solve this issue just by using CSS media query "scripting". Instead, here should be more complex logic which can give frontender some attributes or classnames of initial state.
Here is example:
1. Visit /admin/config/development/settings page
2. Initially all checkboxes are unchecked.
3. If you will toggle "Twig development mode" checkbox and then click on save btn
4. On the next visits of this page initial state will be different. Because checkbox is initially checked, so container element which is sensitive to the state of this checkbox should be initially visible. <-- here we are missing some helpful attributes or classnames, just to detect initial state to understand which CSS rules we should write.
If initial state should be "visible" -> we don't need to hide anything.
If initial state should be "hidden" -> we should hide element using CSS.
====
Summarizing:
We have to have some extra html attribute or classname above the element with state, which explains initial behavior. For instance
data-initial-state="hidden". These attributes/classnames we could use to prevent layout shifting on initial page load. For instance:With html element "details" we could add just from PHP "open" html attribute in details html tag in case if initial state is "expanded"
Comment #4
kostyashupenkoAdded proof of concept in merge request. You can test on '/admin/config/development/settings' page
Comment #5
andypostComment #6
smustgrave commentedThe issue summary mentions using at-media scripting feature, but proof of concept seemed to go a different route. Could it be explained some/documented in issue summary why a different approach is needed?
Comment #7
emil stoianov commentedThe proposed solution works but one needs to manually set the initial_state for each container
Some additional work is needed on automatically setting the initial_state.