Skip to content

Instantly share code, notes, and snippets.

@dgrammatiko
Created February 13, 2022 16:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgrammatiko/a20236039586a2fbc5c77caadffc3de8 to your computer and use it in GitHub Desktop.
Save dgrammatiko/a20236039586a2fbc5c77caadffc3de8 to your computer and use it in GitHub Desktop.

Developers please conform to the new image convention

Joomla 4 shipped with native support for lazy loading images and also with a new concept of adapters for storing images. This requires some attention in the code.

Tobias Zulauf was the developer that handled the communication with the Google devs for implementing all the nice recomendation whenever you run a lighthouse. On top of that he was the one that created the plugin that would allow the Web Platform new feature called images lazy loading. On a weird turn of events the project decided not to go with the plugin approach but rather to use the native support for lazy loading as the default behaviour universally for all the images. There were a lot of discussions with people commenting against this approach, mainly because the first itteration was treating every image as a lazy loadable image. This was rectified few month later when the image picker code had to be revisited so it would allow remote storage of images (what is known as Media Adapters). Google developers were also supporting the approach that didn't require the plugin, the plugin had the overhead that portion of the rendered HTML had to be parsed with some regular expression and the attribute was then added on that portion of the HTML. Apart from the obvious performance impact there was a usabiliy impact as the plugin wouldn't be able to add the attribute to some images, it was either all or none. I guess all these are just historical events and to some point they might be totally irrelevant for a developer that has developed some extensions for Joomla 4. But, and there's a big but here, these changes affect the way the developers are going to work with images. For some time, actually untill version 4.0.5 Joomla had left the task of adding an image to the output HTML up to the developers to do it their way. The project already shipped two different helpers to do this, but it turned out that most, if not all, they completely ignored the helpers and thus the images had a weird # with some random words and number at the end of the URL.

The solution

To put an end to this rather strange situation, a new JLayout was introduced that will allow developers to output the image tags correctly and most importantly way easier: So instead or writting something like this:

<?php

echo '<img src="' . $imageURL .'" alt="' . htmlspecialchars($imageAlt, ENT_COMPAT, 'UTF-8') . '">';

?>

The recomended way to do this is to use the JLayout:

<?php

echo LayoutHelper::render('joomla.html.image', ['src' => imageURL, 'alt' => $imageAlt]);

?>

Benefits:

  • The URL and the alt attribute will be correctly escaped
  • The image tag is rendered correctly and the developer doesn't have to worry about the # at the end of the URL
  • The image tag will get a loading="lazy" attribute if the image has defined width and height attributes
  • The alt attribute will be ignored if the value passes is false (boolean)
  • Any additional attributes will be rendered correctly, just pass them as in the named array: (e.g. 'class' => 'my-class')

About Backward Compatibility

The JLayout will be available in Joomla 4.0.5 and later but was backported also in Joomla 3.10.6 so that developers can use it in their extensions that are available for both major versions. For those that want to support earlier versions of Joomla, the recomended way is to distribute a copy of the layouts/joomla/html/image.php file in your extension and copy it to the exact location using a simple is_file() check in your update script. Here is a simple example of how to do this:

 public function install($type, $parent)
 {
	 // After your existing code
		if (!is_file(JPATH_ROOT . '/layouts/joomla/html/image.php'))
		{
		copy(
			$parent->getParent()->getPath('source') . '/image.php',
			JPATH_ROOT . '/layouts/joomla/html/image.php'
		);
	 }
 }
@softforge
Copy link

Sure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment