SLIDER-USAGE (Standard Module )

src/app/shared/components/slider/templates

Demo Section

Each variation will be presented in the following section.

Slider (Bildergalerie) 100%

SM24 | Slider (Bildergalerie) 100% als Modul

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

  1. Alternative text that describes the image
  2. Alternative text that describes the image
  3. Alternative text that describes the image
  4. Alternative text that describes the image
  5. Alternative text that describes the image

1. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

2. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

©2018 imageworks

3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

©2018 imageworks

5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

Slider (Bildergalerie) 100% RTE

SM24 | Slider (Bildergalerie) 100% als Modul

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

  1. Alternative text that describes the image
  2. Alternative text that describes the image
  3. Alternative text that describes the image
  4. Alternative text that describes the image
  5. Alternative text that describes the image

1. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

2. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

©2018 imageworks

3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.

©2018 imageworks

5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

©2018 imageworks

Readme

npm version Gitter Chat

Slider

Description

The component represents a simple but powerful slider.

The slider module is a component for cycling through elements, like a carousel or slideshow. It allows users to swipe on touch-enabled devices.


JIRA


Requirements


Installation

Installation with Veams

veams install component slider
veams -i c slider

Fields

slider.hbs

The partial is a {{#wrapWith}} helper. Documentation for wrapWith helper.

Settings

Parameter Type Default Description
settings.sliderContextClass String 'default' Context class of component
settings.sliderClasses String '' Modifier classes for component
settings.sliderJsOptions Object null JavaScript options object which gets stringified in the markup
settings.sliderInnerFullWidth Boolean false Delete the class .is-container from .slider__content
settings.sliderHidePagination Boolean false Hide the pagination when set to true

slider__controls.hbs

Content

Parameter Type Description
content.sliderButtons Object Contains the controls content. When the object is not defined, the controls will not be printed out
content.sliderButtons.prev String Define the button text for the previous button
content.sliderButtons.next String Define the button text for the next button

slider__list.hbs

The partial is a {{#wrapWith}} helper. Documentation for wrapWith helper.

Settings

Parameter Type Default Description
settings.sliderOverflow Boolean Set this option to true if you want to add the class .is-overflow which gives you the possibility to show all hidden items next to the active element(s)

slider__item.hbs

The partial is a {{#wrapWith}} helper. Documentation for wrapWith helper.

slider__image-description.hbs

Content

Parameter Type Description
content.text String Image description text
content.source String Image description source

JavaScript Options

The module gives you the possibility to override default options:

Option Type Default Description
autoPlay Boolean false Enable AutoPlay option of the slider
autoPlayInterval Number 3000 AutoPlay speed in milliseconds
classes.active String 'is-active' Class for the active slide
classes.cloneClass String 'is-cloned' For the infinite slider the last and first element gets cloned. The cloning class can be overridden
classes.disabled String 'is-disabled' Class for disabled next/prev button
classes.hidden String 'is-hidden' The hidden class used by handling the visibility of the slider
classes.paginationItem String 'slider__pagination-list-item' Class which used in mini template
classes.sliding String is-sliding Class to be set during slide animation
classes.unresolved String is-unresolved Unresolved class which gets removed when initialized
counterRelationLabel String 'of' Define label for counter relation
disablePagination Boolean false Disable pagination
enableTouchSwipe Boolean true Enable support for swipe gestures on touch devices
groupPaginationItems Boolean true Enable the grouping of pagination items
infinite Boolean false The slider will be set in infinite mode. Can not be used with multiple active slide items
pageScrollThreshold Number 30 Threshold for vertical swipe in pixels
paginationItemClass String 'slider__pagination-list-item' Class for the generated pagination item
paginationItemJsAtom String 'slider-pagination-item' Data attribute for the generated pagination item
pauseOnHover Boolean true When autoplay is set you can enable/disable pause on hover
selectors.counter String '[data-js-item="slider-counter"]' Define counter
selectors.imageDescription String '[data-js-item="image-description"]' Define image description element
selectors.imageDescriptionWrapper String '[data-js-item="image-description-wrapper"]' Define image description wrapper element
selectors.items String '[data-js-item="slider-item"]' Define the slide item element
selectors.next String '[data-js-item="slider-next"]' Define the next button element
selectors.prev String '[data-js-item="slider-prev"]' Define the prev button element
selectors.paginationList String '[data-js-item="slider-pagination-list"]' Define the pagination list element in which the pagination items are generated in
selectors.ribbon String '[data-js-item="slider-ribbon"]' Define the slider ribbon which is holding all slides and gets the full width
selectors.wrapper String '[data-js-item="slider-wrapper"]' Define the slider wrapper element
slideByItemNumber Number false You can use the option to override the initial slide step which is the number of current visible items
startAtIndex Number 0 Start index for the slider
swipeThreshold Number 5 Threshold for horizontal swipe in percent
visibleItems Object {'mobile-s': 1, 'mobile-p': 1, 'tablet-p': 1, 'tablet-l': 1, 'desktop-m': 1, 'desktop-l': 1} Define how many slide items should be visible on different viewports

Sass Options

There are multiple global variables which you can change:

Variable Default Description
$slider-darken: 10 !default Darken value for hover effects
$slider-unresolved-height: 300px !default Set a fix height when the slider is in unresolved state
$slider-duration: 600ms !default Slide item animation duration
$slider-ease-method: ease !default Slide item animation ease method
$slider-control-bg-color: #a5cfd1 !default Background color of control buttons
$slider-pagination-color: #555 !default Background color of pagination items
$slider-pagination-color-active: $slider-pagination-color !default Active vackground color of pagination items which gets darken by $slider-darken
$slider-pagination-size: 15px !default Pagination size (width & height)
$slider-pagination-border-radius: 25% !default Border radius of pagination items

Templates

slider-usage.hbs

{{! wrapWith START: Slider }}
{{#with @root.slider.variations.default}}
	{{#wrapWith "slider" settings=this.settings content=this.content}}
	{{! WrapWith START: Slider List }}
		{{#wrapWith "slider__list" settings=this.settings}}

			{{#wrapWith "slider__item"}}
				{{#deepMerge @root.detail-page-3.sliderPicture
				             with='{"settings": {"ariaDescribedBy": "image-description-1"}}' arrayMerge="extend"}}
					{{> picture }}
				{{/deepMerge}}
			{{/wrapWith}}

			{{#wrapWith "slider__item"}}
				{{#deepMerge @root.detail-page-3.sliderPicture
				             with='{"settings": {"ariaDescribedBy": "image-description-2"}}' arrayMerge="extend"}}
					{{> picture }}
				{{/deepMerge}}
			{{/wrapWith}}

			{{#wrapWith "slider__item"}}
				{{#deepMerge @root.detail-page-3.sliderPicture
				             with='{"settings": {"ariaDescribedBy": "image-description-3"}}' arrayMerge="extend"}}
					{{> picture }}
				{{/deepMerge}}
			{{/wrapWith}}

			{{#wrapWith "slider__item"}}
				{{#deepMerge @root.detail-page-3.sliderPicture
				             with='{"settings": {"ariaDescribedBy": "image-description-4"}}' arrayMerge="extend"}}
					{{> picture }}
				{{/deepMerge}}
			{{/wrapWith}}

			{{#wrapWith "slider__item"}}
				{{#deepMerge @root.detail-page-3.sliderPicture
				             with='{"settings": {"ariaDescribedBy": "image-description-5"}}' arrayMerge="extend"}}
					{{> picture }}
				{{/deepMerge}}
			{{/wrapWith}}

		{{/wrapWith}}
	{{! WrapWith END: Slider List }}
	{{/wrapWith}}
{{/with}}
{{! wrapWith END: Slider}}

slider.hbs

<div class="c-slider{{#if options.settings.sliderContextClass}}--{{options.settings.sliderContextClass}}{{else}}--default{{/if}}{{#if
		options.settings.sliderClasses}} {{options.settings.sliderClasses}}{{/if}}"
 data-css="c-slider" data-js-module="slider" {{#if options.settings.sliderJsOptions}} data-js-options='{{stringify options.settings.sliderJsOptions}}'
 {{/if}}>


	{{#if options.content.headline}}
	<h2 class="slider__headline">{{options.content.headline}}</h2>
	{{/if}}

	{{#if options.content.introText}}
	<p class="slider__intro-text">{{options.content.introText}}</p>
	{{/if}}

	<div class="slider__content{{#unless options.settings.sliderInnerFullWidth}} is-container{{/unless}}">
		{{{yield}}}
	</div>

	{{#unless options.settings.sliderHidePagination}}
	<div class="slider__pagination-wrapper">
		{{> slider__pagination }}
	</div>
	{{/unless}}

	<div class="slider__counter-controls-panel">
		{{#if options.settings.sliderShowCounter}}
		<div class="slider__counter" data-js-item="slider-counter" aria-hidden="true"></div>
		{{/if}}

		{{#with options.content.sliderButtons}}
		<div class="slider__controls-wrapper">
			{{> slider__controls }}
		</div>
		{{/with}}
	</div>

	{{#if options.content.sliderImageDescription}}
	<div class="slider__image-description-wrapper" data-js-item="image-description-wrapper">
		{{/if}}

		{{#each options.content.sliderImageDescription}}
		{{> slider__image-description }}
		{{/each}}

		{{#if options.content.sliderImageDescription}}
	</div>
	{{/if}}
</div>

slider__controls.hbs

<button type="button" class="slider__control is-previous" data-js-item="slider-prev">
	{{prev}}
</button>
<button type="button" class="slider__control is-next" data-js-item="slider-next">
	{{next}}
</button>

slider__item.hbs

<li class="slider__item" data-js-item="slider-item">
	{{{yield}}}
</li>

slider__list.hbs

<div class="slider__list-wrapper{{#if options.settings.sliderOverflow}} is-overflow{{/if}}" data-js-item="slider-wrapper">
	<ol class="slider__list" data-js-item="slider-ribbon">
		{{{yield}}}
	</ol>
</div>

slider__pagination.hbs

<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
</ol>

Data File

slider.hjson

{
	"variations": {
		"default": {
			"docs": {
				"variationName": "Slider (Bildergalerie) 100%"
			},
			"settings": {
				"sliderContextClass": "default",
				"sliderClasses": "is-unresolved",
				"sliderHidePagination": true,
				"sliderShowCounter": true,
				"sliderJsOptions": {
					"counterRelationLabel": "von"
				}
			},
			"content": {
				"headline": "SM24 | Slider (Bildergalerie) 100% als Modul",
				"introText": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
				"sliderButtons": {
					"next": "Nächstes",
					"prev": "Vorheriges"
				},
				"sliderImageDescription": [
					{
						"content": {
							"id": "image-description-1",
							"text": "1. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-2",
							"text": "2. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-3",
							"text": "3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-4",
							"text": "4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-5",
							"text": "5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					}
				]
			}
		},
		"rte": {
			"docs": {
				"variationName": "Slider (Bildergalerie) 100% RTE"
			},
			"settings": {
				"sliderContextClass": "rte",
				"sliderClasses": "is-unresolved is-rte-embed",
				"sliderHidePagination": true,
				"sliderShowCounter": true,
				"sliderJsOptions": {
					"counterRelationLabel": "von"
				}
			},
			"content": {
				"headline": "SM24 | Slider (Bildergalerie) 100% als Modul RTE",
				"introText": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
				"sliderButtons": {
					"next": "Nächstes",
					"prev": "Vorheriges"
				},
				"sliderImageDescription": [
					{
						"content": {
							"id": "image-description-1",
							"text": "1. RTE Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-2",
							"text": "2. RTE At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-3",
							"text": "3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-4",
							"text": "4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.",
							"source": "©2018 imageworks"
						}
					},
					{
						"content": {
							"id": "image-description-5",
							"text": "5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
							"source": "©2018 imageworks"
						}
					}
				]
			}
		}
	}
}

Styles

_slider.scss

/* ===================================================
Slider Module
=================================================== */

/* ---------------------------------------------------
Global Variables
--------------------------------------------------- */
// General
$slider-darken: 10 !default;
$slider-unresolved-height: 300px !default;
// Animation Variables
$slider-duration: 600ms !default;
$slider-ease-method: ease !default;
// Controls
$slider-control-bg-color: #a5cfd1 !default;
// Pagination
$slider-pagination-color: #555 !default;
$slider-pagination-color-active: $slider-control-bg-color !default;
$slider-pagination-size: 15px !default;
$slider-pagination-border-radius: 25% !default;

/* ---------------------------------------------------
Global Styles
--------------------------------------------------- */

[data-js-module~="slider"] {
	clear: both;
	display: inline-block;
	position: relative;
	width: 100%;
	margin: 0 auto 60px;

	@include bp($bp-mobile-p) {
		margin-bottom: 80px;
	}

	@include bp($bp-tablet-p) {
		margin-bottom: 100px;
	}

	@include bp(1920px) {
		margin-bottom: 120px;
	}

	/*
	Unresolved state
	----------------------- */
	&.is-unresolved {

		.slider__list {
			height: $slider-unresolved-height;
			overflow: hidden;
		}

		.slider__item {
			opacity: 0;
		}
	}

	.slider__headline {
		@include headline-h2-styles();
	}

	.slider__intro-text {
		font-family: $font-regular;
		font-size: 1.6rem;
		line-height: (22/16);
		letter-spacing: .25px;
		color: $color-dark;
		margin-bottom: 25px;
	}

	/*
	List
	----------------------- */
	.slider__list-wrapper {
		display: block;
		position: relative;
		overflow: hidden;

		&.is-overflow {
			overflow: visible;
		}
	}

	.slider__list {
		left: 0;
		position: relative;
		transform: translate3d(0, 0, 0);
		transition: transform $slider-duration $slider-ease-method;
		margin-left: 0;
	}

	.slider__item {
		@include float();

		position: relative;
		opacity: .3;
		transition: opacity $slider-duration $slider-ease-method;
		vertical-align: top;
		line-height: 0;
		background-color: $color-light;
		list-style-type: none;
		padding-left: 0;
		margin-left: 0;

		&.is-active {
			opacity: 1;
		}
	}

	.slider__counter-controls-panel {
		@include print() {
			border-top: 1px solid $color-gray-border;
		}
	}

	/*
	Actions
	----------------------- */
	.slider__controls-wrapper {
		position: relative;
		display: inline-block;
		float: right;
		word-spacing: -2px;

		@include bp(410px) {
			word-spacing: -3px;
		}

		.slider__control {
			@include reset-btn();
			@include hidden-text();

			position: relative;
			background-color: $color-dark;
			width: 50px;
			height: 50px;
			border: 1px solid transparent;
			transition: border-color $animation-duration-std $animation-easing-std, background-color $animation-duration-std $animation-easing-std;

			@include bp($bp-tablet-p) {
				width: 54px;
				height: 54px;
			}

			@include bp($bp-desktop-m) {
				width: 60px;
				height: 60px;
			}

			@include hcm() {
				font-family: $font-regular;
				width: auto;
				color: initial;
				font-size: 1.6rem;
				border-color: $color-black;
				padding: 0 10px;
			}

			&:hover:not(.is-disabled) {
				cursor: pointer;
				background-color: $color-white;
				border-color: $color-green;

				&::before {
					@include sprites-icon-arrow-green100();

					transform: translate(calc(-50% + 5px), -50%);
				}

				&.is-previous {

					&::before {
						transform: translate(calc(-50% - 5px), -50%) rotate(180deg);
					}
				}
			}

			&::before {
				@include pseudo();
				@include centering();
				@include sprites-icon-arrow-white();

				transition: transform $animation-duration-std $animation-easing-std;

				@include print() {
					background-image: none;
				}
			}

			&.is-disabled {
				opacity: .1;
				cursor: not-allowed;
			}

			&.is-previous {
				left: 0;

				&::before {
					transform: translate(-50%, -50%) rotate(180deg);
				}
			}

			&.is-next {
				right: 0;
			}
		}

		.touch & {

			.slider__control {
				&:hover:not(.is-disabled) {
					cursor: pointer;
					background-color: $color-dark;
					border: 1px solid transparent;

					&::before {
						@include sprites-icon-arrow-white();

						transform: translate(-50%, -50%);
					}

					&.is-previous {

						&::before {
							transform: translate(-50%, -50%) rotate(180deg);
						}
					}
				}
			}

			@include bp($bp-tablet-l + 1) {
				display: block;
			}
		}
	}



	/*
	Pagination
	----------------------- */
	.slider__pagination-wrapper {
		@include centering(h);

		bottom: $slider-pagination-size;
	}

	.slider__pagination-list {
		margin: 0;
		padding: 0;
	}

	.slider__pagination-list-item {
		@extend %hidden-text;

		background-color: $slider-pagination-color;
		border-radius: $slider-pagination-border-radius;
		display: inline-block;
		height: $slider-pagination-size;
		margin: 0 $slider-pagination-size/3;
		width: $slider-pagination-size;
		transition: background-color $slider-duration/4 $slider-ease-method;

		&:hover {
			cursor: pointer;
			background-color: darken($slider-pagination-color, $slider-darken);
		}

		&.is-active {
			background-color: $slider-pagination-color-active;
		}

		&.is-hidden {
			display: none;
		}
	}

	.slider__counter {
		display: inline-block;
		line-height: 60px;
		font-size: 1.2rem;
	}

	.slider__counter-index {
		font-family: $font-bold;
	}

	.slider__image-description-wrapper {
		position: relative;
		height: auto;
		overflow: hidden;
		margin-bottom: 25px;
		transition: height $animation-duration-std $animation-easing-std;
	}

	.slider__image-description {
		position: absolute;
		font-size: 1.2rem;
		line-height: (17/12);
		opacity: 0;
		transition: opacity $animation-duration-std $animation-easing-std;
		color: $color-dark;

		@include print() {
			display: none;
		}

		&.is-active {
			opacity: 1;
			z-index: 200;

			@include print() {
				display: block;
			}
		}
	}

	.slider__image-description-text {
		padding: 10px 0;

		@include bp($bp-tablet-p) {
			padding: 15px 0 10px;
		}
	}
}

/* ---------------------------------------------------
Context: Default
--------------------------------------------------- */
.c-slider--default {

	.slider__headline,
	.slider__intro-text,
	.slider__image-description-wrapper,
	.slider__counter-controls-panel {
		@include bp($bp-tablet-p) {
			@include grid-column-width(12);
			@include grid-push-h(0);
		}

		@include bp($bp-tablet-l) {
			@include grid-column-width(10);
			@include grid-push-h(1);
		}

		@include bp($bp-desktop-l) {
			@include grid-column-width(8);
			@include grid-push-h(2);
		}
	}

	.slider__content {
		width: 100%;

		@include bp($bp-tablet-p) {
			@include grid-column-width(12);
			@include grid-push-h(0);
		}

		@include bp($bp-tablet-l) {
			@include grid-column-width(10);
			@include grid-push-h(1);
		}

		@include bp($bp-desktop-l) {
			@include grid-column-width(8);
			@include grid-push-h(2);
		}
	}
}

/* ---------------------------------------------------
Context: Landingpage
--------------------------------------------------- */
.c-slider--lpage {

	.slider__image-description-wrapper,
	.slider__counter-controls-panel,
	.slider__headline,
	.slider__intro-text {
		@include bp($bp-tablet-p) {
			@include grid-column-width(12);
			@include grid-push-h(0);
		}
	}

	.slider__content {
		width: 100%;

		@include bp($bp-tablet-p) {
			@include grid-column-width(12);
			@include grid-push-h(0);
		}
	}
}

/* ---------------------------------------------------
Context: RTE + Lightbox
--------------------------------------------------- */
.c-slider--rte {
	/*
	MODIFIERS
	----------------------- */
	&.is-rte-embed {
		margin-bottom: 60px;
	}

	.slider__intro-text {
		@include rte-dimensions();

		font-family: $font-regular;
		font-size: 1.5rem;
		line-height: (22/15);
		letter-spacing: .25px;
		color: $color-dark;
		margin-bottom: 25px;

		@include bp($bp-desktop-m) {
			font-size: 1.6rem;
			line-height: (24/16);
			margin-bottom: 30px;
		}
	}

	.grid__row {
		max-width: none;
	}

	.slider__image-description-wrapper,
	.slider__content,
	.slider__counter-controls-panel {
		@include rte-dimensions();
	}

	.slider__image-description-wrapper {
		margin-bottom: 0;
	}

	.slider__list {
		margin-bottom: 0;
	}

	li.slider__item {
		margin-bottom: 0;
		margin-top: 0;
		overflow: visible;
		list-style: none;

		&::before {
			left: 0;
			content: "";
			color: transparent;
		}
	}
}

.c-slider--lightbox {
	margin: 0 auto !important;
	display: block;
	max-width: 100vh;
	max-height: 100vw;

	.grid__row {
		max-width: none;
	}

	.slider__image-description-wrapper,
	.slider__content,
	.slider__counter-controls-panel {
		max-width: 100vh;
		max-height: 100vw;
		margin: 0 auto;
		padding: 0 8px;
	}

	.slider__image-description-wrapper {
		margin-bottom: 0;
	}

	li.slider__item {
		margin-bottom: 0;
		overflow: visible;
		list-style: none;

		&::before {
			left: 0;
			content: "";
			color: transparent;
		}
	}

	.slider__counter,
	.slider__image-description-text,
	.slider__image-description-source {
		color: $color-white;
	}

	.slider__control {
		border: 1px solid $color-white;

		&.is-disabled {
			opacity: .4;
		}
	}
}

Scripts

slider.js

/**
 * Represents a responsive slider which can be used as ribbon.
 *
 * @module Slider
 * @version v1.0.0
 *
 * @author Sebastian Fitzner
 * @author Andy Gutsche
 */
import $ from 'jquery';
import Component from '@veams/component';
import transitionEndEvent from '@veams/helpers/lib/detection/transition-end-event';
import getComputedTranslate from '../../../utilities/helpers/get-computed-translate';

class Slider extends Component {
	/**
	 * General Properties
	 */

	// Elements in Markup
	$el = $(this.el);
	$prev = this.$el.find(this.options.selectors.prev);
	$next = this.$el.find(this.options.selectors.next);
	$items = this.$el.find(this.options.selectors.items);
	$initialItems = this.$items;
	$wrapper = this.$el.find(this.options.selectors.wrapper);
	$ribbon = this.$el.find(this.options.selectors.ribbon);
	$lastItem = this.$items.eq(this.$items.length - 1);
	$firstItem = this.$items.eq(0);
	$counter = this.$el.find(this.options.selectors.counter);
	$imageDescriptionWrapper = this.$el.find(this.options.selectors.imageDescriptionWrapper);
	$imageDescription = this.$imageDescriptionWrapper.find(this.options.selectors.imageDescription);
	imageDescriptionHeights = [];

	// Transition
	transition = this.$ribbon.css('transition');

	// Pagination
	paginationDisabled = this.options.disablePagination || this.$items.length < 2;
	paginationItemSel = '[data-js-item="' + this.options.paginationItemJsItem + '"]';
	infinite = this.options.infinite && this.$items.length > 1;
	touchSwipeEnabled = false;
	clickHandler = true;
	_index = this.options.startAtIndex || 0;
	_autoPlay = this.options.autoPlay && this.infinite;

	/**
	 * Constructor for our class
	 *
	 * @see module.js
	 *
	 * @param {Object} obj - Object which is passed to our class
	 * @param {Object} obj.el - element which will be saved in this.el
	 * @param {Object} obj.options - options which will be passed in as JSON object
	 */
	constructor(obj) {
		let options = {
			classes: {
				active: 'is-active', // Active class for slides and pagination items
				cloned: 'is-cloned', // Clone class for cloned items (only used with infinite)
				disabled: 'is-disabled', // Disabled class for next/prev button
				hidden: 'is-hidden', // hidden class for pagination
				paginationItem: 'slider__pagination-list-item', // Define your class which we use in our mini tmpl
				sliding: 'is-sliding', // Class to be set during slide animation
				unresolved: 'is-unresolved' // Unresolved class which gets removed when initialized
			},
			autoPlay: false, // Enable AutoPlay
			autoPlayInterval: 3000, // AutoPlay interval in milliseconds
			counterRelationLabel: 'of', // Label for counter relation
			disablePagination: false, // Disable pagination display
			enableTouchSwipe: false, // Enable/Disable swipe support
			groupPaginationItems: false, // Group the pagination elements (useful for multiple visible items)
			infinite: false, // Infinite looping (only possible without multiple visible items)
			pageScrollThreshold: 30, // Threshold for vertical swipe in pixels
			paginationItemJsItem: 'slider-pagination-item', // data-js-item for pagination list item
			pauseOnHover: true, // Used when options.autoPlay is true
			selectors: {
				counter: '[data-js-item="slider-counter"]',
				imageDescription: '[data-js-item="image-description"]', // Image description
				imageDescriptionWrapper: '[data-js-item="image-description-wrapper"]', // Image description wrapper
				items: '[data-js-item="slider-item"]', // Slide Items
				next: '[data-js-item="slider-next"]', // Next Button
				prev: '[data-js-item="slider-prev"]', // Previous Button
				paginationList: '[data-js-item="slider-pagination-list"]', // Pagination List
				ribbon: '[data-js-item="slider-ribbon"]', // Ribbon element
				wrapper: '[data-js-item="slider-wrapper"]' // Wrapper element
			},
			slideByItemNumber: false, // Use the option to override the initial slide step
			startAtIndex: 0, // Start at a different index
			swipeThreshold: 10, // Threshold for horizontal swipe in percent
			visibleItems: {
				// Visible items per viewport
				'mobile-s': 1,
				'mobile-p': 1,
				'tablet-p': 1,
				'tablet-l': 1,
				'desktop-m': 1,
				'desktop-l': 1
			}
		};

		super(obj, options);
	}

	/**
	 * Custom getters and setter
	 */

	/**
	 * Get module information
	 */
	static get info() {
		return {
			version: '1.0.0',
			vc: true,
			mod: false
		};
	}

	/**
	 * Get and set visible items.
	 *
	 * @param {number} visible - Number of visible items
	 */
	get visibles() {
		return this._numVisible;
	}

	set visibles(visible) {
		this._numVisible = visible;
	}

	/**
	 * Get and set items length for slider.
	 *
	 * @param {number} len - Number of item length
	 */
	get itemsLength() {
		return this._itemLength;
	}

	set itemsLength(len) {
		this._itemLength = len;
	}

	/**
	 * Get and set the index of slider.
	 *
	 * @param {number} idx - index number of slide
	 */
	get index() {
		return this._index;
	}

	set index(idx) {
		this._index = idx;
	}

	/**
	 * Get paused property.
	 *
	 * @param {Boolean} bool - pause state
	 */
	get paused() {
		return this._paused;
	}

	set paused(bool) {
		this._paused = bool;
	}

	/**
	 * Get autoPlay property.
	 *
	 * @param {Boolean} bool - autoplay state
	 */
	get autoPlay() {
		return this._autoPlay;
	}

	set autoPlay(bool) {
		this._autoPlay = bool;
	}

	/**
	 * Get controls height.
	 */
	get controlHeight() {
		return this.$prev.outerHeight();
	}

	/**
	 * Return the defined option or current visible items
	 * which will be used for the next and previous slide animation.
	 */
	get slideBy() {
		return this.options.slideByItemNumber || this.visibles;
	}

	/**
	 * Get ribbon width.
	 */
	get ribbonWidth() {
		return ((this.$items.length * this.thumbWidth) + 1);
	}

	/** =================================================
	 * EVENTS
	 * ================================================ */

	/**
	 * Bind local events to this.$el.
	 */
	get events() {
		return {
			'click {{this.options.selectors.prev}}': 'showPrevElement',
			'touchstart {{this.options.selectors.prev}}': 'showPrevElement',
			'click {{this.options.selectors.next}}': 'showNextElement',
			'touchstart {{this.options.selectors.next}}': 'showNextElement',
			'click {{this.paginationItemSel}}': 'navigateToElement',
			'touchstart {{this.paginationItemSel}}': 'navigateToElement'
		};
	}

	/**
	 * Subscribe to global events of Veams or App namespace.
	 */
	get subscribe() {
		return {
			'{{context.EVENTS.resize}}': 'render'
		};
	}

	/**
	 * Bind all events
	 */
	bindEvents() {
		if (this.autoPlay && this.options.pauseOnHover) {
			this.registerEvent('{{context.EVENTS.mouseenter}}', 'pause');
			this.registerEvent('{{context.EVENTS.mouseleave}}', 'play');
		}
	}

	/**
	 * Unbind all events
	 */
	unbindEvents() {
		// Global Events
		this.context.Vent.off(this.context.EVENTS.resize);

		// Local Events
		this.$el.off(this.context.clickHandler);
	}

	/** =================================================
	 * STANDARD METHODS
	 * ================================================= */
	didMount() {
		if (!this.paginationDisabled) {
			this.$paginationList = this.$el.find(this.options.selectors.paginationList);
		}

		if (this.options.autoPlay && !this.infinite) {
			console.warn(
				'Slider: Sorry - option "autoPlay" has no effect while option "infinite" is set to false!'
			);
		}

		if (this.infinite) {
			for (let item in this.options.visibleItems) {
				if (this.options.visibleItems.hasOwnProperty(item)) {
					if (this.options.visibleItems[item] > 1) {
						console.warn(
							'Slider: Sorry - option "visibleItems" has no effect while option "infinite" is set to true!'
						);
						break;
					}
				}
			}
		}
	}

	/**
	 * Renders the view's template to the UI
	 */
	render() {
		if (!this.context.currentMedia) {
			console.warn(
				'Slider: this.context.currentMedia is necessary to support the slider module!'
			);
			return;
		}

		if (this.$clonedLast && this.$clonedFirst) {
			this.$clonedLast.remove();
			this.$clonedFirst.remove();
			this.$items = this.$initialItems;
		}

		this.visibles = this.infinite ? 1 : this.options.visibleItems[this.context.currentMedia];
		this.itemsLength = this.$items.length;

		this.handleVisibility();

		if (!this.paginationDisabled) {
			this.removePagination();
			this.addPagination();
		}

		if (this.infinite) {
			this.infiniteLoop();
			this.index = this.index === 0 ? this.index + this.visibles : this.index;
		}

		this.bindTransitions();
		this.getAndSetDimensions();

		if (
			this.context.detections.touch &&
			this.options.enableTouchSwipe &&
			!this.touchSwipeEnabled
		) {
			this.bindSwipes();
		}

		this.goToItem(this.index);

		if (this.autoPlay && this.paused) {
			this.play();
		}

		this.$imageDescription.eq(this.index).addClass(this.options.classes.active);

		this.getImageDescriptionHeights();
		this.$imageDescriptionWrapper.css(
			'height',
			this.imageDescriptionHeights[this.index] + 'px'
		);
	}

	/** =================================================
	 * CUSTOM SLIDER METHODS
	 * ================================================= */

	/**
	 * Bind transition events
	 *
	 */
	bindTransitions() {
		let onRibbonTransitionEnd = this.onRibbonTransitionEnd.bind(this);
		let onItemsTransitionEnd = this.onItemsTransitionEnd.bind(this);

		this.$ribbon.on(transitionEndEvent(), onRibbonTransitionEnd);
		this.$items.on(transitionEndEvent(), onItemsTransitionEnd);
	}

	/**
	 * React to transitionend on ribbon
	 *
	 * @param {Object} e - Event object.
	 */
	onRibbonTransitionEnd(e) {
		e.stopPropagation();

		this.$el.removeClass(this.options.classes.sliding);
		this.$imageDescription.eq(this.index).addClass(this.options.classes.active);

		if (this.autoPlay && this.paused) {
			if (this.options.pauseOnHover) {
				if (!this.$el.is(':hover')) {
					this.play();
				}
			} else {
				this.play();
			}
		}

		if (this.$clonedFirst && this.$clonedFirst.hasClass(this.options.classes.active)) {
			this.$clonedFirst.removeClass(this.options.classes.active);
			this.index = 1;

			this.animateSlide({
				idx: this.index,
				animate: false
			});
		}

		if (this.$clonedLast && this.$clonedLast.hasClass(this.options.classes.active)) {
			this.$clonedLast.removeClass(this.options.classes.active);
			this.index = this.$items.length - this.visibles - 1;

			this.animateSlide({
				idx: this.index,
				animate: false
			});
		}

		this.clickHandler = true;
	}

	/**
	 * React to transitionend on items
	 *
	 * @param {Object} e - Event object.
	 */
	onItemsTransitionEnd(e) {
		e.stopPropagation();
	}

	/**
	 * Get heights of all image descriptions
	 *
	 */
	getImageDescriptionHeights() {
		let i = 0;

		for (i; i < this.$imageDescription.length; i++) {
			this.imageDescriptionHeights.push(this.$imageDescription.eq(i).outerHeight());
		}
	}

	/**
	 * Clone first and last element
	 *
	 */
	infiniteLoop() {
		this.$clonedFirst = this.$firstItem.clone(true).addClass(this.options.classes.cloned);
		this.$clonedLast = this.$lastItem.clone(true).addClass(this.options.classes.cloned);

		if (this.options.infinite) {
			this.$clonedFirst.find(this.paginationItemSel).attr('data-index', this.itemsLength);
			this.$clonedLast.find(this.paginationItemSel).attr('data-index', -1);
		}

		this.$firstItem.before(this.$clonedLast);
		this.$lastItem.after(this.$clonedFirst);

		this.$items = $(this.options.selectors.items, this.$el);
	}

	/**
	 * Animate slide
	 *
	 * @param {Object} obj - animation property object.
	 */
	animateSlide(obj) {
		if (!obj.animate) {
			this.$ribbon.css('transition', 'none');
		} else {
			if (obj.idx !== obj.prevIdx) {
				this.$el.addClass(this.options.classes.sliding);
			}

			this.$ribbon.css('transition', this.transition);
		}

		if (obj.idx !== obj.prevIdx) {
			this.$imageDescription.removeClass(this.options.classes.active);
		}

		this.$ribbon.css('transform', 'translate3d(' + -obj.idx * this.thumbWidth + 'px, 0, 0)');
	}

	/**
	 * Check first/last slide classes
	 *
	 */
	checkSlides() {
		if (this.$clonedFirst.hasClass(this.options.classes.active)) {
			this.$firstItem.addClass(this.options.classes.active);
		}
		if (this.$clonedLast.hasClass(this.options.classes.active)) {
			this.$lastItem.addClass(this.options.classes.active);
		}
	}

	/**
	 * When items length is 0 we hide this view.
	 */
	handleVisibility() {
		if (this.itemsLength === 0) {
			this.$el.addClass(this.options.classes.hidden);
			console.warn('Slider: There is no item we can use in our slider :(');
		}

		this.$el.css('max-width', 'none');
	}

	/**
	 * Empty pagination.
	 */
	removePagination() {
		this.$paginationList.empty();
	}

	/**
	 * Add pagination elements with a simple string template and
	 * save a pagination item reference.
	 */
	addPagination() {
		let tmpl = '';
		let i = 0;
		let item = this.options.paginationItemJsItem;
		let itemClass = this.options.classes.paginationItem;

		for (i; i < this.$items.length; i++) {
			let idx = i + 1;
			let hiddenClass = '';

			if (this.options.groupPaginationItems) {
				hiddenClass = i % this.visibles === 0 ? '' : this.options.classes.hidden;
			}

			tmpl += `
					<li class="${itemClass} ${hiddenClass}" data-js-item="${item}" data-index="${i}">
						<strong>${idx}</strong>
					</li>
					`;
		}

		this.$paginationList.append(tmpl);
		this.$paginationItems = $(
			'[data-js-item="' + this.options.paginationItemJsItem + '"]',
			this.$el
		);
	}

	/**
	 * Navigate to a specific slide.
	 *
	 * @param {object} e - Event object.
	 * @param {object} currentTarget - Target to which listener was attached.
	 */
	navigateToElement(e, currentTarget) {
		let $currentTarget = $(currentTarget);

		if ($currentTarget.hasClass(this.options.classes.active)) {
			return;
		}

		let idx = parseInt($currentTarget.attr('data-index'), 10) || $currentTarget.index();

		if (this.infinite) {
			idx = idx + this.slideBy;
		}

		this.goToItem(idx);
	}

	/**
	 * Go to the next slide.
	 *
	 * @param {object} e - Event object.
	 * @param {object} currentTarget - Target to which listener was attached.
	 */
	showNextElement(e, currentTarget) {
		const $currentTarget = $(currentTarget);

		if (e && typeof e.preventDefault === 'function') {
			e.preventDefault();
		}

		if ($currentTarget.prop('disabled')) {
			return;
		}

		if (this.clickHandler) {
			this.goToItem(this.index + this.slideBy);
			this.clickHandler = false;
		}
	}

	/**
	 * Go to the previous slide.
	 *
	 * @param {object} e - Event object.
	 * @param {object} currentTarget - Target to which listener was attached.
	 */
	showPrevElement(e, currentTarget) {
		const $currentTarget = $(currentTarget);

		if (e && typeof e.preventDefault === 'function') {
			e.preventDefault();
		}

		if ($currentTarget.prop('disabled')) {
			return;
		}

		if (this.clickHandler) {
			this.goToItem(this.index - this.slideBy);
			this.clickHandler = false;
		}
	}

	/**
	 * Return the direction `next` or `prev`.
	 *
	 * @param {number} index - Index of the pagination element.
	 */
	getDirection(index) {
		return index > this.index ? 'next' : 'prev';
	}

	/**
	 * Bind all swipe gestures.
	 */
	bindSwipes() {
		this.registerEvent(
			'{{context.EVENTS.touchstart}} {{this.options.selectors.ribbon}}',
			'startDrag'
		);
	}

	/**
	 * Drag handler for preview controller and map
	 *
	 * @param {Object} e - Event object for 'touchstart' events
	 * @param {Object} e - Event object for 'touchstart' events
	 */
	startDrag(e, currentTarget) {
		let elem = currentTarget;
		let $elem = $(elem);
		let deltaX = 0;
		let deltaY = 0;

		// save initial values (including current x and y offset values)
		let dragStartValues = {
			elemX: elem.offsetLeft + getComputedTranslate(elem, 'x'),
			pageX: e.touches[0].pageX,
			pageY: e.touches[0].pageY
		};

		// on 'touchmove'
		$elem.on(this.context.EVENTS.touchmove, e => {
			// get delta compared to initial values
			let dragValues = Slider.getDragValues(e, dragStartValues);

			deltaX = dragValues.deltaX;
			deltaY = dragValues.deltaY;

			if (Math.abs(deltaY) <= this.options.pageScrollThreshold) {
				this.translateRibbon(dragValues.x);
			}
		});

		// if user stops touching stop tracking of touch movement
		$(window).on(this.context.EVENTS.touchend, () => {
			$(window).off(this.context.EVENTS.touchend);
			$elem.off(this.context.EVENTS.touchmove);

			// if drag delta for x < threshold snap back
			if (
				Math.abs(deltaX) <= this.$el.outerWidth() * (this.options.swipeThreshold / 100) ||
				Math.abs(deltaY) > this.options.pageScrollThreshold
			) {
				this.goToItem(this.index);

				return;
			}

			e.preventDefault();

			// swipe right
			if (deltaX > 0) {
				// if not first item goto previous otherwise snap back
				if (this.index > 0) {
					this.goToItem(this.index - 1);
				} else {
					this.goToItem(this.index);
				}
			}

			// swipe left
			if (deltaX < 0) {
				// if not last item goto next otherwise snap back
				if (this.index < this.$items.length - 1) {
					this.goToItem(this.index + 1);
				} else {
				}
				this.goToItem(this.index);
			}
		});
	}

	/**
	 * Calculate and return delta values between initial values and current values
	 *
	 * @param {Object} e - Event object for 'touchstart' events
	 * @param {Object} dragStartValues - Object containing initial values
	 *
	 * @return {Object} - Delta values and new x-value
	 */
	static getDragValues(e, dragStartValues) {
		let deltaX = e.touches[0].pageX - dragStartValues.pageX;
		let deltaY = e.touches[0].pageY - dragStartValues.pageY;

		return {
			x: dragStartValues.elemX + deltaX,
			deltaX: deltaX,
			deltaY: deltaY
		};
	}

	/**
	 * Translate ribbon on swipe
	 *
	 * @param {Number} x - New translate value for x-axis
	 */
	translateRibbon(x) {
		this.$ribbon.css({
			transform: 'translate3d(' + x + 'px, 0, 0)',
			transition: 'none'
		});
	}

	/**
	 * Enables button
	 *
	 * @param {Object} $btn - button element.
	 */
	enableBtn($btn) {
		$btn.removeClass(this.options.classes.disabled);
		$btn.prop('disabled', false);
		$btn.removeAttr('aria-disabled');
	}

	/**
	 * Disables button
	 *
	 * @param {Object} $btn - button element.
	 */
	disableBtn($btn) {
		$btn.addClass(this.options.classes.disabled);
		$btn.prop('disabled', true);
		$btn.attr('aria-disabled', true);
	}

	/**
	 * Handles the method to go to a specific item.
	 * Further we handle the class
	 *
	 * @param {number} i - Index number.
	 */
	goToItem(i) {
		let maxIndex = this.$items.length - this.visibles;

		if (maxIndex < 0) {
			maxIndex = 0;
		}

		if (!this.paused) {
			this.pause();
		}

		if (this.infinite) {
			if (i < 0) {
				i = maxIndex;
			} else if (i > maxIndex) {
				i = 0;
			}
		} else {
			this.enableBtn(this.$prev);
			this.enableBtn(this.$next);

			if (i < 1) {
				this.disableBtn(this.$prev);

				if (i < 0) {
					i = 0;
				}
			}

			if (i > maxIndex - 1) {
				this.disableBtn(this.$next);

				if (i > maxIndex) {
					i = maxIndex;
				}
			}
		}

		let prevIdx = this.index;
		this.index = i;

		this.animateSlide({
			animate: !this.$el.hasClass(this.options.classes.unresolved),
			idx: i,
			prevIdx: prevIdx
		});

		if (this.$el.hasClass(this.options.classes.unresolved)) {
			this.$el.removeClass(this.options.classes.unresolved);
		}

		this.handleActivity();

		if (this.infinite) {
			this.checkSlides();
		}
	}

	/**
	 * Handle activity.
	 */
	handleActivity() {
		this.$items.removeClass(this.options.classes.active);

		this.$imageDescriptionWrapper.css(
			'height',
			this.imageDescriptionHeights[this.index] + 'px'
		);

		if (!this.paginationDisabled && this.$paginationItems && this.$paginationItems.length) {
			this.$paginationItems.removeClass(this.options.classes.active);
		}

		let counterTmpl = `<span class="slider__counter-index">${this.index +
			1}</span> <span class="slider__counter-relation-label">${
			this.options.counterRelationLabel
		}</span> <span class="slider__counter-total">${this.$items.length}</span>`;

		this.$counter.html(counterTmpl);

		// If this slider instance isn't infinite
		if (!this.infinite) {
			for (let idx = this.index; idx < this.index + this.visibles; idx++) {
				// First set active slide element(s)
				this.$items.eq(idx).addClass(this.options.classes.active);

				// Do that also for pagination element(s)
				if (!this.paginationDisabled) {
					this.$paginationItems.eq(idx).addClass(this.options.classes.active);
				}
			}
		} else {
			for (let idx = this.index - 1; idx < this.index - 1 + this.visibles; idx++) {
				let slideIdx = idx;
				this.$items.eq(slideIdx + 1).addClass(this.options.classes.active);

				if (!this.paginationDisabled) {
					if (idx >= this.$paginationItems.length) {
						slideIdx = 0;
					}

					if (idx < 0) {
						slideIdx = this.$paginationItems.length - 1;
					}

					this.$paginationItems.eq(slideIdx).addClass(this.options.classes.active);
				}
			}
		}
	}

	/**
	 * Start autoplay.
	 */
	play() {
		clearInterval(this.autoPlayInterval);

		this.autoPlayInterval = setInterval(() => {
			this.goToItem(this.index + this.visibles);
		}, this.options.autoPlayInterval);

		this.paused = false;
	}

	/**
	 * Pause autoplay.
	 */
	pause() {
		clearInterval(this.autoPlayInterval);
		this.paused = true;
	}

	/**
	 * Get and set dimensions for our project progress.
	 */
	getAndSetDimensions() {
		this.resetStyles();
		this.width = this.$wrapper.outerWidth();
		this.thumbWidth = this.width / this.visibles;
		this.$wrapper.css('width', this.width + 'px');
		this.$items.css('width', this.thumbWidth + 'px');

		this.$ribbon.css({
			width: this.ribbonWidth + 'px'
		});
	}

	/**
	 * Reset width styles
	 */
	resetStyles() {
		this.$wrapper[0].removeAttribute('style');
		this.$items.removeAttr('style');
		this.$ribbon.removeAttr('style');
	}
}

export default Slider;

HTML Output

Slider (Bildergalerie) 100%

<div class="c-slider--default is-unresolved" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;counterRelationLabel&quot;:&quot;von&quot;}'>
	<h2 class="slider__headline">SM24 | Slider (Bildergalerie) 100% als Modul</h2>
	<p class="slider__intro-text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.</p>
	<div class="slider__content is-container">
		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
			<ol class="slider__list" data-js-item="slider-ribbon">
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-1" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-2" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-3" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-4" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-5" />
					</picture>
				</li>
			</ol>
		</div>
	</div>
	<div class="slider__counter-controls-panel">
		<div class="slider__counter" data-js-item="slider-counter" aria-hidden="true"></div>
		<div class="slider__controls-wrapper">
			<button type="button" class="slider__control is-previous" data-js-item="slider-prev">
				Vorheriges
			</button>
			<button type="button" class="slider__control is-next" data-js-item="slider-next">
				Nächstes
			</button> </div>
	</div>
	<div class="slider__image-description-wrapper" data-js-item="image-description-wrapper">
		<div id="image-description-1" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				1. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-2" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				2. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-3" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-4" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-5" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
	</div>
</div>

Slider (Bildergalerie) 100% RTE

<div class="c-slider--default is-unresolved" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;counterRelationLabel&quot;:&quot;von&quot;}'>
	<h2 class="slider__headline">SM24 | Slider (Bildergalerie) 100% als Modul</h2>
	<p class="slider__intro-text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.</p>
	<div class="slider__content is-container">
		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
			<ol class="slider__list" data-js-item="slider-ribbon">
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-1" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-2" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-3" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-4" />
					</picture>
				</li>
				<li class="slider__item" data-js-item="slider-item">
					<picture class="c-picture--slider
						" data-css="c-picture">
						<!--[if IE 9]><audio><![endif]-->
						<source srcset="
						 https://via.placeholder.com/400x267  400w  , 
						 https://via.placeholder.com/800x534  800w  , 
						 https://via.placeholder.com/1200x801  1200w  , 
						 https://via.placeholder.com/1600x1068  1600w  , 
						 https://via.placeholder.com/2000x1335  2000w  , 
						 https://via.placeholder.com/2400x1602  2400w  , 
						 https://via.placeholder.com/2800x1868  2800w  , 
						 https://via.placeholder.com/3200x2135  3200w  " />
						<!--[if IE 9]></audio><![endif]-->
						<img class="
						 picture__image" src="https://via.placeholder.com/400x267" alt="Alternative text that describes the image" title="Alternative text that describes the image" data-sizes="auto" aria-describedby="image-description-5" />
					</picture>
				</li>
			</ol>
		</div>
	</div>
	<div class="slider__counter-controls-panel">
		<div class="slider__counter" data-js-item="slider-counter" aria-hidden="true"></div>
		<div class="slider__controls-wrapper">
			<button type="button" class="slider__control is-previous" data-js-item="slider-prev">
				Vorheriges
			</button>
			<button type="button" class="slider__control is-next" data-js-item="slider-next">
				Nächstes
			</button> </div>
	</div>
	<div class="slider__image-description-wrapper" data-js-item="image-description-wrapper">
		<div id="image-description-1" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				1. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-2" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				2. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-3" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				3. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-4" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				4. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
		<div id="image-description-5" class="slider__image-description" data-js-item="image-description">
			<p class="slider__image-description-text">
				5. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
			</p>
			<span class="slider__image-description-source">©2018 imageworks</span>
		</div>
	</div>
</div>

Wonach suchst du?