Image Attributes
RuntCMS supports three types of editable images. Add the appropriate attribute to your HTML and editors can replace them directly on the live site.
Static assets vs managed images
Not every image on your site needs to go through RuntCMS. Before reaching for data-cms-image, ask one question: will an editor ever need to replace this?
- Yes — use a CMS image attribute (
data-cms-image,data-cms-bg-image, etc.) so the editor can replace it from the live page. - No — upload it as a static asset instead and reference it directly in your HTML.
Icons, illustrations, decorative images, and UI graphics that are part of the design rarely need to be editor-replaceable. For these, create a static folder alongside your CMS content — for example public/assets/ or public/images/ — and upload files there via FTP, SFTP, or your hosting control panel:
public/
assets/
icons/
arrow.svg
logo-mark.svg
illustrations/
hero-graphic.png
Then reference them directly in your HTML:
<img src="{cms:site:path}assets/icons/arrow.svg" alt="">
cms/uploads/ folder is managed by RuntCMS — its Image Library tracks what's in use and can delete orphaned files. Static assets uploaded there directly (not through a CMS slot) will appear as orphaned and could be accidentally removed. A separate assets/ folder avoids this entirely.
Inline images — data-cms-image
Add data-cms-image="name" to any <img> tag to make it replaceable:
<img
src="{cms:site:path}/cms/uploads/team-photo.jpg"
alt="Our team"
data-cms-image="team-photo"
>
When logged in, hovering over this image shows a Replace Image button. Clicking it opens the image upload panel.
The attribute value (team-photo) is the slot name — a unique identifier for this image on this page.
src attribute. Once an editor uploads a replacement, the database-stored URL is used instead and the original src is ignored.
Global images — data-cms-global-image
Use data-cms-global-image="name" for images that should be the same on every page — a logo, for example:
<img
src="{cms:site:path}/cms/uploads/logo.png"
alt="Company logo"
data-cms-global-image="site-logo"
>
Replacing a global image updates it across every page that uses that slot name. The image panel notes when you're replacing a global image so editors aren't surprised.
Background images — data-cms-bg-image
Use data-cms-bg-image="name" on any element that has a CSS background image you want editors to be able to replace:
<section
class="hero"
data-cms-bg-image="hero-bg"
style="background-image: url('{cms:site:path}/cms/uploads/hero-default.jpg');"
>
<h1>Welcome</h1>
</section>
When logged in, hovering over this section shows a Replace Background button. The upload and versioning process is identical to inline images.
background-size: cover; background-position: center; in your CSS for full-width hero sections.
Text colour variant — data-cms-text-variant
When an editor replaces a background image with a much lighter or darker photo, the text on top of it can become unreadable. The optional data-cms-text-variant attribute lets you offer the editor a simple Text: Light / Text: Dark toggle directly on the page, without them needing admin access.
Add it to the same element as data-cms-bg-image:
<section
class="hero dark-text"
data-cms-bg-image="hero-bg"
data-cms-text-variant="dark-text,light-text"
style="background-image: url('{cms:site:path}/cms/uploads/hero.jpg');"
>
<h1>Welcome</h1>
</section>
The value is a comma-separated list of CSS class names the editor can cycle through. The first class listed becomes the default when the slot is first created.
In your stylesheet, define what each class does:
.dark-text { color: rgba(15, 15, 15, 0.9); }
.light-text { color: #ffffff; }
When an editor hovers over the section, a Text colour toggle button appears alongside the Replace Background button. Clicking it cycles through your listed classes. The choice is saved when the editor clicks Save in the runtbar.
Built-in defaults
If you don't add data-cms-text-variant, RuntCMS still creates a text variant record using its two built-in classes:
runt-text-dark— near-black text, suitable for light backgroundsrunt-text-light— white text, suitable for dark backgrounds
These classes are already defined in runtbar.css and work without any extra CSS on your part. The default starting class is runt-text-dark.
data-cms-text-variant before any editor loads the page.
How image slots work
RuntCMS uses an "image slot" model. Each data-cms-image, data-cms-global-image, or data-cms-bg-image attribute defines a slot. Slots are provisioned (created in the database) automatically the first time a logged-in user visits the page.
Each slot keeps the current image plus the three most recent previous versions. When an image is replaced, the old file is moved from public/cms/uploads/ to storage/archived-images/ — a non-public directory blocked by .htaccess. Archived images are not directly web-accessible; they are served through a PHP proxy to authenticated users only. When a fifth version is uploaded, the oldest archived file is permanently deleted from disk. The Image Library in the admin panel shows images from both directories.
Summary table
| Attribute | Scope | Element type |
|---|---|---|
data-cms-image="name" |
Page-specific | <img> |
data-cms-global-image="name" |
Site-wide | <img> |
data-cms-bg-image="name" |
Page-specific | Any element with CSS background-image |
Image size guidelines
Uploaded images must be under 18 megapixels (width × height). Very high-resolution camera photos should be downsized before uploading. As a guide:
- Hero / banner images: 2400px wide, JPEG at 80% quality
- Team / profile photos: 800px wide
- Logos: PNG with transparency, 400–600px wide
RuntCMS does not resize images on upload — it stores them as-is. Use appropriate dimensions to keep page load times fast.
Alt text
The alt attribute is set in your template HTML, not by the editor at upload time. Make sure you provide meaningful alt text in your template for important images. For decorative images, use alt="".
Editors who need to update alt text for accessibility reasons will need admin access to edit the page HTML file directly.
Privacy and archiving
When an editor replaces an image, the old file is moved to storage/archived-images/ — a directory outside the web root, protected by .htaccess. This means:
- Old images are not publicly accessible. Anyone with a cached or bookmarked URL to a replaced image will get a 404.
- Search engines cannot index old images. The default
robots.txtalso includesDisallow: /cms/uploads/to prevent indexing of current images. - Admins can still restore old versions. Archived images are served through a PHP proxy to authenticated users only.
- Three archived versions are kept per slot. When a fourth replacement happens, the oldest archived file is permanently deleted from disk.
The storage/ directory must be writable by the web server, same as public/cms/uploads/. It is created automatically during installation.