Image Zoom - Single image — with caption

  1. Demo
  2. Docu
  3. Full Screen ↗
  • Documentation
  • HTML code
  • Configuration
  • Image Zoom

    What it does

    The jcrafts-zoom component adds click-to-zoom and gallery slideshow behaviour to images inside Joomla article content areas. Clicking any eligible <img> opens it full-size in a native <joomla-dialog>; images sharing the same data-zoom-gallery name are grouped into a keyboard-navigable slideshow.

    Key Features

    • Zero markup changes: works via event delegation on existing article images — no wrapper element required.
    • Single-image zoom: opens the full-resolution image in a <joomla-dialog type="image"> with an edge-to-edge, overlay close button.
    • Gallery slideshow: groups images by data-zoom-gallery name; renders prev/next navigation and a live position counter inside a <joomla-dialog type="inline">.
    • Smart caption resolution: reads captions from a sibling <figcaption>, data-caption attribute, or title attribute — in that priority order.
    • Full-resolution source: always uses img.getAttribute('src'), not currentSrc, so the original URL is opened even when plg_content_responsive rewrites srcset.
    • Accessibility: keyboard navigation (← →), aria-live counter, aria-label on the inner <dialog>, and focus-visible outlines on all interactive elements.

    How to use

    1. Basic single-image zoom

    No extra attributes are needed. Any <img> found inside a standard Joomla content container is automatically zoom-enabled.

    WebC (design-system component):

    
    <link rel="stylesheet" href="/assets/css/template/jcrafts-zoom.css">
    
    
    <article>
      <figure>
        <img src="photo.jpg" alt="A scenic view" loading="lazy" decoding="async">
        
      </figure>
    </article>
    
    
    

    Raw HTML (in a Joomla article):

    <figure>
      <img src="photo.jpg" alt="A scenic view" loading="lazy">
      <figcaption>A scenic view at golden hour.</figcaption>
    </figure>
    

    2. Gallery slideshow

    Add the same data-zoom-gallery value to every image that belongs to the group. Clicking any one of them opens the slideshow starting at that image.

    WebC:

    
    <link rel="stylesheet" href="/assets/css/template/jcrafts-zoom.css">
    
    
    <article>
      <figure>
        <img src="img1.jpg" alt="First" loading="lazy" decoding="async">
        <figcaption>Caption one.</figcaption>
      </figure>
    <figure>
        <img src="img2.jpg" alt="Second" loading="lazy" decoding="async">
        
      </figure>
    <figure>
        <img src="img3.jpg" alt="Third" loading="lazy" decoding="async">
        <figcaption>Caption three.</figcaption>
      </figure>
    </article>
    
    
    

    Raw HTML:

    <img src="img1.jpg" alt="First"  data-zoom-gallery="my-gallery">
    <img src="img2.jpg" alt="Second" data-zoom-gallery="my-gallery">
    <img src="img3.jpg" alt="Third"  data-zoom-gallery="my-gallery">
    

    3. Captions

    Captions are resolved automatically in the following priority order:

    1. <figcaption> that is a sibling inside the same <figure> (standard TinyMCE markup).
    2. data-caption attribute on the <img>.
    3. title attribute on the <img>.
    <!-- figcaption (highest priority) -->
    <figure>
      <img src="photo.jpg" alt="...">
      <figcaption>This text becomes the caption.</figcaption>
    </figure>
    
    <!-- data-caption -->
    <img src="photo.jpg" alt="..." data-caption="This text becomes the caption.">
    
    <!-- title (lowest priority) -->
    <img src="photo.jpg" alt="..." title="This text becomes the caption.">
    

    4. Opt-out

    Add the class no-zoom to an image or any of its ancestors to exclude it from zoom entirely. The click handler is skipped and the cursor: zoom-in affordance is removed.

    <!-- on the image itself -->
    <img src="photo.jpg" alt="..." class="no-zoom">
    
    <!-- on the wrapping figure (also excludes the figcaption from triggering zoom) -->
    <figure class="no-zoom">
      <img src="photo.jpg" alt="...">
      <figcaption>Not zoomable.</figcaption>
    </figure>
    
    <!-- on any ancestor container — all images inside are excluded -->
    <div class="no-zoom">
      <img src="photo.jpg" alt="...">
      <img src="other.jpg" alt="...">
    </div>
    

    Configuration options

    These are the props accepted by the WebC component (jcrafts-zoom-l.webc) and passed through .config.js:

    Prop Type Default Description
    images Array< { src, alt, caption }> One or more image objects to render.
    gallery boolean false When true, all images share the same data-zoom-gallery attribute and open as a slideshow.
    galleryName string '' The gallery group identifier. Must be unique per page when multiple galleries are present.

    How it works

    The JavaScript (jcrafts-zoom.js) attaches a single delegated click listener to document. On each click it checks whether the event target matches CONTENT_SELECTOR — a list of common Joomla article wrappers:

    '.item-page img',
    '.com-content-article img',
    '.article-body img',
    '.article-fulltext img',
    '.article-introtext img',
    'article img'
    

    If the matched image has a data-zoom-gallery attribute, openGallery() is called; otherwise openZoom() is called. Both functions create a <joomla-dialog> element, call .show() (which appends it to <body> and runs connectedCallback synchronously), and clean up on the joomla-dialog:close event.

    img.getAttribute('src') is used instead of img.currentSrc so that the full-resolution original URL is always opened, even after plg_content_responsive has substituted a resized srcset entry into currentSrc.

    CSS classes

    Class Element Purpose
    .jcrafts-gallery <div> wrapper Grid container for the slideshow (prev button / figure / next button / counter).
    .jcrafts-gallery-figure <figure> Holds the active image and optional <figcaption>.
    .jcrafts-gallery-prev <button> Navigate to the previous image. Hidden when the group has only one image.
    .jcrafts-gallery-next <button> Navigate to the next image. Hidden when the group has only one image.
    .jcrafts-gallery-counter <div> Shows the current position (e.g. 2 / 5). Has aria-live="polite".

    CSS custom properties

    Property Fallback Used on
    --color-primary currentColor Focus outline on images and nav buttons; nav button hover colour.
    --color-neutral-600 #6c757d Default colour of nav buttons, figcaption text, and counter text.
    --font-size-sm 0.875rem Font size for figcaption and counter text.

    Accessibility

    • Keyboard navigation: inside an open gallery dialog, ArrowLeft and ArrowRight move between images. The keydown listener is removed on close to prevent memory leaks.
    • aria-live="polite": the .jcrafts-gallery-counter element announces position changes to screen readers without interrupting ongoing speech.
    • aria-label on <dialog>: set directly on the inner native <dialog> element (not the <joomla-dialog> host) so assistive technology receives the label correctly. The value is the image caption, falling back to alt text or the gallery name.
    • focus-visible outlines: all interactive elements (img, .jcrafts-gallery-prev, .jcrafts-gallery-next) show a 2px solid outline keyed to --color-primary only when focused via keyboard, keeping the UI clean for pointer users.
    • Semantic caption association: when a caption is present in a single-image zoom, the <img> is wrapped in a <figure> / <figcaption> pair inside the dialog body for correct AT association.

    Reference:

    • JavaScript: tmpl_connemarakraemer/design-system/src/_includes/components/jcrafts-zoom/jcrafts-zoom.js
    • CSS: tmpl_connemarakraemer/design-system/src/_includes/components/jcrafts-zoom/jcrafts-zoom.css
    • WebC template: tmpl_connemarakraemer/design-system/src/_includes/components/jcrafts-zoom/jcrafts-zoom-l.webc
    • Config / variants: tmpl_connemarakraemer/design-system/src/_includes/components/jcrafts-zoom/jcrafts-zoom.config.js
    • Depends on: Joomla's joomla-dialog web component (loaded via <joomla-dialog-l> in the WebC template)

    Tip: Images inside standard Joomla article containers are zoom-enabled automatically — no extra markup is needed for single-image zoom. Add data-zoom-gallery="name" (or use the WebC component with gallery: true) only when you want to group images into a slideshow.


    HTML Code (Demo)

    <link rel="stylesheet" href="/assets/css/template/jcrafts-zoom.css">
    <article>
      <figure>
        <img src="https://picsum.photos/seed/jczoom2/1200/800" alt="Mountain landscape" loading="lazy" decoding="async">
        <figcaption>A sweeping mountain landscape at golden hour.</figcaption>
      </figure>
    </article>

    Configuration

    Component Config: Teasers/jcrafts-zoom/jcrafts-zoom.config.js
    {
      "images": [
        {
          "src": "https://picsum.photos/seed/jczoom2/1200/800",
          "alt": "Mountain landscape",
          "caption": "A sweeping mountain landscape at golden hour."
        }
      ],
      "gallery": false,
      "galleryName": ""
    }