Problem/Motivation

The new lazy loading attribute will be enabled by default in Chrome 76 (https://chromestatus.com/feature/5645767347798016). We should support this because it should bring nice performance and loading improvements for pages with many images and frames that are not visible on the first page load.

Read more about this feature on:

Comments

pivica created an issue. See original summary.

pivica’s picture

Status: Active » Needs review
Issue tags: +next-release
StatusFileSize
new3.67 KB

Here is a first patch.

miro_dietiker’s picture

+++ b/themes/bs_bootstrap/bs_bootstrap.theme
@@ -144,6 +144,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
+    '#options' => ['' => t('None'), 'lazy' => t('Lazy'), 'eager' => t('Eager'), 'auto' => t('Auto')],

It would be really nice to have either a description is provided or a link to specifications. Lazy, Eager, Auto all is not clear to the regular uninformed user. / site builder.

And then we should state what expectedly supports this as well in the UI as a disclaimer. ;-)

+++ b/themes/bs_bootstrap/bs_bootstrap.theme
@@ -407,6 +422,36 @@ function bs_bootstrap_preprocess_select(&$variables) {
+ * Implements hook_preprocess_svg_formatter().

SVG? :-)

And those are actual integration to specific contrib modules, so we should put a reference in the comment.

+++ b/themes/bs_bootstrap/bs_bootstrap.theme
@@ -144,6 +144,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
+  $form['bs_bootstrap']['lazy_loading_iframe'] = [

Thought this would affect all iframes until i have seen that it only affects video_embed cases.. I don't know if you really want to have such a generic setting and later expand it to affect more iframes?

Also not fully sure how this works combined with GDPR postponed loading-on-click features.. And script based iframes?

So maybe this is really video_embed specific?

sasanikolic’s picture

Status: Needs review » Needs work

Note that this (for now) only works in Chrome and Android browser: https://caniuse.com/#search=lazy-loading
For Firefox an issue was created, but no priority was defined yet: https://bugzilla.mozilla.org/show_bug.cgi?id=1542784

Based on the previous feedback, changing the status. Will test it soon.

pivica’s picture

Issue summary: View changes
pivica’s picture

Issue summary: View changes
pivica’s picture

StatusFileSize
new4.76 KB
new3.21 KB

Here is a new patch.

> It would be really nice to have either a description is provided or a link to specifications.

Added.

> Lazy, Eager, Auto

It seems auto is not an option any more so i've removed it.

> And then we should state what expectedly supports this as well in the UI as a disclaimer. ;-)

You are referring to browser support or?

> SVG? :-)

Why not? If it is coming from img tag i guess it makes sense right? I improved patch to work with SVG only when it is not inlined.

> And those are actual integration to specific contrib modules, so we should put a reference in the comment.

Added comments related to this.

> Thought this would affect all iframes until i have seen that it only affects video_embed cases..

No just video iframes which are the most common case probably.

Media Twitter is using iframe but it is initialized on client-side - maybe we could pass optional loading parameter somehow, didn't check it for now. Same goes for media instagram - it is converted to iframe on client-side.

We will deal with iframes in the follow-up.

> Also not fully sure how this works combined with GDPR postponed loading-on-click features.. And script based iframes?

No idea, however how is this related to GDPR in this context? Here we are just changing when the resource will be loaded. I guess you could track scrolling of viewport with this to some degree - but that is very inaccurate because each browser has it own logic when it will decide to load some lazy resource.

Additionally, Drupal core changed media handling, for example youtube is now handled by oembed. Discussed this with @berdir and his proposal is to move iframe support to follow-up and that we should concentrate first on images.

pivica’s picture

StatusFileSize
new2.52 KB
new4.76 KB

Used wrong attributes in link translation, fixed now.

pivica’s picture

Issue summary: View changes
pivica’s picture

Status: Needs work » Needs review

Ready for a new review.

Created #3157699: Lazy loading of iframes follow-up for all iframe related issues.

sasanikolic’s picture

Status: Needs review » Needs work
  1. +++ b/themes/bs_bootstrap/bs_bootstrap.theme
    @@ -154,6 +154,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
    +    '#options' => ['' => t('None'), 'lazy' => t('Lazy'), 'eager' => t('Eager')],
    

    I see Mozilla defines it as "Eager", but maybe we should consider a different name, like "Normal", "Default" or something else? On the other hand I feel like we should stick to the definitions mentioned at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading. I don't have a strong opinion about that, just an idea.

  2. +++ b/themes/bs_bootstrap/bs_bootstrap.theme
    @@ -154,6 +154,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
    +    '#description' => t('Indicates how the browser should load the image. Eager will load the image immediately, lazy will defer loading of the iframe until it reaches a calculated distance from the viewport, as defined by the browser. More information on this <a href="@link" target="_blank">link</a>.', ['@link' => 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading']),
    

    Maybe change "on this link" to "here".

  3. +++ b/themes/bs_bootstrap/bs_bootstrap.theme
    @@ -154,6 +154,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
    +    '#title' => t('Lazy load IFrame'),
    

    iframe should be lowercase, as we're referring to the html element: https://www.w3schools.com/tags/tag_iframe.asp

Last, but not the least, note that this will not work in older Firefox, Firefox for mobiles, IE11, Safari: https://caniuse.com/#feat=loading-lazy-attr. Didn't check if there are some polyfills for those yet, should we just state that we don't support this functionality in those browsers as just yet? Safari should be fixed soon: https://bugs.webkit.org/show_bug.cgi?id=196698.

pivica’s picture

Status: Needs work » Needs review
StatusFileSize
new2.54 KB
new4.74 KB

Here is a new patch based on the latest comment feedback.

> I see Mozilla defines it as "Eager", but maybe we should consider a different name, like "Normal", "Default" or something else?

Well, it's not Mozilla that defines it but the actual specification https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loadi....

I do agree that 'Normal' or 'Default' would be a better fit, but it could create confusion if somebody actually visits documentation link read that there is an 'Eager' option which is not presented visually on settings form. So i would keep it 'Eager' for now.

> 2. and 3.

Done.

> Last, but not the least, note that this will not work in older Firefox, Firefox for mobiles, IE11, Safari...

Current iframe support is old and works only for contributed media module, it will not work for new media core solution. We have a follow-up for this on #3157699: Lazy loading of iframes - i've updated issue description with your feedback. We are also stating in the description that this feature is experimental for now, i guess that is enough for now.

berdir’s picture

  1. +++ b/themes/bs_bootstrap/bs_bootstrap.theme
    @@ -154,6 +154,21 @@ function bs_bootstrap_form_system_theme_settings_alter(&$form, FormStateInterfac
    +  $form['bs_bootstrap']['lazy_loading_iframe'] = [
    +    '#type' => 'select',
    +    '#title' => t('Lazy load iFrame'),
    +    '#options' => ['' => t('None'), 'lazy' => t('Lazy'), 'eager' => t('Eager')],
    +    '#default_value' => bs_bootstrap_get_setting('lazy_loading_iframe'),
    +    '#description' => t('EXPERIMENTAL feature! Note that new core media is not supported currently.<br/>Indicates how the browser should load the iframe. Eager will load the iframe immediately, lazy will defer loading of the iframe until it reaches a calculated distance from the viewport, as defined by the browser. More information <a href="@link" target="_blank">here</a>.', ['@link' => 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-loading']),
    +  ];
    

    I'm unsure about keeping this at all.

    The "new" feature is in core since 8.6, that's Sept 18.

    It's also way less frequently used and much less of a concern IMHO.

  2. +++ b/themes/bs_bootstrap/bs_bootstrap.theme
    @@ -480,6 +532,8 @@ function bs_bootstrap_get_setting($setting_name) {
    +    'lazy_load_img' => '',
    +    'lazy_load_iframe' => '',
    
    +++ b/themes/bs_bootstrap/config/install/bs_bootstrap.settings.yml
    @@ -21,6 +21,8 @@ bs_bootstrap:
         navbar_container_type: fixed
    +  lazy_loading_img: false
    +  lazy_loading_iframe: false
       logo_svg_inline: true
    
    +++ b/themes/bs_bootstrap/config/schema/bs_bootstrap.schema.yml
    @@ -44,6 +44,12 @@ bs_bootstrap.settings:
                   label: 'Title of a link (label or language ISO code)'
    +        lazy_loading_img:
    +          type: string
    +          label: 'Image lazy loading'
    +        lazy_loading_iframe:
    +          type: string
    

    this doesn't seem to match. false as default config, but type string?

pivica’s picture

Title: Support lazy loading of images and iframes » Support lazy loading of images
StatusFileSize
new3.55 KB
new3.38 KB

> 1. I'm unsure about keeping this at all.

Makes total sense, removed related code to #3157699-3: Lazy loading of iframes.

> 2. this doesn't seem to match. false as default config, but type string?

Saw that before, but was a bit too lazy to change it, i guess type casting worked fine. Anyway, make sense to fix this.

Found one additional bug, in settings get function key was lazy_load_img instead of lazy_loading_img.

sasanikolic’s picture

Note that lazy loading will be enabled by default in Drupal 9.1: #3167034.

However, I noticed that in their image preprocess function they have this:

  // Without dimensions specified, layout shifts can occur,
  // which are more noticeable on pages that take some time to load.
  // As a result, only mark images as lazy load that have dimensions.
  if (isset($variables['width'], $variables['height']) && !isset($variables['attributes']['loading'])) {
    $variables['attributes']['loading'] = 'lazy';
  }

We don't have any check like that, thus we're adding the lazy attribute also to responsive images, which doesn't happen when I remove this patch.

pivica’s picture

> Note that lazy loading will be enabled by default in Drupal 9.1: #3167034.

Discussed with @sni, we do not like the fact that Drupal is doing this:

  // Without dimensions specified, layout shifts can occur,
  // which are more noticeable on pages that take some time to load.
  // As a result, only mark images as lazy load that have dimensions.
  if (isset($variables['width'], $variables['height']) && !isset($variables['attributes']['loading'])) {
    $variables['attributes']['loading'] = 'lazy';
  }

Because we think that these two things are not related. Lazy loading is one thing and setting width/height is another one - why should we not lazy loading image assets if width/height is not set.
Additionally, @sni is saying that this creates a problem with responsive images because the core is not setting width/height on the responsive image.

The only thing that we could improve is to do a lazy loading attribute empty check like core is doing like:

if (!empty($lazy_loading) && empty($variables['attributes']['loading'])) {
   $variables['attributes']['loading'] = $lazy_loading;
}

So lets do that.

berdir’s picture

I'm not sure it's so unrelated. Lazy-loading on images without a predefined width/height might result in layout adjustments as the image gets loaded, I would assume that's the reason for that.

But yes, without doing it for responsive images, it's missing out on the main use case.

pivica’s picture

> Lazy-loading on images without a predefined width/height might result in layout adjustments as the image gets loaded, I would assume that's the reason for that.

I do agree that that is the reason they added that checks, however, I don't think that this should be default behaviour - if no w/h then disable lazy loading. For some people, it would still be better to lazy load these resources when/if needed then to always load them.
Additionally, I would treat any image that is coming from image styles and has missing w/h or any other manual image without w/h as a bug.

Two more things.

1. Lazy loading attribute works also for iframes, and we have an idea to support youtube/vimeo and similar iframes that are coming from media. We would need separate settings for that.

2. We are offering option here for lazy loading which can be disabled if needed and user wantsthat, the core is not doing that for now.

pivica’s picture

StatusFileSize
new1.02 KB
new3.38 KB

And a third thing, we also support lazy load attrib for SVG images with img tag, not something that core is doing.

Here is a patch that adds a check like core is doing.

pivica’s picture

pivica’s picture

Status: Needs review » Closed (won't fix)

Core introduced lazy loading of images which is turned on by default in #3167034: Leverage the 'loading' html attribute to enable lazy-load by default for images in Drupal core. There is no point for this patch any more.