Home
Wiki
Home
Wiki
  1. 2. Components
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 1. Structure
      • Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • Overview
      • Addresses
      • BillingRetail
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • Company
      • General
      • Login
      • LoginModal
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ShoppingListsButton
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Register
      • Shipping
      • ShoppingLists
      • ShoppingListsNavbar
      • Toast
      • Users
      • VariantContent
      • WishlistButton
      • Services
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • Overview
        • theme.js
      • Css / Scss
        • Overview
        • ThemeClasses
    • 5. SDK
      • Overview
      • LiquidGlobals
      • ServicesSDK
  1. 2. Components

BannerCarousel

Purpose#

The BannerCarousel component renders a responsive banner slider using Swiper.
It supports:
“full width” vs “container” rendering
multiple layout modes via columns
configurable height via bannerHeight
banners with:
background color
background image (desktop + mobile)
background video with fallback image
internal content blocks (“sets”) per slide

Inputs (model contract)#

Model shape (storefront example)#

{
  "name": "BannerCarousel",
  "view": "Default",
  "section": "SectionA",
  "settings": {
    "bannerExtended": true,
    "bannerHeight": "Standard",
    "columns": "One",
    "banners": [
      {
        "backgroundImage": {
          "id": "Image Id",
          "galleryId": "Gallery Id",
          "link": "https://example.com/sample",
          "mediaType": "Image"
        },
        "backgroundImageMobile": {
          "id": "Mobile image Id",
          "galleryId": "Mobile gallery Id",
          "link": "https://example.com/sample",
          "mediaType": "Image"
        },
        "sets": [
          {
            "backgroundColor": true,
            "alignment": "Left",
            "header": "Sample header",
            "text": "<p>Sample text</p>\n",
            "buttonText": "Sample button text",
            "buttonLink": "/sample"
          },
          ...
        ]
      },
      ...
    ],
    "id": "Component Id",
    "section": "SectionA",
    "type": "NoirBannerCarousel",
    "name": "BannerCarousel",
    "configuredInContentApi": true,
    "view": "Default",
    "displayName": "Sample display name",
    "cssClass": "Sample cssClass"
  },
  "translations": {
    "clickToLearnMoreAbout": "Sample translation",
    "bannerLink": "Sample translation",
    "...": "..."
  }
}

Required fields#

settings.id
Used to form deterministic ids:
wrapper: comp-{{ id }}
swiper container: banner-carousel-{{ id }}
settings.banners[]
Component renders only when banners exist and banners.length > 0.

Optional fields#

settings.cssClass
Appended when non-empty and not (UNDEFINED).
settings.bannerExtended (boolean)
true renders full width; otherwise it uses container.
settings.columns (string)
Controls layout modifiers and Swiper configuration.
Observed values in storefront example: One
Template also supports: Two, Three, Four, TwoThirdOneThird, OneThirdTwoThird.
settings.bannerHeight (string)
Observed value: Standard
Template also supports: Small, FullHeight.

JavaScript#

Global object#

The component exposes a global object:
It’s used from Liquid via Alpine:
x-data="bannercarouseldefault.initComponent('{{ id }}', '{{ columns }}')"
initComponent(...) returns the Alpine component state + methods and then boots Swiper.

initComponent(id, columns)#

What it does
Factory function that receives:
id: component instance id (used to target #banner-carousel-<id>)
columns: layout mode (e.g. One, Two, Three, etc.)
Returns Alpine state:
id, columns
navbarHeight, topbarHeight
bannersHeight (calculated height for FullHeight behaviors)
isMobile (computed with breakpoint < 1440)
Exposes methods:
init()
getBannersHeight()
updateNavbarHeight()
updateTopbarHeight()
swiperInit(id, columns)
Advice
Keep id and columns as strings (as the Liquid call passes strings).
Don’t “guess” DOM selectors from other elements; this component already relies on .navbar and .topbar being present (see the height helpers below).

init()#

What it does
Runs automatically when Alpine mounts the component.
Calls getBannersHeight() once on load.
Registers a window.resize listener that:
1.
recomputes isMobile (window.innerWidth < 1440)
2.
waits 500ms
3.
calls getBannersHeight() again
Initializes Swiper by calling:
this.swiperInit(this.id, this.columns)
Why the timeout exists
After resize, the DOM/layout (navbar/topbar heights) may still be transitioning.
A small delay helps avoid measuring “intermediate” heights.
Advice
If you observe layout jank on resize, consider:
replacing setTimeout(…, 500) with requestAnimationFrame loops, or
debouncing resize events and measuring only once after the last resize.
There is no cleanup (listener removal). That’s fine if the component is not mounted/unmounted repeatedly.
If you add partial navigation later, add a guard to avoid duplicated listeners.

getBannersHeight()#

What it does
Computes bannersHeight differently for desktop vs mobile:
Desktop (!isMobile):
reads viewport height: window.innerHeight
refreshes topbar + navbar heights via:
updateTopbarHeight()
updateNavbarHeight()
sets:
bannersHeight = vh - topbarHeight - navbarHeight
Mobile (isMobile):
sets:
bannersHeight = "auto"
Where it’s used
This value is used by the template in FullHeight-type layouts to set an inline height / style so the carousel fits in the remaining viewport under header UI.
Advice
Make sure .topbar and .navbar exist when FullHeight is enabled; otherwise heights become 0 and banners may overlap with the header.
If the desktop breakpoint for “FullHeight behavior” is changed in CSS, update isMobile breakpoint (1440) to match the design system.

updateNavbarHeight()#

What it does
Queries:
document.querySelector(".navbar")
If found:
this.navbarHeight = navbar.offsetHeight
Advice
This is tightly coupled to the .navbar class.
If the theme structure changes, update the selector rather than adding extra DOM queries elsewhere.

updateTopbarHeight()#

What it does
Queries:
document.querySelector(".topbar")
If found:
this.topbarHeight = topbar.offsetHeight
Advice
Same coupling rule as the navbar: keep selectors stable or update them centrally here.

swiperInit(id, columns)#

What it does
Initializes a Swiper instance on #banner-carousel-<id> with rules based on columns and on a “Small height” mode.

Step 1: Normalize layout settings#

Default:
spaceBetween = 24
slidesPerViewMobile = 1
slidesPerViewDesktop = 1
Switch on columns:
Two → desktop slidesPerView = 2
Three → desktop slidesPerView = 3
Four → desktop slidesPerView = 4
TwoThirdOneThird / OneThirdTwoThird → desktop slidesPerView = 2
default (One) → spaceBetween = 0 and desktop slidesPerView = 1

Step 2: Resolve DOM elements#

Finds carousel container:
#banner-carousel-<id>
Finds pagination element inside carousel:
.swiper-pagination-<id>
Detects “Small height mode”:
checks if closest .carousel-wrap has class heightSmall
Collects slides:
.swiper-slide

Step 3: Decide whether looping is enabled#

Calculates:
minSlidesNeeded = max(slidesPerViewMobile, slidesPerViewDesktop)
Enables loop only if:
slides.length > minSlidesNeeded
Why this matters
Swiper loop can behave badly when there aren’t enough slides to loop smoothly for the chosen layout.

Step 4: Create Swiper#

Creates:
new Swiper(carousel, { ... })
Notable options:
loop: enableLoop
speed: 600
autoHeight: true
observer: true, observeParents: true (helps when parent layout changes)
Pagination enabled and clickable
Mobile baseline:
slidesPerView = 1
spaceBetween = hasSmallHeight ? 24 : 0
Grid mode:
rows: hasSmallHeight ? 2 : 1
Desktop breakpoint (1024):
slidesPerView = slidesPerViewDesktop
spaceBetween = spaceBetween
grid: false
Advice
Swiper must be loaded globally before this runs (it’s assumed by new Swiper(...)).
If you ever add dynamic slide insertion/removal, observer: true helps but may not be enough; you may need to destroy/reinit Swiper for correctness.
The code defines spaceBetween for the default case as 0, while “small height” uses 24 for mobile. Keep this intentional: small-height mode is effectively a 2-row grid and needs spacing.
Consider adding null-checks around DOM lookups if this function might be called when the expected markup isn’t present (currently it assumes the carousel exists and has the pagination element).

Dependencies#

Swiper (CSS + JS)
Alpine.js

Notes#

If Swiper isn’t loaded, the carousel won’t behave as a slider (slides may appear stacked).
FullHeight mode depends on .topbar and .navbar being present; if those class names change, height calculation may become inaccurate.
Some banner items may contain empty sets ({}) by design.
Modified at 2026-04-14 13:18:56
Previous
Announcement
Next
BlogCategoryList
Built with