Files
Brummel 83726ed040 feat(hero): responsive srcset for carousel slides
Phones were downloading the full 1.5 MB / 2 MB hero JPEG. Now the
image macro emits a `srcset` ladder (480/768/1200/1600/2560/3840/5345 w)
with `sizes="100vw"`, so a 480 px-wide phone picks the ~19 KB variant
and 5K screens still get the native resolution.

Also drop `loading="lazy"` on the first slide — it is the LCP element
and should load eager.

Macro changes:
- Add `srcset_widths` (CSV string, since Tera macros only allow scalar
  defaults) and `sizes` parameters.
- Add `lazy=true` parameter; callers can pass `lazy=false` for
  above-the-fold images.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:31:47 +02:00

38 lines
2.3 KiB
HTML

{# Image-rendering macro, used both by templates (directly via import)
and indirectly by the `img` shortcode (which forwards to it).
Modes:
- `srcset_widths="480,768,…"` non-empty: emit a responsive `srcset`
over those widths. `sizes` should describe the layout (e.g.
"100vw" for the full-width hero). The `src` fallback uses the
largest width. CSV form because Tera macros only allow scalar
defaults, not arrays.
- `width > 0`: single resized variant via Zola's image pipeline.
- `width = 0` (default): raw <img> straight from /static/images/.
In all modes we omit the HTML width/height attributes — the theme CSS
sizes the image, matching the live Grav site's pattern. Avoiding the
HTML width attribute sidesteps a stretch artefact triggered by
Bootstrap-3's `img { height: auto !important }` interacting with
`.float-right` padding.
`lazy=false` switches off `loading="lazy"`. Use it for above-the-fold
images (LCP candidates) like the first hero slide. #}
{% macro render(src, width=0, alt="", class="", srcset_widths="", sizes="", lazy=true) %}
{%- set width = width | int -%}
{%- set loading_attr = "" -%}
{%- if lazy -%}{%- set loading_attr = ' loading="lazy"' -%}{%- endif -%}
{%- if srcset_widths -%}
{%- set widths = srcset_widths | split(pat=",") -%}
{%- set largest = widths | last | trim | int -%}
{%- set fallback = resize_image(path="static/images/" ~ src, width=largest, op="fit_width", quality=82) -%}
<img src="{{ fallback.url | safe }}" srcset="{%- for w_str in widths -%}{%- set w = w_str | trim | int -%}{%- set r = resize_image(path="static/images/" ~ src, width=w, op="fit_width", quality=82) -%}{{ r.url | safe }} {{ w }}w{%- if not loop.last -%}, {%- endif -%}{%- endfor -%}" sizes="{{ sizes }}" alt="{{ alt }}"{% if class %} class="{{ class }}"{% endif %}{{ loading_attr | safe }}>
{%- elif width > 0 -%}
{%- set resized = resize_image(path="static/images/" ~ src, width=width, op="fit_width", quality=85) -%}
<img src="{{ resized.url | safe }}" alt="{{ alt }}"{% if class %} class="{{ class }}"{% endif %}{{ loading_attr | safe }}>
{%- else -%}
<img src="/images/{{ src | safe }}" alt="{{ alt }}"{% if class %} class="{{ class }}"{% endif %}{{ loading_attr | safe }}>
{%- endif -%}
{% endmacro render %}