Saat saya mulai mengedit tema Ghost, saya sadar menulis <img> berulang itu tidak efisien — apalagi jika ingin mendukung AVIF/WebP dan ukuran responsif.

Karena itu, saya membuat komponen gambar reusable menggunakan partial Handlebars. Berikut cara kerjanya dan kenapa penting untuk performa.


🧩 Konsep Dasar

Ghost menggunakan templating Handlebars (.hbs). Kamu bisa membuat partial agar bisa dipakai berulang dengan cara:

{{> image src=feature_image alt=feature_image_alt class="rounded-xl"}}

Cara ini menjaga konsistensi sekaligus memudahkan maintenance tema.


💡 Penjelasan Kode

Berikut contoh partial partials/image.hbs:

{{!--
Reusable image template for Ghost themes
Params:
  - src (required)
  - alt (optional)
  - class (optional)
  - loading (optional)
  - sizes (optional)
  - default_src_size (optional, defaults to "xl")
  - width / height (optional)
  - decoding (optional)
  - fetchpriority (optional)
  - draggable (optional)
  - animated (optional)
  - excluded_src_sizes (optional, bracket-separated list: e.g. "[xxs][xs]")
Example usage:
{{> image
    src=feature_image
    alt=feature_image_alt
    class="rounded-xl"
    loading="lazy"
    sizes="(max-width: 768px) 100vw, 768px"
    excluded_src_sizes="[xxs][xs]"
}}
--}}

{{#if src}}
  <picture{{#if class}} class="{{class}}"{{/if}}>
      {{#unless animated}}
      <source
          srcset="
              {{^match excluded_src_sizes "~" "[xxs]"}}{{img_url src size="xxs" format="avif"}} 30w,{{/match}}
              {{^match excluded_src_sizes "~" "[xs]"}}{{img_url src size="xs" format="avif"}} 150w,{{/match}}
              {{^match excluded_src_sizes "~" "[s]"}}{{img_url src size="s" format="avif"}} 300w,{{/match}}
              {{^match excluded_src_sizes "~" "[m]"}}{{img_url src size="m" format="avif"}} 720w,{{/match}}
              {{^match excluded_src_sizes "~" "[l]"}}{{img_url src size="l" format="avif"}} 960w,{{/match}}
              {{^match excluded_src_sizes "~" "[xl]"}}{{img_url src size="xl" format="avif"}} 1200w,{{/match}}
              {{^match excluded_src_sizes "~" "[xxl]"}}{{img_url src size="xxl" format="avif"}} 2000w,{{/match}}
              {{img_url src}}"
          {{#if sizes}}sizes="{{sizes}}"{{/if}}
          type="image/avif">
      {{/unless}}

      <source
          srcset="
              {{^match excluded_src_sizes "~" "[xxs]"}}{{img_url src size="xxs" format="webp"}} 30w,{{/match}}
              {{^match excluded_src_sizes "~" "[xs]"}}{{img_url src size="xs" format="webp"}} 150w,{{/match}}
              {{^match excluded_src_sizes "~" "[s]"}}{{img_url src size="s" format="webp"}} 300w,{{/match}}
              {{^match excluded_src_sizes "~" "[m]"}}{{img_url src size="m" format="webp"}} 720w,{{/match}}
              {{^match excluded_src_sizes "~" "[l]"}}{{img_url src size="l" format="webp"}} 960w,{{/match}}
              {{^match excluded_src_sizes "~" "[xl]"}}{{img_url src size="xl" format="webp"}} 1200w,{{/match}}
              {{^match excluded_src_sizes "~" "[xxl]"}}{{img_url src size="xxl" format="webp"}} 2000w,{{/match}}
              {{img_url src}}"
          {{#if sizes}}sizes="{{sizes}}"{{/if}}
          type="image/webp">

      <img
          srcset="
              {{^match excluded_src_sizes "~" "[xxs]"}}{{img_url src size="xxs"}} 30w,{{/match}}
              {{^match excluded_src_sizes "~" "[xs]"}}{{img_url src size="xs"}} 150w,{{/match}}
              {{^match excluded_src_sizes "~" "[s]"}}{{img_url src size="s"}} 300w,{{/match}}
              {{^match excluded_src_sizes "~" "[m]"}}{{img_url src size="m"}} 720w,{{/match}}
              {{^match excluded_src_sizes "~" "[l]"}}{{img_url src size="l"}} 960w,{{/match}}
              {{^match excluded_src_sizes "~" "[xl]"}}{{img_url src size="xl"}} 1200w,{{/match}}
              {{^match excluded_src_sizes "~" "[xxl]"}}{{img_url src size="xxl"}} 2000w,{{/match}}
              {{img_url src}}"
          {{#if sizes}}sizes="{{sizes}}"{{/if}}
          src="{{#if default_src_size}}{{img_url src size=default_src_size}}{{else}}{{img_url src size="xl"}}{{/if}}"
          {{#if alt}}alt="{{alt}}"{{/if}}
          {{#if class}}class="{{class}}"{{/if}}
          {{#if loading}}loading="{{loading}}"{{/if}}
          {{#if decoding}}decoding="{{decoding}}"{{/if}}
          {{#if fetchpriority}}fetchpriority="{{fetchpriority}}"{{/if}}
          {{#if draggable}}draggable="{{draggable}}"{{/if}}
          {{#if width}}width="{{width}}"{{/if}}
          {{#if height}}height="{{height}}"{{/if}}>
  </picture>
{{/if}}

<picture> digunakan untuk menyediakan beberapa format gambar sekaligus. Ghost akan menyesuaikan ukuran gambar sesuai kebutuhan layar pengguna.

<picture>: The Picture element - HTML | MDN
The <picture> HTML element contains zero or more <source> elements and one <img> element to offer alternative versions of an image for different display/device scenarios.

⚙️ Parameter Opsional

Kamu bisa menambahkan:

  • excluded_src_sizes → melewati ukuran tertentu
  • sizes → mengatur perilaku responsif
  • loading, decoding, fetchpriority → membantu optimasi performa

🧠 Kenapa Ini Penting

Dengan komponen ini:

  • Kode jadi lebih bersih dan mudah dikelola
  • Skor performa (Lighthouse) meningkat
  • Semua gambar otomatis mengikuti best practice
Reusable image template for Ghost themes
Reusable image template for Ghost themes. GitHub Gist: instantly share code, notes, and snippets.

Membuat Komponen Gambar Reusable di Ghost Theme

Pelajari cara membuat komponen gambar reusable di Ghost menggunakan Handlebars. Optimalkan performa situs dan permudah pengelolaan gambar.

Membuat Komponen Gambar Reusable di Ghost Theme