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 index 0000000000000000000000000000000000000000..66b21a7a849bcb38fd56a0c0cac5516285425b9c --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-90426-Browser-nativeLazyLoadingForImages.rst @@ -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 diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php index c6f8a449d7578a705162f5d9c92938c3de07381a..be7b956c0c17302f96608082cb41fb77624a7447 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php @@ -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); diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/MediaViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/MediaViewHelper.php index 8012c2751bc82dd74280dfdbb0900e833ff4cfd7..48b4ebec4d3c7f58308b8825d156ba2b7abde83a 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/MediaViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/MediaViewHelper.php @@ -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'); diff --git a/typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript b/typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript index 58dc374ed8148d5cbf3c285b6fe2eb8ec122d803..3b5b2fbc8ad8ae2c1edc8341f96fd73cca4d386a 100644 --- a/typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript +++ b/typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript @@ -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> diff --git a/typo3/sysext/fluid_styled_content/Configuration/TypoScript/constants.typoscript b/typo3/sysext/fluid_styled_content/Configuration/TypoScript/constants.typoscript index e8243535e79eb5a1edafbf3f4195378d7c37a39b..1846e1536dec18363c28e559a9b802a062cb5448 100644 --- a/typo3/sysext/fluid_styled_content/Configuration/TypoScript/constants.typoscript +++ b/typo3/sysext/fluid_styled_content/Configuration/TypoScript/constants.typoscript @@ -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 diff --git a/typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html b/typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html index 2d384b37fbf65e4e0462895a4b9c20c9e33156da..12427ff687207d34d69d76874a9b803e849b1138 100644 --- a/typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html +++ b/typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html @@ -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>