States API creates jank (layout shift) on page load

Created on 26 November 2023, 7 months ago
Updated 22 January 2024, 5 months ago

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.

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
JavascriptΒ  β†’

Last updated about 10 hours ago

Created by

πŸ‡ΊπŸ‡ΈUnited States mherchel Gainesville, FL, US

Live updates comments and jobs are added and updated live.
  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @mherchel
  • πŸ‡·πŸ‡ΊRussia kostyashupenko Omsk

    Regarding this issue her is a list of states which can really damage layout shifting:

    • visible
    • invisible
    • expanded
    • collapsed

    First two states can be used for any thing, while the last two states are for the details html element (playing around open html attribute).

    Now about visible/invisible states. We can have something like

       $form['something'] = [
          '#type' => 'fieldset',
          '#title' => $this->t('Some title'),
          '#states' => [
            'visible' => $something,
          ],
        ];
    

    With the code above we adding state `visible` directly to the container of some elements.
    While with this code:

      $form['something'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('Something'),
          '#states' => [
            'visible' => $something,
          ],
        ];
    

    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

      $document.on('state:visible', (e) => {
        if (e.trigger) {
          let $element = $(e.target).closest(
            '.js-form-item, .js-form-submit, .js-form-wrapper',
          );
          // For links, update the state of itself instead of the wrapper.
          if (e.target.tagName === 'A') {
            $element = $(e.target);
          }
          $element.toggle(e.value);
        }
      });
    

    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.

  • Merge request !6192POC β†’ (Open) created by kostyashupenko
  • Status changed to Needs review 5 months ago
  • πŸ‡·πŸ‡ΊRussia kostyashupenko Omsk

    Added proof of concept in merge request. You can test on '/admin/config/development/settings' page

  • Status changed to Needs work 5 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    The 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?

Production build 0.69.0 2024