Copy environment

Gallery Slider

<div class="gallery-slider">
    <div class="gallery-slider__rail">
        <div class="gallery-slider__rail-inner">
            <div class="grid grid--no-vertical-gutter gallery-slider__grid animation__target">
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/527x393" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/666x746" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/527x556" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/666x592" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/527x393" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
                <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                    <figure class="image image--fluid image--overlay gallery-slider__image">
                        <img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20530%20530%22%3E%3C%2Fsvg%3E" data-srcset="//placehold.it/666x746" data-sizes="auto" alt="" class="image__img lazyload">

                        <span class="image__overlay"></span>
                    </figure>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="gallery-slider">
    <div class="gallery-slider__rail">
        <div class="gallery-slider__rail-inner">
            <div class="grid grid--no-vertical-gutter gallery-slider__grid animation__target">
                {% if data.items %}
                    {% for item in data.items %}
                        <div class="grid__col grid__col--xs-3 grid__col--sm-5 grid__col--md-4 gallery-slider__grid-col">
                            {% include '@image' with {class: "gallery-slider__image", modifier: "image--fluid image--overlay", data: item|srcset('530x530f')} %}
                        </div>
                    {% endfor %}
                {% endif %}
            </div>
        </div>
    </div>
</div>
{
  "language": "en-US",
  "data": {
    "items": [
      {
        "srcset": "//placehold.it/527x393"
      },
      {
        "srcset": "//placehold.it/666x746"
      },
      {
        "srcset": "//placehold.it/527x556"
      },
      {
        "srcset": "//placehold.it/666x592"
      },
      {
        "srcset": "//placehold.it/527x393"
      },
      {
        "srcset": "//placehold.it/666x746"
      }
    ]
  }
}
  • Content:
    .gallery-slider__rail {
        position: relative;
        cursor: grab; /* stylelint-disable-line plugin/no-unsupported-browser-features */
        overflow: hidden;
        width: var(--app-width);
    }
    
    .gallery-slider__rail-inner {
        overflow-x: scroll;
        margin: 0 0 -20px;
        padding-bottom: 20px;
    
        @include bp(sm-min) {
            padding-right: calc(100vw / 7); /* stylelint-disable-line plugin/no-unsupported-browser-features */
        }
    
        @include bp(xxl-min) {
            padding-right: calc(var(--app-width) - 1920px + (1920px / 7)); /* stylelint-disable-line plugin/no-unsupported-browser-features */
        }
    }
    
    .gallery-slider__grid {
        flex-wrap: nowrap;
    }
    
    .gallery-slider__grid-col {
        pointer-events: none;
    }
    
    .gallery-slider__image {
        overflow: hidden;
        pointer-events: none;
        transform: scale(1);
        transform-origin: center top;
        transition-property: transform;
        transition-timing-function: $transition-easing-in;
        transition-duration: $transition-duration;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .gallery-slider.is-dragging & {
            transform: scale(.9);
            transition-timing-function: $transition-easing-out;
        }
    }
    
    .image__img {
        .gallery-slider & {
            width: 100%;
        }
    }
    
  • URL: /components/raw/gallery-slider/gallery-slider.scss
  • Filesystem Path: src/patterns/components/gallery-slider/gallery-slider.scss
  • Size: 1.3 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    
    import '../grid/grid';
    
    import './gallery-slider.scss';
    
    interface IGallerySliderSettings {
        dragClass: string;
    }
    
    export default class GallerySlider extends Component {
        static initSelector: string = '.gallery-slider';
    
        settings: IGallerySliderSettings;
        draggableArea: JQuery;
        mouseDown: boolean;
        mouseMoved: boolean;
        startX: number;
        dragSpeedMultiplier: number = 1.1;
        velX: number;
        momentumID: number;
        animationDurationMultiplier: number = .93; // must be a value between 0 and 1;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.settings = $.extend({
                dragClass: 'is-dragging',
            });
    
            this.draggableArea = this.element.find('.gallery-slider__rail-inner');
    
            this.mouseDown = false;
    
            this.init();
        }
    
        init(): void {
            $(window).on('mousemove', this.scroll.bind(this));
            $(window).on('mouseup', this.dragEndHandler.bind(this));
            $(window).on('mouseout', this.dragEndHandler.bind(this));
    
            this.draggableArea.on('mousedown', this.dragStartHandler.bind(this));
    
            this.draggableArea.on('touchstart', () => {
                this.addDraggingClass();
            });
    
            this.draggableArea.on('touchend', () => {
                this.removeDraggingClass();
            });
        }
    
        dragEndHandler(): void {
            this.mouseDown = false;
    
            if (!Helpers.isMobileDevice) {
                this.beginMomentumTracking();
            }
    
            this.removeDraggingClass();
        }
    
        dragStartHandler(event: MouseEvent): void {
            this.mouseMoved = false;
            this.mouseDown = true;
            this.startX = event.pageX - this.draggableArea.offset().left;
    
            if (!Helpers.isMobileDevice) {
                this.cancelMomentumTracking();
            }
    
            this.addDraggingClass();
        }
    
        scroll(event: MouseEvent): void {
            if (this.mouseDown && event !== undefined) {
                this.mouseMoved = true;
                const x: number = event.pageX - this.draggableArea.offset().left;
                const walk: number = (x - this.startX);
    
                // Store the previous scroll position
                const prevScrollLeft: number = this.draggableArea.scrollLeft();
    
                this.draggableArea.scrollLeft(this.draggableArea.scrollLeft() - walk * this.dragSpeedMultiplier);
                this.startX = x;
    
                // Compare change in position to work out drag speed
                this.velX = this.draggableArea.scrollLeft() - prevScrollLeft;
            }
        }
    
        addDraggingClass(): void {
            this.element.addClass(this.settings.dragClass);
        }
    
        removeDraggingClass(): void {
            this.element.removeClass(this.settings.dragClass);
        }
    
        beginMomentumTracking(): void {
            this.cancelMomentumTracking();
            this.momentumID = requestAnimationFrame(this.momentumLoop.bind(this));
        }
    
        cancelMomentumTracking(): void {
            cancelAnimationFrame(this.momentumID);
        }
    
        momentumLoop(): void {
            this.draggableArea.scrollLeft(this.draggableArea.scrollLeft() + this.velX);
    
            this.velX *= this.animationDurationMultiplier;
    
            if (Math.abs(this.velX) > 0.5) {
                this.momentumID = requestAnimationFrame(this.momentumLoop.bind(this));
            }
        }
    }
    
  • URL: /components/raw/gallery-slider/gallery-slider.ts
  • Filesystem Path: src/patterns/components/gallery-slider/gallery-slider.ts
  • Size: 3.4 KB
  • Handle: @gallery-slider--default
  • Filesystem Path: src/patterns/components/gallery-slider/gallery-slider.twig
  • References (1): @image
  • Referenced by (1): @gallery