[FEATURE] Add native browser lazy loading for images 17/63317/6
authorBenni Mack <benni@typo3.org>
Tue, 18 Feb 2020 21:51:22 +0000 (22:51 +0100)
committerBenni Mack <benni@typo3.org>
Thu, 20 Feb 2020 14:02:37 +0000 (15:02 +0100)
This change adds the browser-native lazy loading option "loading"
HTML attribute for images.

See https://addyosmani.com/blog/lazy-loading/ for more details.

Resolves: #90426
Releases: master
Change-Id: I5c457ed5b72ef81622e5135f182d7b10ededd4df
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63317
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Christian Eßl <indy.essl@gmail.com>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Christian Eßl <indy.essl@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Feature-90426-Browser-nativeLazyLoadingForImages.rst [new file with mode: 0644]
typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/MediaViewHelper.php
typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript
typo3/sysext/fluid_styled_content/Configuration/TypoScript/constants.typoscript
typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-90426-Browser-nativeLazyLoadingForImages.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-90426-Browser-nativeLazyLoadingForImages.rst
new file mode 100644 (file)
index 0000000..66b21a7
--- /dev/null
@@ -0,0 +1,39 @@
+.. include:: ../../Includes.txt
+
+========================================================
+Feature: #90426 - Browser-native lazy loading for images
+========================================================
+
+See :issue:`90426`
+
+Description
+===========
+
+TYPO3 now supports the browser-native `loading` HTML attribute in :html:`<img>` tags.
+
+It is set to "lazy" by default for all images within Content Elements rendered
+with Fluid Styled Content. Supported browsers then choose to load these
+images at a later point when the image is within the browsers' Viewport.
+
+The configuration option is available via TypoScript constants and
+can be easily adjusted via the TypoScript Constant Editor in the Template module.
+
+Please note that not all browsers support this option yet, but adding
+this property will just be skipped for unsupported browsers.
+
+
+Impact
+======
+
+TYPO3 Frontend now renders images in content elements with the "loading=lazy"
+attribute by default when using TYPO3's templates from Fluid Styled Content.
+
+Using the TypoScript constant `styles.content.image.lazyLoading`,
+the behavior can be modified generally to be either set to `eager`,
+`auto` or to an empty value, removing the property directly.
+
+The Fluid ImageViewHelper has the possibility to set this option
+via `<f:image src="{fileObject}" treatIdAsReference="true" loading="lazy">`
+to hint the browser on how the prioritization of image loading should be used.
+
+.. index:: Frontend, ext:fluid_styled_content
\ No newline at end of file
index c6f8a44..be7b956 100644 (file)
@@ -114,6 +114,7 @@ class ImageViewHelper extends AbstractTagBasedViewHelper
         $this->registerTagAttribute('ismap', 'string', 'Specifies an image as a server-side image-map. Rarely used. Look at usemap instead', false);
         $this->registerTagAttribute('longdesc', 'string', 'Specifies the URL to a document that contains a long description of an image', false);
         $this->registerTagAttribute('usemap', 'string', 'Specifies an image as a client-side image-map', false);
+        $this->registerTagAttribute('loading', 'string', 'Native lazy-loading for images property. Can be "lazy", "eager" or "auto"', false);
 
         $this->registerArgument('src', 'string', 'a path to a file, a combined FAL identifier or an uid (int). If $treatIdAsReference is set, the integer is considered the uid of the sys_file_reference record. If you already got a FAL object, consider using the $image parameter instead', false, '');
         $this->registerArgument('treatIdAsReference', 'bool', 'given src argument is a sys_file_reference record', false, false);
index 8012c27..48b4ebe 100644 (file)
@@ -86,6 +86,7 @@ class MediaViewHelper extends AbstractTagBasedViewHelper
         $this->registerArgument('height', 'string', 'This can be a numeric value representing the fixed height in pixels. But you can also perform simple calculations by adding "m" or "c" to the value. See imgResource.width for possible options.');
         $this->registerArgument('cropVariant', 'string', 'select a cropping variant, in case multiple croppings have been specified or stored in FileReference', false, 'default');
         $this->registerArgument('fileExtension', 'string', 'Custom file extension to use for images');
+        $this->registerArgument('loading', 'string', 'Native lazy-loading for images property. Can be "lazy", "eager" or "auto". Used on image files only.');
     }
 
     /**
@@ -157,6 +158,9 @@ class MediaViewHelper extends AbstractTagBasedViewHelper
         $this->tag->addAttribute('src', $imageUri);
         $this->tag->addAttribute('width', $processedImage->getProperty('width'));
         $this->tag->addAttribute('height', $processedImage->getProperty('height'));
+        if (in_array($this->arguments['loading'] ?? '', ['lazy', 'eager', 'auto'], true)) {
+            $this->tag->addAttribute('loading', $this->arguments['loading']);
+        }
 
         $alt = $image->getProperty('alternative');
         $title = $image->getProperty('title');
index 58dc374..3b5b2fb 100644 (file)
@@ -18,6 +18,7 @@ lib.contentElement {
     settings {
         defaultHeaderType = {$styles.content.defaultHeaderType}
         media {
+            lazyLoading = {$styles.content.image.lazyLoading}
             popup {
                 bodyTag = <body style="margin:0; background:#fff;">
                 wrap = <a href="javascript:close();"> | </a>
index e824353..1846e15 100644 (file)
@@ -17,6 +17,9 @@ styles.content {
     # cat=content/parseFunc/a0; type=string; label=List of allowed HTML tags when rendering RTE content
     allowTags = a, abbr, acronym, address, article, aside, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, dfn, dl, div, dt, em, font, footer, header, h1, h2, h3, h4, h5, h6, hr, i, img, ins, kbd, label, li, link, meta, nav, ol, p, pre, q, s, samp, sdfield, section, small, span, strike, strong, style, sub, sup, table, thead, tbody, tfoot, td, th, tr, title, tt, u, ul, var
 
+    # cat=content/cImage/a0; type=options[lazy,eager,auto,]; label=Default settings for browser-native image lazy loading: Can be "lazy" (browsers could choose to load images later), "eager" (load images right away) or "auto" (browser will determine whether the image should be lazy loaded or not)
+    image.lazyLoading = lazy
+
     textmedia {
         # cat=content/cTextmedia/b1; type=int+; label= Max Image/Media Width: This indicates that maximum number of pixels (width) a block of media elements inserted as content is allowed to consume
         maxW = 600
index 2d384b3..12427ff 100644 (file)
@@ -1,3 +1,3 @@
 <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
-<f:media class="image-embed-item" file="{file}" width="{dimensions.width}" height="{dimensions.height}" alt="{file.alternative}" title="{file.title}" />
+<f:media class="image-embed-item" file="{file}" width="{dimensions.width}" height="{dimensions.height}" alt="{file.alternative}" title="{file.title}" loading="{settings.media.lazyLoading}" />
 </html>