Where is image alt text stored in Jahia, and why does removing it not stick?
Question
Where is image alt text stored in Jahia, and why does removing it not stick?
Answer
"Alt text" is three different things in Jahia depending on where the image is, and they do not share a property. Most confusion here comes from assuming they do.
| Where the image is | What stores the alt text |
|---|---|
| An image component on a page | j:alternateText on the content node |
| An image inside a rich text field | nothing - it is raw HTML in the text string |
| A file in the document manager | nothing at all |
There is no alt text on a file
This surprises people. A file in the document manager has no alt property. The
mixin that marks a node as an image, jmix:image, carries exactly two
properties - verified on 8.2.3.2:
j:height : LONG (protected)
j:width : LONG (protected)
Both are protected, so they are filled by metadata extraction on upload and are not editable.
Alt text is a property of the use of an image, not of the file, which is correct: the same picture needs different alt text in different places.
What a file does have is generic metadata - jcr:title and jcr:description
(both internationalized), plus optional j:keywords, j:tagList and
j:defaultCategory mixins, and jmix:exif for JPEGs.
j:alt, j:altText and jmix:accessibility do not exist. Querying the last
two on a running 8.2.3.2 returns null. The only real name is j:alternateText.
Why clearing the alt text does not stick
Three different causes, one per context.
The image component falls back to the node name
The shipped view does not emit an empty alt when the field is blank - it
substitutes the content node's name:
<img src="${imageUrl}" alt="${fn:escapeXml(not empty title.string ? title.string : currentNode.name)}" .../>
So clearing the field gives you alt="my-image-component-1", not alt="".
For a decorative image that genuinely needs an empty alt, the stock view cannot produce one. Override the view in your template module and drop the fallback.
CKEditor 4 refills it from the file name every time you pick
This is the most common cause. When you pick an image through the Jahia picker, Content Editor writes the picked file's name straight into the alt field:
const altElementId = dialog.getName() === 'image2' ? 'alt' : 'txtAlt';
...
contentElement.setValue(pickerResult.name);
So: clear the alt, re-pick the image, and the alt is back. Clear it after picking, and do not re-open the picker afterwards.
CKEditor 5 has the opposite problem
Inserting an image through the Jahia picker on CK5 sets no alt attribute at all. Use the "Change image text alternative" button in the image balloon toolbar.
(Check which editor you are on first - a stock Jahia 8.2 runs CKEditor 4.)
Rich text alt text is static, and that is by design
In a rich text field the whole <img alt="..."> is just characters inside the
text property. Jahia does intercept image markup on save, but only the URL
attributes - src, srcset, data-src, data-srcset - which it rewrites into
internal references so links survive a move or rename.
alt is not in that list. It is copied through verbatim and never bound to
the file node. So renaming the file, or editing its jcr:title later, does not
change alt text already saved in rich text. There is no "dynamic alt text" in a
rich text field without custom rendering.
What "Internal link" does on a document-manager image
Nothing to do with alt text. It is the j:linkType dropdown, and it makes the
image clickable:
| Value | Effect |
|---|---|
none (default) | not a link |
internal | adds jmix:internalLink, exposing j:linknode - a reference to a page or content inside this Jahia |
external | adds jmix:externalLink, exposing j:url and j:linkTitle |
The title rendered on the resulting <a> is the target node's displayable
name, not something you type. j:target controls the window.
Adding alt text to your own image field
There is no reusable alt-text mixin to extend. j:alternateText is declared
inline on each shipped image-reference type, so copy the pattern into your own
definition:
[myt:myImageComponent] > jnt:content, jmix:nodeReference, jmix:multimediaContent, jmix:editorialContent
- j:node (weakreference, picker[type='image']) internationalized < 'jmix:image'
- j:alternateText (string) internationalized
Or simply extend the existing type - [myt:x] > jnt:imageReferenceLink inherits
j:alternateText.
Keep j:alternateText as the name. It is a convention rather than an inherited
contract, but views and tooling expect it.
WebP and AVIF
Core does not support either. The metadata extraction config registers image
parsers for bmp, gif, png, tiff, wbmp, x-icon, x-psd, x-xcf and jpeg. Neither
image/webp nor image/avif appears anywhere in it.
That has a consequence beyond "not optimised". Dimensions come from that
extraction, and setting j:width/j:height is what causes jmix:image to be
added to the node. The image picker only offers jmix:image nodes. So a .webp
or .avif upload gets no dimensions, never becomes a jmix:image, and
therefore does not appear in the image picker at all - it can still be
uploaded and linked as an ordinary file.
For modern formats, the Academy documents an optional media-optimization module (Cloudimage) which converts images to WebP via a CDN. No AVIF output path was found in core or in that module's documentation.
This article was drafted with AI assistance, then reviewed and curated by Jahia Customer Support engineers before publication.