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="">
Keep static assets out of cms/uploads/. The 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.

Initial src: On first load, the image shown is whatever is in the 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.

CSS background-size and position: Your CSS handles how the background image is sized and positioned. RuntCMS only manages the image source URL. Use 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 backgrounds
  • runt-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.

One-time provisioning: The default class is set the first time a logged-in user visits the page. To change the default for a new section, list the preferred class first in 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

AttributeScopeElement 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.txt also includes Disallow: /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.

RuntCMS 0.9 Documentation