The Antlers Gotcha That Puts Your Image URL as Text Above Your Image
You're building out a page in Statamic. You've got your hero image field set up, the asset uploaded, everything looks right in the Control Panel.
Then you check the frontend and there's your image... with its full URL printed as text directly above it.
https://example.com/assets/hero-banner.png
[actual image renders here]
What in the world?
What's Happening
If you're coming from Blade, Twig, or basically any other templating engine, you probably wrote something like this:
{{ hero_image }}
<img src="{{ url }}" alt="{{ alt }}">
{{ /hero_image }}
Looks reasonable. Tag pair syntax, access the inner properties. This is how you'd loop through things in most templating systems.
The problem is that {{ hero_image }} on its own line outputs the asset's string representation—which is its URL—before the template enters the tag pair context.
So you get:
- The URL as text (from
{{ hero_image }}) - Then your properly formatted image (from the
<img>tag inside)
I call this "URL bleed" and it's one of those Antlers quirks that trips up basically everyone who didn't grow up with Statamic.
The Fix: Colon Notation
For single asset fields (anything with max_files: 1 in the blueprint), skip the tag pair entirely. Use colon notation to access properties directly:
{{ if hero_image }}
<img
src="{{ hero_image:url }}"
alt="{{ hero_image:alt ?? 'Default alt text' }}"
width="{{ hero_image:width }}"
height="{{ hero_image:height }}"
>
{{ /if }}
No URL bleed. No weirdness. The {{ if hero_image }} check handles cases where the field is empty, and you get direct access to all the asset properties.
When Tag Pairs Are Actually Correct
Tag pair syntax works perfectly fine—and is the right choice—when you're dealing with multiple assets:
{{ gallery_images }}
<img src="{{ url }}" alt="{{ alt }}" class="gallery-item">
{{ /gallery_images }}
When there are multiple items to loop through, the tag pair creates a proper iteration context. No URL bleed issue.
The gotcha specifically hits single assets because Antlers treats {{ hero_image }} as "output this thing" before it sees the closing tag.
A Complete Example
Here's a production-ready hero section pattern that handles everything correctly:
<section class="hero relative overflow-hidden">
{{ if hero_image }}
<img
src="{{ glide:hero_image width="1920" height="1080" fit="crop" quality="85" }}"
alt="{{ hero_image:alt ?? title }}"
width="{{ hero_image:width }}"
height="{{ hero_image:height }}"
class="absolute inset-0 w-full h-full object-cover"
loading="eager"
>
{{ /if }}
<div class="relative z-10 container mx-auto px-4 py-24">
<h1>{{ title }}</h1>
{{ if subtitle }}
<p class="text-xl">{{ subtitle }}</p>
{{ /if }}
</div>
</section>
Note the Glide integration—you can still use image manipulation with colon notation by referencing the field in the Glide tag directly.
Available Properties
When you're using colon notation, here's what you have access to:
| Property | What It Returns |
|---|---|
url |
Public URL to the asset |
path |
Path within the container |
alt |
Alt text from metadata |
width |
Image width in pixels |
height |
Image height in pixels |
size |
File size in bytes |
size_kb |
File size in kilobytes |
extension |
File extension |
mime_type |
MIME type |
focus |
Focal point coordinates |
ratio |
Aspect ratio |
Quick Reference
| Scenario | Pattern |
|---|---|
| Single asset URL | {{ hero_image:url }} |
| Single asset with conditional | {{ if hero_image }}{{ hero_image:url }}{{ /if }} |
| Multiple assets | {{ gallery }}{{ url }}{{ /gallery }} |
| Single asset + Glide | {{ glide:hero_image width="800" }} |
How to Check Your Blueprint
Not sure if a field is single or multiple? Check the blueprint:
# Single asset - use colon notation
handle: hero_image
field:
type: assets
container: assets
max_files: 1
# Multiple assets - use tag pair
handle: gallery
field:
type: assets
container: assets
# No max_files or max_files > 1
This is one of those "once you know it, you never forget it" situations. The URL bleed is annoying enough that you'll remember to use colon notation for single assets going forward.
The Statamic docs do cover this, but when you're moving fast and pulling from other templating experience, tag pair syntax just feels natural. Now you know why it doesn't work the way you'd expect.
Need Help With Statamic?
Book a free Discovery Audit and get expert guidance on your Statamic challenges.
Book a Discovery Audit