Gatefold Documentation 1.1

Carousel

Wraps Swiper. Every carousel on the page is found and initialised from its own markup — there is no per-page JavaScript to write, and each carousel is configured with data-cel-* attributes. A page can carry several carousels with different behaviour.


HTML Markup

<div class="cel-carousel-slider" data-cel-carousel="portfolio">
  <div class="swiper">
    <div class="swiper-wrapper">

      <div class="swiper-slide">
        <img src="assets/images/demo/portfolio/portfolio-1-1024w.webp" alt="">
      </div>

    </div>
  </div>

  <!-- Optional. Present = enabled, unless an attribute says otherwise. -->
  <div class="swiper-pagination"></div>
  <div class="swiper-button-prev"></div>
  <div class="swiper-button-next"></div>
</div>

The outer element carries the settings. .cel-carousel-slider and .cel-carousel-slider-no-gutter are both recognised. The inner .swiper / .swiper-wrapper / .swiper-slide structure is Swiper's own and is required.

Initialization

initCarouselSwiper();

Called for you on DOMContentLoaded, at the bottom of main.js. The function is internal to that file, not a global, so there is nothing to call from your own scripts. It skips any .swiper that already has an instance.

Parameters

All optional, all read from the outer element. A missing attribute falls back to the preset, then to the default.

Attribute Values Default Description
data-cel-carousel preset name — Selects a named preset. portfolio is the one that ships.
data-cel-loop false true Wraps from the last slide back to the first.
data-cel-speed ms 800 Transition duration. The portfolio preset raises it to 1200.
data-cel-slides-per-view number or auto auto A number fixes the columns at every width, replacing the preset's. auto lets each slide keep its own width.
data-cel-centered false true Centres the active slide. The preset turns this off.
data-cel-gutter px — One fixed gap at every width, replacing the responsive ladder.
data-cel-pagination true / false presence Overrides whether the dots are used.
data-cel-navigation true / false presence Overrides whether the arrows are used.
data-cel-autoplay delay in ms off Presence enables autoplay; the value is the delay.
data-cel-overlay-sync overlay id — See initOverlayCarouselSync().

“Presence” means the markup decides. If you put a .swiper-pagination element in, you get dots; leave it out and you do not. The attribute is only there for the case where the element exists but you want it off — then it is hidden with a class, not with inline styles.

Behavior

  • Gaps are a ladder, not a number. By default the space between slides grows with the viewport: 20px from 320, 24 from 768, 32 from 1024, 36 from 1280, 42 from 1536. data-cel-gutter replaces the whole ladder with one value.
  • Keyboard control is on, but only while the carousel is in the viewport — arrow keys do not hijack the page from elsewhere.
  • A carousel whose slides already fit disables its own arrows and looping (watchOverflow).
  • Fewer slides than columns is fine. The column count never exceeds the number of slides, so three slides on a four-column desktop widen to fill the row instead of leaving a gap. Looping needs more slides than columns, so it is decided per width: off where every slide is already on screen, on wherever the carousel scrolls.
  • Reduced motion sets the transition to zero and refuses autoplay. Autoplay at zero speed would teleport a slide every few seconds, which is worse than the animation it replaces.

Presets

A preset is a named bundle of settings for a carousel whose responsive behaviour is fundamentally different, rather than one value away. portfolio is a fixed-count grid: 1 column from 320px, 2 from 576, 3 from 992, 4 from 1200, 5 from 2400 and 6 from 3200, with gaps of 0–8px, no centring, and a slower 1200ms transition.

Presets live in CAROUSEL_SWIPER.presets at the top of main.js. To add one, copy the portfolio block under a new name and select it with data-cel-carousel="<name>".

Scalar attributes still apply on top, so a preset is a starting point rather than a lock: data-cel-carousel="portfolio" data-cel-loop="false".

initInfoOverHover()

The panel that rises over a slide on hover, with the image scaling behind it and the text staggering in. GSAP-driven, and bound only where hovering is a real input.


HTML Markup

<div class="swiper-slide">
  <div class="cel-info-over-wrapper">

    <div class="cel-info-over io-h-center io-v-bottom cel-align-center">
      <div class="cel-info-over-inner io-inner-bg">
        <h5>The Last Great Canvas Was Twelve Inches</h5>
        <p>Art, alphabetised by surname.</p>
      </div>
    </div>

    <img src="assets/images/demo/portfolio/portfolio-1-1024w.webp" alt="">
  </div>
</div>

Three elements are required inside the wrapper: .cel-info-over (the box that moves), .cel-info-over-inner (whose children stagger), and an img (which scales). A wrapper missing any of them is skipped rather than half-animated.

Placement classes on .cel-info-over — io-h-center, io-v-bottom — position the panel; io-inner-bg gives the inner box its own fill.

Initialization

initInfoOverHover();

Called for you on DOMContentLoaded, at the bottom of main.js.

Behavior

  • Desktop only. Bound from 992px up, and torn down below it. A hover effect on a touch screen fires on tap and then sticks, so the panel would stay open with no way to dismiss it.
  • The teardown is real. Crossing the breakpoint removes both listeners, kills the running timeline and clears every property GSAP set. Resizing back and forth does not accumulate handlers.
  • Leaving is faster than entering — the exit runs at 0.7× the duration. An exit that takes as long as the entrance feels like the interface is reluctant to let go.
  • Reduced motion collapses every duration to zero; the end states are identical, they are simply arrived at instantly.

Custom Configuration

Unlike the carousel, this one is tuned from JavaScript rather than from markup — it is a motion curve, and motion curves are not per-instance decisions. Edit the INFO_OVER_HOVER defaults at the top of main.js, or pass an object to the call at the bottom of it:

initInfoOverHover({
  imgScale:         1.08,   // how far the image scales behind the panel
  imgDuration:      0.6,
  overlayDuration:  1,
  overlayScale:     true,   // scale the panel as well as sliding it
  overlayScaleFrom: 0.8,
  overlayY:         40,     // px the panel travels up from
  contentY:         100,    // px each line of content travels up from
  contentDuration:  0.55,
  contentStagger:   0.08,   // delay between lines
  leaveSpeed:       0.7,    // multiplier on the exit; lower is faster
});

Keeps the carousel behind an open overlay on the same item as the overlay itself, so closing the panel does not leave the strip somewhere else.


HTML Markup

<div class="cel-carousel-slider" data-cel-carousel="portfolio"
     data-cel-overlay-sync="portfolio">

The value is the data-cel-overlay-id of the overlay to follow. One attribute; there is nothing else to wire.

Behavior

  • Only while the overlay is open. Opening an item from the strip moves nothing — the strip is already showing it. Without this, the click that ends a drag on the carousel would jump the strip to the item you grabbed.
  • Listens for the cel:overlay-nav event that Overlay Navigation publishes, and moves the matching carousel to the same index.
  • At zero speed. The strip is behind a panel while this runs, so an animation would only ever be seen as a jump at the moment the panel disappears.
  • Uses slideToLoop, not slideTo. With looping on, the real slides sit among duplicates, and a raw index lands on a clone.

This lives here rather than in overlay-nav.js on purpose. Swiper is a dependency of main.js; the navigation module has no business knowing which carousel library the page happens to use. It publishes an event and stops there.