# Bülten bannerı: ücretsiz Shopify bölümü

> Kompakt bir e-posta kaydı: tek satırlık bir şerit ya da isteğe bağlı görselli, footer tarzı bir blok. Aboneler, uygulama olmadan Shopify müşterisi olur.

Bülten bannerı, iki görünümde kompakt bir e-posta kaydı sunan ücretsiz bir Shopify bölümüdür: başlık, kısa bir satır ve e-posta alanının tek sırada durduğu bir şerit ya da isteğe bağlı bir görselin yanında başlık, metin, form ve küçük notlardan oluşan daha büyük, footer tarzı bir blok. Shopify’ın kendi müşteri formunu kullanır; her abone "newsletter" ve isterseniz kendi etiketinizle müşteri olarak kaydedilir, başarı ve hata mesajlarınız gösterilir. JavaScript gerektirmez ve Online Store 2.0 temalarında uygulama olmadan çalışır.

- **Kategori:** Formlar ve bülten
- **Kullanıldığı yerler:** Ana sayfa, Footer alanı, Blog, Her sayfa
- **Okuduğu veri:** Shopify müşteri formu
- **Boyut:** 2 dosyada 20 KB, JavaScript yok
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/bulten-banneri
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-newsletter-banner.html
- **Eklenme tarihi:** 2026-11-02

## Ne işe yarar

- Ana sayfada bölümler arasında ya da blog yazılarının altında ince bir kayıt şeridi
- Temanın footer’ının hemen üstünde, yanında fotoğraf olan bir kayıt bloğu
- Yakında açılacak ya da lansman sayfasında bekleme listesi kaydı

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · Newsletter banner” adıyla görünür. Kimlikler, türler, etiketler ve varsayılan değerler bölümün şemasından gelir. Etiketler tema düzenleyicide göründüğü gibi İngilizcedir.

### Bölüm ayarları

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `variant` | `select` | Style | strip | `strip`, `footer` |

### Content

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `heading` | `inline_richtext` | Heading | Get the studio letter |  |
| `heading_tag` | `select` | Heading tag | h2 | `h1`, `h2`, `h3`, `p` |
| `heading_size` | `select` | Heading size | medium | `small`, `medium`, `large` |
| `text` | `richtext` | Text | `<p>New pieces and kiln days, once a month.</p>` |  |

### Form

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `input_label` | `text` | Field label | Email address |  |
| `show_label` | `checkbox` | Show field label | `false` |  |
| `placeholder` | `text` | Field placeholder | you@example.com |  |
| `button_label` | `text` | Button label | Subscribe |  |
| `customer_tag` | `text` | Extra customer tag | – |  |
| `small_print` | `inline_richtext` | Small print | `Unsubscribe any time. Read our <a href="/policies/privacy-policy">privacy policy</a>.` |  |
| `success_message` | `text` | Success message | Thanks for subscribing. See you in your inbox. |  |
| `error_message` | `text` | Error message | We couldn't sign you up. Please check your email address. |  |

### Image (footer block)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `image` | `image_picker` | Desktop image | – |  |
| `image_mobile` | `image_picker` | Mobile image | – |  |
| `image_position` | `select` | Image position on desktop | right | `left`, `right` |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `section_width` | `select` | Width | page | `page`, `full` |
| `text_alignment` | `text_alignment` | Text alignment on desktop | left |  |
| `text_alignment_mobile` | `select` | Text alignment on mobile | left | `left`, `center`, `right` |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #2A2420 |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_text` | `color` | Text | #F4EFE8 |  |
| `color_accent` | `color` | Accent (button) | #E8D9C4 |  |
| `color_accent_text` | `color` | Text on accent | #2A2420 |  |
| `color_field_bg` | `color` | Field background | #FFFDF9 |  |
| `color_field_text` | `color` | Field text | #2A2420 |  |

### Spacing and visibility

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `40` | 0–160 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `40` | 0–160 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `32` | 0–120 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `32` | 0–120 px, step 4 |
| `show_on` | `select` | Show on | all | `all`, `desktop`, `mobile` |
| `anchor_id` | `text` | Anchor ID | – |  |

### Motion

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `animate` | `checkbox` | Rise in on scroll | `false` |  |

## Kurulum

### Shopify yönetim panelinde

1. Canlı temanızda değil, bir kopyasında çalışın: Shopify yönetim panelinde **Online Mağaza > Temalar** sayfasına gidin, mevcut temanızın **…** menüsünü açın ve **Kopya oluştur**’u seçin.
2. Kopyada **…** menüsünü açın ve **Kodu düzenle**’yi seçin.
3. `sections` klasörüne `lib-newsletter-banner.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-newsletter-banner.liquid` içeriğini yapıştırıp kaydedin.
4. `lib-image.liquid` dosyalarını da aynı şekilde `snippets` klasörüne ekleyin. Başka bir Lib bölümünden gelen aynı adlı bir snippet zaten varsa aynı dosyadır; tek kopya yeterli.
5. Kopyada **Özelleştir**’i açın, **Bölüm ekle**’yi seçin ve **Lib · Newsletter banner** bölümünü ekleyin. Örnek içeriği kendi içeriğinizle değiştirin, renkleri ayarlayın.
6. Kopyayı önizleyin, her şey doğru göründüğünde yayınlayın.

### Shopify CLI ile

Yerel tema klasörünüzde dosyaları indirin ve yalnızca bunları yayında olmayan bir temaya gönderin (temanın kimliğini `shopify theme list` gösterir):

```sh
curl -fsSL -o sections/lib-newsletter-banner.liquid https://lintelagency.com/resources/shopify-sections/files/lib-newsletter-banner.liquid
curl -fsSL -o snippets/lib-image.liquid https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-newsletter-banner.liquid --only snippets/lib-image.liquid
```

Canlı temaya asla göndermeyin: her zaman yayında olmayan bir temanın kimliğini verin, `--live` ya da `--allow-live` kullanmayın. Ardından bölümü yukarıdaki gibi tema düzenleyicide ekleyin.

## Dosyalar

- [sections/lib-newsletter-banner.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-newsletter-banner.liquid): `sections/` klasörüne
- [snippets/lib-image.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid): `snippets/` klasörüne

## Sık sorulan sorular

### Bülten kaydı bölümünden farkı ne?

Bülten kaydı; ortalanmış, yan görselli ve görselli banner düzenleri sunan tam boy bir bölümdür. Bülten bannerı ise onun kompakt sürümüdür: diğer bölümlerin arasına sığan tek satırlık bir şerit ya da footer tarzı bir blok; Shopify müşteri formu aynıdır.

### Aboneler nereye gidiyor?

Shopify müşterilerinize; "newsletter" ve belirlediyseniz kendi etiketinizle (örneğin "footer") kaydedilirler, böylece nereden kaydolduklarını görebilirsiniz. Onlara Shopify Email ya da müşterileri eşitleyen bir e-posta uygulamasıyla e-posta gönderebilirsiniz.

### Müşteri kaydolduktan sonra ne görüyor?

Sayfa bölümün olduğu yerde yeniden yüklenir ve formun yerini başarı mesajınız alır. E-posta kabul edilmezse hata mesajınız Shopify’ın kendi açıklamasıyla birlikte görünür ve alan ekran okuyucular için geçersiz olarak işaretlenir.

### Şerit footer’ın içinde durabilir mi?

Şeridi şablonun son bölümü olarak yerleştirin ya da footer grubuna bölüm eklemeye izin veren temalarda oraya ekleyin; seçtiğiniz tam genişliği ya da sayfa genişliğini kaplar.

## Kaynak kod

### sections/lib-newsletter-banner.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Newsletter banner: a compact sign-up in two styles. "Strip" puts the heading, a short line and
  the email field with its button in one row on desktop (stacked on mobile), for between sections
  or above the footer. "Footer block" is a larger block with heading, text, form and small print,
  plus an optional image beside it. Both use Shopify's customer form: the email is added as a
  customer tagged "newsletter" (plus an optional tag of your own); success and error messages are
  settings. No JavaScript.
  Depends on: snippets/lib-image.liquid
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign heading_tag = s.heading_tag | default: 'h2'
  assign form_id = 'lib-nl-banner-' | append: section.id
  assign input_id = 'LibNlBannerEmail-' | append: section.id
  assign error_id = 'LibNlBannerError-' | append: section.id
  assign note_id = 'LibNlBannerNote-' | append: section.id
  assign tags = 'newsletter'
  if s.customer_tag != blank
    assign tags = tags | append: ',' | append: s.customer_tag
  endif
  assign has_image = false
  if s.variant == 'footer' and s.image != blank or s.variant == 'footer' and s.image_mobile != blank
    assign has_image = true
  endif
-%}

<div
  class="lib-nl-banner lib-nl-banner--{{ s.variant }} lib-nl-banner--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-image-pos="{{ s.image_position }}"
  {% if has_image %}
    data-has-image
  {% endif %}
  {% if s.animate %}
    data-animate
  {% endif %}
  style="
    --lib-bg: {{ s.color_bg }};
    {% if s.color_bg_gradient != blank %}--lib-bg-image: {{ s.color_bg_gradient }};{% endif %}
    --lib-text: {{ s.color_text }};
    --lib-accent: {{ s.color_accent }};
    --lib-accent-text: {{ s.color_accent_text }};
    --lib-field-bg: {{ s.color_field_bg }};
    --lib-field-text: {{ s.color_field_text }};
    --lib-pt: {{ s.padding_top }}px;
    --lib-pb: {{ s.padding_bottom }}px;
    --lib-pt-m: {{ s.padding_top_mobile }}px;
    --lib-pb-m: {{ s.padding_bottom_mobile }}px;
  "
>
  <div class="lib-nl-banner__inner">
    {%- if has_image -%}
      <div class="lib-nl-banner__media">
        {%- render 'lib-image',
          image: s.image,
          image_mobile: s.image_mobile,
          class: 'lib-nl-banner__img',
          sizes: '(min-width: 990px) 40vw, 100vw'
        -%}
      </div>
    {%- endif -%}

    <div class="lib-nl-banner__copy" data-align="{{ s.text_alignment }}" data-align-m="{{ s.text_alignment_mobile }}">
      {%- if s.heading != blank -%}
        <{{ heading_tag }} class="lib-nl-banner__heading lib-nl-banner__heading--{{ s.heading_size }}">
          {{- s.heading -}}
        </{{ heading_tag }}>
      {%- endif -%}
      {%- if s.text != blank -%}
        <div class="lib-nl-banner__text">{{ s.text }}</div>
      {%- endif -%}
    </div>

    {%- form 'customer', id: form_id, class: 'lib-nl-banner__form' -%}
      <input type="hidden" name="contact[tags]" value="{{ tags | escape }}">
      {%- if form.posted_successfully -%}
        <p class="lib-nl-banner__msg lib-nl-banner__msg--success" role="status">
          <svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><path d="m5 10.5 3.2 3L15 6.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
          <span>{{ s.success_message | escape }}</span>
        </p>
      {%- else -%}
        {%- if form.errors -%}
          <div class="lib-nl-banner__msg lib-nl-banner__msg--error" id="{{ error_id }}" role="alert">
            <p>{{ s.error_message | escape }}</p>
            {%- for field in form.errors -%}
              <p>
                {%- if field == 'form' -%}
                  {{ form.errors.messages[field] }}
                {%- else -%}
                  {{ form.errors.translated_fields[field] | capitalize }}
                  {{ form.errors.messages[field] }}
                {%- endif -%}
              </p>
            {%- endfor -%}
          </div>
        {%- endif -%}
        <label class="lib-nl-banner__label{% unless s.show_label %} lib-nl-banner__sr{% endunless %}" for="{{ input_id }}">
          {{- s.input_label | default: 'Email' | escape -}}
        </label>
        <div class="lib-nl-banner__row">
          <input
            class="lib-nl-banner__input"
            id="{{ input_id }}"
            type="email"
            name="contact[email]"
            required
            autocomplete="email"
            autocapitalize="off"
            spellcheck="false"
            {% if s.placeholder != blank %}
              placeholder="{{ s.placeholder | escape }}"
            {% endif %}
            {% if form.errors %}
              aria-invalid="true"
            {% endif %}
            {% if form.errors or s.small_print != blank %}
              aria-describedby="{% if form.errors %}{{ error_id }} {% endif %}{% if s.small_print != blank %}{{ note_id }}{% endif %}"
            {% endif %}
          >
          <button type="submit" class="lib-nl-banner__submit">{{ s.button_label | default: 'Subscribe' | escape }}</button>
        </div>
        {%- if s.small_print != blank -%}
          <p class="lib-nl-banner__note" id="{{ note_id }}">{{ s.small_print }}</p>
        {%- endif -%}
      {%- endif -%}
    {%- endform -%}
  </div>
</div>

{% stylesheet %}
  .lib-nl-banner {
    background-color: var(--lib-bg);
    background-image: var(--lib-bg-image, none);
    color: var(--lib-text);
    padding: var(--lib-pt) 1rem var(--lib-pb);
  }
  .lib-nl-banner__inner { max-width: 1200px; margin: 0 auto; display: grid; gap: 1.25rem; }
  .lib-nl-banner--full .lib-nl-banner__inner { max-width: none; }
  .lib-nl-banner__inner > * { min-width: 0; }
  @media (max-width: 749px) {
    .lib-nl-banner { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); }
    .lib-nl-banner[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-nl-banner[data-show='mobile'] { display: none; }
  }

  .lib-nl-banner__copy { display: flex; flex-direction: column; align-items: flex-start; text-align: left; }
  .lib-nl-banner__copy[data-align='center'] { align-items: center; text-align: center; }
  .lib-nl-banner__copy[data-align='right'] { align-items: flex-end; text-align: right; }
  @media (max-width: 749px) {
    .lib-nl-banner__copy[data-align-m='left'] { align-items: flex-start; text-align: left; }
    .lib-nl-banner__copy[data-align-m='center'] { align-items: center; text-align: center; }
    .lib-nl-banner__copy[data-align-m='right'] { align-items: flex-end; text-align: right; }
  }
  .lib-nl-banner__heading { margin: 0; font-size: clamp(1.375rem, 2.4vw, 1.875rem); line-height: 1.15; letter-spacing: -0.015em; text-wrap: balance; }
  .lib-nl-banner__heading--small { font-size: clamp(1.125rem, 1.8vw, 1.375rem); }
  .lib-nl-banner__heading--large { font-size: clamp(1.75rem, 3.4vw, 2.75rem); }
  .lib-nl-banner__text { margin-top: 0.5rem; font-size: 1rem; line-height: 1.55; opacity: 0.85; }
  .lib-nl-banner__text > :first-child { margin-top: 0; }
  .lib-nl-banner__text > :last-child { margin-bottom: 0; }

  .lib-nl-banner__form { width: 100%; }
  .lib-nl-banner__label { display: block; margin-bottom: 0.375rem; font-size: 0.875rem; font-weight: 600; }
  .lib-nl-banner__sr {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .lib-nl-banner__row { display: flex; gap: 0.5rem; }
  .lib-nl-banner__input {
    flex: 1;
    min-width: 0;
    min-height: 3rem;
    padding: 0 1rem;
    border: 1.5px solid color-mix(in srgb, var(--lib-field-text) 30%, transparent);
    border-radius: 999px;
    background: var(--lib-field-bg);
    color: var(--lib-field-text);
    font: inherit;
  }
  .lib-nl-banner__input::placeholder { color: color-mix(in srgb, var(--lib-field-text) 60%, transparent); }
  .lib-nl-banner__input:focus-visible { outline: 2px solid var(--lib-accent); outline-offset: 2px; }
  .lib-nl-banner__submit {
    flex: none;
    min-height: 3rem;
    padding: 0 1.5rem;
    border: 0;
    border-radius: 999px;
    background: var(--lib-accent);
    color: var(--lib-accent-text);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
  }
  .lib-nl-banner__submit:focus-visible { outline: 2px solid var(--lib-text); outline-offset: 2px; }
  @media (max-width: 479px) {
    .lib-nl-banner__row { flex-direction: column; }
  }
  .lib-nl-banner__note { margin: 0.625rem 0 0; font-size: 0.8125rem; line-height: 1.45; opacity: 0.8; }
  .lib-nl-banner__note a { color: inherit; text-underline-offset: 0.2em; }
  .lib-nl-banner__note a:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 2px; }
  .lib-nl-banner__msg { margin: 0 0 0.75rem; font-weight: 600; }
  .lib-nl-banner__msg p { margin: 0; }
  .lib-nl-banner__msg--success { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
  .lib-nl-banner__msg--error { padding: 0.5rem 0.75rem; border-left: 3px solid currentColor; }

  /* Strip: copy and form side by side from tablet width up. */
  @media (min-width: 750px) {
    .lib-nl-banner--strip .lib-nl-banner__inner { grid-template-columns: 1fr minmax(20rem, 30rem); align-items: center; gap: 2.5rem; }
  }

  /* Footer block: copy over the form, optional image beside them. */
  .lib-nl-banner--footer .lib-nl-banner__inner { gap: 1.5rem; }
  .lib-nl-banner--footer .lib-nl-banner__copy,
  .lib-nl-banner--footer .lib-nl-banner__form { max-width: 34rem; }
  .lib-nl-banner--footer .lib-nl-banner__copy[data-align='center'] ~ .lib-nl-banner__form { margin-inline: auto; }
  .lib-nl-banner--footer .lib-nl-banner__heading { font-size: clamp(1.75rem, 3.4vw, 2.75rem); }
  .lib-nl-banner--footer .lib-nl-banner__heading--small { font-size: clamp(1.375rem, 2.2vw, 1.75rem); }
  .lib-nl-banner--footer .lib-nl-banner__text { margin-top: 0.875rem; font-size: 1.0625rem; }
  .lib-nl-banner__media {
    position: relative;
    overflow: hidden;
    border-radius: 14px;
    aspect-ratio: 4 / 3;
    background: color-mix(in srgb, var(--lib-text) 8%, transparent);
  }
  .lib-nl-banner__img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .lib-nl-banner__img:is(svg) { fill: color-mix(in srgb, var(--lib-text) 25%, transparent); }
  @media (min-width: 990px) {
    .lib-nl-banner--footer[data-has-image] .lib-nl-banner__inner {
      grid-template-columns: 5fr 6fr;
      grid-template-rows: auto auto;
      column-gap: clamp(2.5rem, 5vw, 4.5rem);
      row-gap: 1.75rem;
      align-content: center;
    }
    .lib-nl-banner--footer[data-has-image] .lib-nl-banner__media { grid-row: 1 / 3; aspect-ratio: 1; }
    .lib-nl-banner--footer[data-has-image] .lib-nl-banner__copy { align-self: end; }
    .lib-nl-banner--footer[data-has-image] .lib-nl-banner__form { align-self: start; }
    .lib-nl-banner--footer[data-has-image][data-image-pos='right'] .lib-nl-banner__media { grid-column: 2; }
    .lib-nl-banner--footer[data-has-image][data-image-pos='right'] .lib-nl-banner__copy,
    .lib-nl-banner--footer[data-has-image][data-image-pos='right'] .lib-nl-banner__form { grid-column: 1; grid-row: auto; }
  }

  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .lib-nl-banner[data-animate] .lib-nl-banner__inner > * {
        animation: lib-nl-banner-rise linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 60%;
      }
    }
  }
  @keyframes lib-nl-banner-rise {
    from { opacity: 0; transform: translateY(20px); }
  }
{% endstylesheet %}

{% schema %}
{
  "name": "Lib · Newsletter banner",
  "tag": "section",
  "class": "lib-section",
  "settings": [
    {
      "type": "select",
      "id": "variant",
      "label": "Style",
      "options": [
        { "value": "strip", "label": "Strip (one row from 750px)" },
        { "value": "footer", "label": "Footer block" }
      ],
      "default": "strip"
    },

    { "type": "header", "content": "Content" },
    { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "Get the studio letter" },
    {
      "type": "select",
      "id": "heading_tag",
      "label": "Heading tag",
      "info": "Use H1 only when this is the page's main heading.",
      "options": [
        { "value": "h1", "label": "H1" },
        { "value": "h2", "label": "H2" },
        { "value": "h3", "label": "H3" },
        { "value": "p", "label": "Paragraph" }
      ],
      "default": "h2"
    },
    {
      "type": "select",
      "id": "heading_size",
      "label": "Heading size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" }
      ],
      "default": "medium"
    },
    { "type": "richtext", "id": "text", "label": "Text", "default": "<p>New pieces and kiln days, once a month.</p>" },

    { "type": "header", "content": "Form" },
    { "type": "text", "id": "input_label", "label": "Field label", "default": "Email address" },
    { "type": "checkbox", "id": "show_label", "label": "Show field label", "info": "When off, the label is still read by screen readers.", "default": false },
    { "type": "text", "id": "placeholder", "label": "Field placeholder", "default": "you@example.com" },
    { "type": "text", "id": "button_label", "label": "Button label", "default": "Subscribe" },
    { "type": "text", "id": "customer_tag", "label": "Extra customer tag", "info": "Optional. Added next to \"newsletter\" on the customer." },
    { "type": "inline_richtext", "id": "small_print", "label": "Small print", "info": "Link your privacy policy here.", "default": "Unsubscribe any time. Read our <a href=\"/policies/privacy-policy\">privacy policy</a>." },
    { "type": "text", "id": "success_message", "label": "Success message", "default": "Thanks for subscribing. See you in your inbox." },
    { "type": "text", "id": "error_message", "label": "Error message", "info": "Shown above Shopify's own message when a sign-up fails.", "default": "We couldn't sign you up. Please check your email address." },

    { "type": "header", "content": "Image (footer block)" },
    { "type": "image_picker", "id": "image", "label": "Desktop image", "visible_if": "{{ section.settings.variant == 'footer' }}" },
    { "type": "image_picker", "id": "image_mobile", "label": "Mobile image", "info": "Optional. Shown below 750px.", "visible_if": "{{ section.settings.variant == 'footer' }}" },
    {
      "type": "select",
      "id": "image_position",
      "label": "Image position on desktop",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "right", "label": "Right" }
      ],
      "default": "right",
      "visible_if": "{{ section.settings.variant == 'footer' }}"
    },

    { "type": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "section_width",
      "label": "Width",
      "options": [
        { "value": "page", "label": "Page width" },
        { "value": "full", "label": "Full width" }
      ],
      "default": "page"
    },
    { "type": "text_alignment", "id": "text_alignment", "label": "Text alignment on desktop", "default": "left" },
    {
      "type": "select",
      "id": "text_alignment_mobile",
      "label": "Text alignment on mobile",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" },
        { "value": "right", "label": "Right" }
      ],
      "default": "left"
    },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "default": "#2A2420" },
    { "type": "color_background", "id": "color_bg_gradient", "label": "Background gradient", "info": "Optional. Covers the background color." },
    { "type": "color", "id": "color_text", "label": "Text", "default": "#F4EFE8" },
    { "type": "color", "id": "color_accent", "label": "Accent (button)", "default": "#E8D9C4" },
    { "type": "color", "id": "color_accent_text", "label": "Text on accent", "default": "#2A2420" },
    { "type": "color", "id": "color_field_bg", "label": "Field background", "default": "#FFFDF9" },
    { "type": "color", "id": "color_field_text", "label": "Field text", "default": "#2A2420" },

    { "type": "header", "content": "Spacing and visibility" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 40 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 40 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 32 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 32 },
    {
      "type": "select",
      "id": "show_on",
      "label": "Show on",
      "options": [
        { "value": "all", "label": "All devices" },
        { "value": "desktop", "label": "Desktop only" },
        { "value": "mobile", "label": "Mobile only" }
      ],
      "default": "all"
    },
    { "type": "text", "id": "anchor_id", "label": "Anchor ID", "info": "Optional. Link to this section with #your-id." },

    { "type": "header", "content": "Motion" },
    { "type": "checkbox", "id": "animate", "label": "Rise in on scroll", "info": "Only in browsers that support scroll-driven animations; never when reduced motion is on.", "default": false }
  ],
  "presets": [
    { "name": "Lib · Newsletter banner" }
  ]
}
{% endschema %}
```

### snippets/lib-image.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Responsive image with optional art direction: a separate mobile image (below 750px),
  each honouring its own focal point from the theme editor. Falls back to a placeholder.

  @param {image} [image] - Desktop image (also used on mobile when no mobile image is set)
  @param {image} [image_mobile] - Mobile image, below 750px
  @param {string} [class] - Class for the img element
  @param {string} [sizes] - sizes attribute for the desktop image (default 100vw)
  @param {boolean} [eager] - Load immediately with high fetch priority (use for the first sections on a page)
  @param {string} [placeholder] - placeholder_svg_tag name when no image is set (default 'lifestyle-1')

  @example
  {% render 'lib-image', image: section.settings.image, image_mobile: section.settings.image_mobile, class: 'lib-hero__img', sizes: '(min-width: 990px) 50vw, 100vw', eager: true %}
{% enddoc %}

{%- liquid
  assign desktop = image
  if desktop == blank
    assign desktop = image_mobile
  endif
  assign img_sizes = sizes | default: '100vw'
  assign img_loading = 'lazy'
  assign img_priority = 'auto'
  if eager
    assign img_loading = 'eager'
    assign img_priority = 'high'
  endif
  assign art = false
  if image != blank and image_mobile != blank
    assign art = true
  endif
-%}

{%- if desktop != blank -%}
  <picture
    class="lib-picture{% if art %} lib-picture--art{% endif %}"
    {% if art %}
      style="--lib-pos-m: {{ image_mobile.presentation.focal_point | default: '50% 50%' }};"
    {% endif %}
  >
    {%- if art -%}
      <source
        media="(max-width: 749px)"
        srcset="
          {{ image_mobile | image_url: width: 375 }} 375w,
          {{ image_mobile | image_url: width: 750 }} 750w,
          {{ image_mobile | image_url: width: 1100 }} 1100w,
          {{ image_mobile | image_url: width: 1500 }} 1500w
        "
        sizes="100vw"
        width="{{ image_mobile.width }}"
        height="{{ image_mobile.height }}"
      >
    {%- endif -%}
    {{
      desktop
      | image_url: width: 2400
      | image_tag:
        class: class,
        loading: img_loading,
        fetchpriority: img_priority,
        sizes: img_sizes,
        widths: '600, 900, 1200, 1600, 2000, 2400'
    }}
  </picture>
{%- else -%}
  {{ placeholder | default: 'lifestyle-1' | placeholder_svg_tag: class }}
{%- endif -%}

{% stylesheet %}
  .lib-picture { display: contents; }
  @media (max-width: 749px) {
    /* image_tag sets the desktop focal point inline; the mobile image needs its own. */
    .lib-picture--art img { object-position: var(--lib-pos-m) !important; }
  }
{% endstylesheet %}
```

## Lisans

MIT Lisansı, © 2026 Lintel. Kendi mağazanızda ya da müşteri işlerinde ücretsiz kullanabilir, değiştirebilir ve yayınlayabilirsiniz; her dosyanın başındaki lisans satırını koruyun.
