Brian's Blog Homepage
Thoughtfull woman admiring a bright white painting in a classical gold frame

Over the weekend I was asked how to create a joomla 4 module to display images in an attractive way without installing and third party extensions. I did this for the gallery on the home page of my demo site (https://brianstest.site) and I realised I had never shared the steps taken to achieve it.

As with everything there are many ways to achieve the same thing but my objective here was that the gallery of images would be dynamically created from the content so that once setup a website administrator could change the images without having to look at any code.

Step 1 - The content

  • Create a single category
  • Create as many articles as you need making sure that you add both an intro and full image. Don’t forget to size and optimise the images appropriately before uploading them to your site

Step 2 - The module

  • Create a module of type Articles - Newsflash and publish it in the desired template module position
  • Make sure that you select the correct category and number of articles to display in the module options

Step 3 - The template override

This is the closest you will get to any code and you only have to do it once.

  • Create a template override for mod_articles_news by creating a new folder in your template eg ‎/templates/cassiopeia/html/mod_articles_news/

  • Create a new file in that folder called gallery.php

  • Copy and paste the following code into the gallery.php file

    <?php
    
    /**
     * @package     Joomla.Site
     * @subpackage  mod_articles_news
     *
     * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
     * @license     GNU General Public License version 2 or later; see LICENSE.txt
     */
    
    defined('_JEXEC') or die;
    
    use Joomla\CMS\Layout\LayoutHelper;
    
    if (!$list) {
        return;
    }
    
    $templatePath = 'media/templates/site/' . $app->getDocument()->template;
    /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
    $wa = $app->getDocument()->getWebAssetManager();
    $wa->useScript('bootstrap.modal');
    $wa->useScript('bootstrap.carousel');
    $wa->registerAndUseScript('lightbox', $templatePath . '/js/index.bundle.min.js', [], ['defer' => true], []);
    
    ?>
    <div class="container">
        <div class="row gallery">
            <?php foreach ($list as $item) :
            $images = json_decode($item->images);
            $item->imageSrcIntro = htmlspecialchars($images->image_intro, ENT_COMPAT, 'UTF-8');
            $item->imageSrcFull = \Joomla\CMS\Helper\MediaHelper::getCleanMediaFieldValue(htmlspecialchars($images->image_fulltext, ENT_COMPAT, 'UTF-8'));
            $item->imageAltIntro = htmlspecialchars($images->image_intro_alt, ENT_COMPAT, 'UTF-8');
            $item->imageAltFull = htmlspecialchars($images->image_fulltext_alt, ENT_COMPAT, 'UTF-8');
            $item->imageCaptionIntro = htmlspecialchars($images->image_intro_caption, ENT_COMPAT, 'UTF-8');
            $item->imageCaptionFull = htmlspecialchars($images->image_fulltext_caption, ENT_COMPAT, 'UTF-8');
        ?>
            <div class="photo">
                <a href="/<?php echo $item->imageSrcFull; ?>"
                     data-toggle="lightbox" 
                     data-gallery="photo-gallery" 
                     data-caption="<?php echo $item->imageAltFull; ?>">
                    <?php echo LayoutHelper::render (
                        'joomla.html.image',
                        [
                            'src' => $item->imageSrcIntro,
                            'alt' => $item->imageAltIntro,
                        ]
                    ); ?>
                </a>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    

     

Step 4 - The JavaScript

For the final part we need to add one javascript file - Lightbox for Bootstrap 5

All the setup was done for this in step 3 so just download the file (right-click, Save As...) and then upload it to your website and save it into the js folder of your template. eg "‎/media/templates/site/cassiopeia/js/index.bundle.min.js"

Step 5 - The module (again)

- Re-open the module you created in step 2 and on the advanced tab set the first field layout to be gallery

Step 6 - The css (optional)

The actual css to use will depend on your site and template but this is the css I used and placed in the "/media/templates/site/cassiopeia/css/user.css"

.gallery div {
    flex: auto;
    width: 220px;
    margin: .5vw
}

.gallery div img {
    width: 100%;
    height: auto;
    box-shadow: .3rem .4rem .4rem rgba(0,0,0,0.4);
    transition: transform 400ms ease-out
}

.gallery div img:hover {
    transform: scale(1.15)
}

.gallery .photo:hover {
    background: no-repeat center/20% url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="darkmagenta" d="m28.34 24.12-6.5-6.85A10.49 10.49 0 1 0 12.5 23h.55a1 1 0 1 0-.1-2 8.5 8.5 0 1 1 5.4-2.32A8.72 8.72 0 0 1 16.53 20a1 1 0 0 0-.41 1.35.89.89 0 0 0 .36.36v.08l6.77 7.13A3.48 3.48 0 0 0 25.73 30h.09a3.43 3.43 0 0 0 2.39-1 3.47 3.47 0 0 0 .13-4.88zm-1.5 3.47a1.45 1.45 0 0 1-1.06.41 1.51 1.51 0 0 1-1-.46l-6.15-6.49a10.07 10.07 0 0 0 1.14-.93 10.54 10.54 0 0 0 1-1.12l6.16 6.5a1.47 1.47 0 0 1-.09 2.09z"/><path fill="darkmagenta" d="M8.55 8.16a1 1 0 0 0-1.39.29 7.19 7.19 0 0 0 1.17 9.29A1 1 0 0 0 9 18a1 1 0 0 0 .67-1.74A5.32 5.32 0 0 1 8 12.91a5.24 5.24 0 0 1 .84-3.36 1 1 0 0 0-.29-1.39z"/></svg>');
    opacity: 1
}

.gallery img:hover {
    opacity: .5
}

.carousel-item,.carousel-item .bg-dark {
    min-block-size: 300px
}

.carousel-control-next-icon,.carousel-control-prev-icon {
    background-color: var(--brand);
    border-radius: 0
}

.lightbox-caption {
    background-color: var(--brand)
}

.modal-backdrop.show {
    opacity: .8
}

@media screen and (max-width: 400px) {
    .gallery div {
        margin:0
    }

    .gallery {
        padding: 0
    }
}

J o o m l a !

Brian Teeman

Brian Teeman

Who is Brian?

As a co-founder of Joomla! and OpenSourceMatters Inc I've never been known to be lacking an opinion or being too afraid to express it.

Despite what some people might think I'm a shy and modest man who doesn't like to blow his own trumpet or boast about achievements.

Where is Brian?