Skip to content

HTML Elements

i:img (images)

Renders an image for a product, category, article, etc. Not used for static template images (icons, etc.).

Handles thumbnail URL generation, retina display support, and automatic image alt text.

When multiple dimensions are specified, a srcset is generated that can be used in combination with the HTML5 sizes attribute. If the sizes attribute is omitted, width and height attributes are set based on the actual resulting image dimensions.

If the alt attribute is not specified, it is automatically populated from the image description or the product/variant/... name.

The output differs depending on the device (retina/non-retina) and load order (first/subsequent). Retina images may overflow -- you must handle this in CSS, for example with max-width:100%;max-height:100%.

twig
<i:img src="zbozi.img" format="800x600" />
<i:img src="zbozi.img" format="800x600,300x200" sizes="(min-width: 500px) 50vw, 100vw" />

Attributes

AttributeRequiredDescription
srcyesTwig object
formatyesimage dimensions
sizesnosame as HTML5 sizes -- required when multiple dimensions are specified
watermarknoimage will have a watermark
fillnopad the image with white borders
vectornouse PNG/SVG
transparentnoimage has transparency
qualitynolow/normal/high/lossless (default: normal)
lazyloadnosrc and srcset as data attributes
class---CSS class

Image Zoom

Wrap an image in a link with @ as the href -- it will be replaced with the appropriate URL. The link may contain only one image. If you need a conditional, use two separate links.

twig
<a href="@"><i:img src="zbozi.img" format="800x600" /></a>
<a href="@"><i:img src="zbozi.img" format="800x600" sizes="(min-width: 500px) 50vw, 100vw" /></a>

i:img-360 -- 360 Product View

Renders the 360° spin player for a product that has 360° frames (product.images360). The player is a 100 %-wide box that keeps the frames' aspect ratio from the first paint, shows the first frame as a placeholder until the library has loaded, and re-draws itself whenever its width changes (a slider showing the slide, a fancybox dialog, a phone rotating). Give it a container of the width you want; no sizing CSS is needed. A product without frames renders nothing, so wrap the tag only when the surrounding markup (a slide, a thumbnail) must be conditional too.

twig
{% if product.images360 is not empty %}
    <i:img-360 product="product" format="400x400,800x800" sizes="(min-width: 768px) 400px, 100vw" />
{% endif %}

Attributes

AttributeRequiredDescription
productyesProduct object
formatnoframe dimensions (same as i:img). Default: [500x500, 1000x1000, 1500x1500, 2000x2000]; the library picks the size closest to the screen width
sizesnoresponsiveness of the placeholder (same as i:img) -- required when multiple dimensions are specified
zoomnomagnifier zoom, 2–5 or off (default: 3); the library disables the magnifier on touch devices
no-stepsnohide the forward/backward step buttons
no-fullscreennohide the fullscreen button (the fullscreen view carries the same prev/play/next bar as the inline player)
no-playnohide the play/stop button
autoplaynostart rotating as soon as the frames are loaded (the play button starts as "pause")
hide-logonohide the 360 view logo overlay shown before the first drag
bottom-circlenoshow the bottom 360 circle
lazyloadnoload the library and frames only when the element enters the viewport (see the strategies below)
lazyload="click"noload the library and frames only when the element is clicked (a 360 icon marks the placeholder)
hiddennorender the player hidden (display:none); it is activated only by window.image360.push() -- see below
classnoCSS class added to the .img-360-container element (used to target the player from fancybox data-src)

Loading strategies

StrategyMarkupFrames download
eager<i:img-360 product="product" />on page load
viewportlazyloadwhen the box scrolls into view (200 px ahead in the white-label bundle, at the edge with the legacy inline helper)
clicklazyload="click"when the visitor clicks the placeholder
on demandhidden + window.image360.push(element)when your JS activates it (slider slide shown, dialog opened)

window.image360.push(element) takes the .image-360-hidden element (or its .image-360 counterpart) and initializes it; before the storefront bundle has booted it queues the element and processes it at boot, so it is safe to call from template JS at any time. Pushing an already initialized element does nothing.

In a slider

Put the player into a slide and activate it when the slide is about to be shown, so the frames are downloaded only by visitors who reach the slide. The thumbnail strip gets the first frame via product.firstImage360. While the pointer is down on the player, disable the slider's own swipe so a horizontal drag rotates the product instead of changing the slide (slick example):

twig
{% if product.images360 is not empty %}
    <div class="item item-360">
        <i:img-360 product="product" hidden format="400x400,800x800" sizes="(min-width: 768px) 400px, 100vw" />
    </div>
{% endif %}
js
function activate360InSlide(slick, index) {
    var el = slick.$slides.eq(index).find('.image-360-hidden')[0];
    if (el) {
        window.image360 = window.image360 || [];
        window.image360.push(el);
    }
}

$('.slider')
    .on('init', function (e, slick) { activate360InSlide(slick, slick.currentSlide); })
    .on('beforeChange', function (e, slick, current, next) { activate360InSlide(slick, next); })
    .slick({ fade: true, /* … */ });

$('.item-360 .img-360-container').on('mousedown touchstart', function () {
    $('.slider').slick('slickSetOption', 'swipe', false);
});
$(document).on('mouseup touchend touchcancel', function () {
    $('.slider').slick('slickSetOption', 'swipe', true);
});

Because the player renders hidden until the slide is shown, make the placeholder visible so the slide has its height from the first paint (the box keeps the frames' aspect ratio):

scss
.item-360 .image-360-hidden { display: block; }

In a fancybox lightbox (3.5)

Add a thumbnail link of type inline pointing at a hidden player; the storefront bundle activates the player when the lightbox opens and re-draws it when its slide is shown. The link's data-options switch off fancybox's own touch gestures and the click-to-close on that slide only, so dragging the product does not pan or close the lightbox. The dialog content gets its width from the viewport so that the box fits the viewport height as well (min(92vw, (100vh - 20px) * ratio); the frames' ratio is emitted as --img360-ratio on the .img-360-container). The rule has zero specificity, so any .fancybox-slide .img-360-container { width: … } in the template wins.

twig
<a data-fancybox="product-gallery" data-type="inline" data-src=".fancybox-360" href="javascript:;"
   data-thumb="{{ product.firstImage360.url({width:150,height:150,fill:true}) }}"
   data-options='{"touch": false, "clickSlide": false, "clickContent": false}'>
    <i:img src="product.firstImage360" format="350x350" />
</a>

<div hidden>
    <i:img-360 product="product" hidden class="fancybox-360" format="500x500,1000x1000" sizes="(min-width: 768px) 1000px, 100vw" />
</div>

Keep the lightbox player inside a hidden wrapper: the bundle initializes it as soon as the lightbox opens (so the frames preload while the visitor still looks at the first photo), which makes the player element itself visible; fancybox moves only the .img-360-container into the dialog and puts it back on close, so the wrapper keeps it off the page the whole time.

The same player can be both the slider slide and the lightbox slide only by rendering it twice (one <i:img-360> per place): fancybox moves its inline content into the dialog and back, so a single element cannot live in both.

i:video

twig
{%for video in zbozi.videa%}
    <i:video src="video" width="400" height="300" />
{%endfor%}
{%for video in zbozi.videa%}
    <i:video src="video" width="400" height="300" class="embedded_video" />
{%endfor%}

Attributes

AttributeRequiredTypeDescription
srcyestwigTwig object
widthnointwidth in pixels (no units)
heightnointheight in pixels (no units)
controlsnostringtrue / false
loopnostringtrue / false
colornostringHEX color code for the icon
autoplayno
class------CSS class

i:dynamic (attribute) -- dynamic section definition

Wrapping a section of code in an element with the i:dynamic attribute defines that this section needs to be dynamically updated from JavaScript. The attribute must list the variables used -- only these variables will be available inside the element (similar principle to a Twig macro).

Adding the i:dynamic attribute does not change the code's behavior -- the output remains the same. The only difference is a new attribute in the resulting HTML that enables reloading part of the page from JavaScript.

When reloading, you can also pass additional custom variables as "arguments". These are then available in the template via the "arguments" array. A typical use case is reloading a section that shows variant-specific information -- the newly selected variant can be passed as an argument. Arguments are intended only for refining the selection and cannot be used to load entirely new content. The URL is public, so if an argument carried e.g. an order number, anyone could change the URL to see details of any order. For variant IDs and similar data, manual URL changes are harmless.

twig
<div i:dynamic="cart,product" class="cart-items-table"> {# class is not required and can be anything #}
    {% if arguments['variant']|default(product.variant.id) %}
        abc
    {% endif %}
</div>
javascript
$('.cart-items-table').reload(); // reload by class

$('.cart-items-table, .second-dynamic-div').reload(); // reload multiple sections at once

$('.cart-items-table').reload({
    callback: function() {
        alert('načteno!');
    }
});

$('.cart-items-table').reload({
    callback: function() {
        alert('načteno!');
    },
    arguments: {
        variant: 123
    }
});

$('.cart-items-table').reload({
    after:function(callback){
        // code that runs after the loading animation but before the actual reload
        // the reload is triggered by calling the callback
        // useful for async actions where you want the loading animation but delay the reload until completion
        callback();
    }
});

i:dynamic (tag) -- dynamic section definition

Wrapping a section of code in an <i:dynamic> element defines that this section can be dynamically updated from JavaScript (automatically or manually).

The tag can be used for:

  • reloading the element's content triggered by a JavaScript call
  • deferring content generation until the element enters the viewport (lazy="auto")
  • deferring content generation until explicitly requested from JavaScript (lazy="manual")

The variables attribute must list the variables used -- only these variables will be available inside the element (similar principle to a Twig macro).

twig
{# content is rendered immediately with the page and can be refreshed from JavaScript #}
<i:dynamic variables="cart,product" class="cart-items-table"> {# class is not required and can be anything #}
    <h4>{{ product.name }}</h4>
</i:dynamic>

{# content is not rendered with the initial page load; it loads automatically when the element enters the viewport and can be refreshed from JavaScript #}
<i:dynamic variables="cart,product" lazy="auto" class="cart-items-table">
    <h4>{{ product.name }}</h4>
</i:dynamic>

{# content is not rendered with the initial page load; it loads only when reload() is called from JavaScript #}
<i:dynamic variables="cart,product" lazy="manual" class="cart-items-table">
    <h4>{{ product.name }}</h4>
</i:dynamic>

i:map -- interactive map

The goal is to unify and simplify embedding maps in templates. The map automatically selects zoom and center based on the inserted points (unless explicitly defined!).

The map is rendered via mapy.cz, but support for additional map providers will likely be added in the future for language versions, etc. The template syntax is unified, and adding Google Maps support should not require any template changes.

twig
<i:map grayscale class="map-class">
    <i:map-point address="Drtinova 10, Praha" icon="/images/logo.svg" size="40x50" header="Otevírací doba" tags="praha,kartou">
        Po: 08:00-18:00<br/>
        Út: 08:00-18:00<br/>
        St: 08:00-18:00<br/>
        Čt: 08:00-18:00<br/>
        Pá: 08:00-18:00<br/>
    </i:map-point>
    <i:map-point lat="50.65" lon="14.1456" icon="/images/logo.svg" size="40x50" label="Centrála" tags="usti,kartou"/>
    <i:map-point lat="51.00" lon="15.000" icon="/images/logo.svg" size="40x50" tags="andelka">
        <strong>{%trans%}Otevírací doba{%endtrans%}</strong> <br>
        08:00-18:00
    </i:map-point>

    {% for location in locations %}
        <i:map-point lat="{{location.lat}}" lon="{{location.lon}}" />
    {% endfor %}
</i:map>
html
<!-- generated output -- subject to change! -->

<div class="map-class global-map grayscale">
    <span data-header="Otevírací doba" data-tags="praha,kartou" data-gps="50.0255597,14.5510733" data-icon="/1585575662/images/logo.svg" data-lat="50.0255597" data-lon="14.5510733">
        Po: 08:00-18:00<br>
        Út: 08:00-18:00<br>
        St: 08:00-18:00<br>
        Čt: 08:00-18:00<br>
        Pá: 08:00-18:00<br>
    </span>
    <span data-lat="50.65" data-lon="14.1456" data-label="Centrála" data-tags="usti,kartou" data-icon="/1585575662/images/logo.svg"></span>
    <span data-lat="51.00" data-lon="15.000" data-tags="andelka" data-icon="/1585575662/images/logo.svg">
        <strong>Otevírací doba</strong> <br>
        08:00-18:00
    </span>
    <div class="mapycz" style="height:400px"></div>
</div>

i:map Attributes

AttributeRequiredDescription
lat=""nolatitude of the map center
lon=""nolongitude of the map center
zoom=""nodefault map zoom
height=""nodefault map height (400px)
controls="off"nohide map controls
grayscaleno
clusters=""nodefault distance for markers in a cluster (40)
cluster-class=""nocustom class for the cluster
view=""nobasic / hybrid / aviation / tourist / winter (default: basic)
view-layers="basic,aviation"noenable map layer switching -- basic / hybrid / aviation / tourist / winter (default: "basic,aviation,hybrid,tourist,winter")

i:map-point Attributes

AttributeRequiredDescription
lat="" and lon=""yespoint coordinates. Either lat/lon or address must be provided
address=""yespoint address. Either lat/lon or address must be provided
icon="/images/home.svg"no
size="20x20"nocustom marker size. Default size: 23x32
label="Centrala"nohover title
header="Opening hours"nocard title
tags="praha"notags separated by commas
code="xxx"nomarker identifier

Custom Cluster Class

<i:map cluster-class="embed-map-cluster"></i:map>

cluster-class overrides the original class and creates new classes for the cluster.

Attributes

ClassDescription
embed-map-clustergeneral class for all clusters
embed-map-cluster-small< 10 points
embed-map-cluster-medium< 40 points
embed-map-cluster-large> 40 points

Opening a POI Externally

Call window.mapComponent.openMarkerCard(code) to open any POI detail.

twig
<button type="button" class="show-marker-detail" data-code="simplia">Simplia</button>
<button type="button" class="show-marker-detail" data-code="test">Testovaci</button>

<i:map class="marker-map">
    <i:map-point address="Drtinova 10, Praha" code="simplia">
        Po: 08:00-18:00<br/>
        Út: 08:00-18:00<br/>
        St: 08:00-18:00<br/>
        Čt: 08:00-18:00<br/>
        Pá: 08:00-18:00<br/>
    </i:map-point>
    <i:map-point lat="51.00" lon="15.000" code="test">
        <strong>{%trans%}Otevírací doba{%endtrans%}</strong> <br>
        08:00-18:00
    </i:map-point>
</i:map>
html
<script type="text/javascript">
    Array.prototype.forEach.call(document.querySelectorAll('.show-marker-detail'), function (el) {
        el.addEventListener('click', function (e) {
            e.preventDefault();

            var targetElement = e.target || e.srcElement;

            window.mapComponent.openMarkerCard('.marker-map', targetElement.dataset.code);
        });
    });
</script>

Filtering Map Points

Filtering between tag arrays uses AND logic; within each tag array, OR logic is used. See the example: Praha or Usti AND kartou (card payment).

window.mapComponent.filter Parameters

AttributeRequiredDescription
selectoryesmap selector, e.g. .global-map
filteryesarray of tag arrays
booleannoauto-center map on filtered POIs. Default: false
html
<script type="text/javascript">
    window.mapComponent.filter('.filter-map', [['praha', 'usti'], ['kartou']], true);
</script>

Route Planning

Creates a URL via api.mapy.cz for route planning.

i:map-route-link Attributes

AttributeRequiredDescription
lat="" and lon=""yespoint coordinates. Either lat/lon or address must be provided
address=""yespoint address. Either lat/lon or address must be provided
twig
<i:map-route-link lat="50.7700158" lon="15.0595950">Popisek</i:map-route-link>
html
<!-- generated output -- subject to change! -->

<a class="map-route-link" data-lat="50.7700158" data-lon="15.0595950" href="//mapy.cz/?planovani-trasy&amp;rc=95ra0x1qpF&amp;rs=&amp;rs=coor&amp;ri=&amp;ri=&amp;mrp=&amp;mrp={&quot;c&quot;:111}">
    Popisek
</a>

Creates a URL to a POI on mapy.cz.

twig
<i:map-link search="Helveti.cz">Helveti</i:map-link><br>
<i:map-link search="Jadi.cz, Praha">Jadi.cz Praha</i:map-link><br>
<i:map-link search="Jadi.cz, Liberec">JAdi.cz Liberec</i:map-link><br>
<i:map-link search="Jadi.cz">Jadi.cz</i:map-link><br>
<i:map-link search="Vítkova 244/8, Praha">Adresa</i:map-link>
html
<!-- generated output -- subject to change! -->
<a class="map-link" href="//mapy.cz/zakladni?x=14.446071624756&amp;y=50.090213775635&amp;id=12903247&amp;source=firm">Helveti</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=14.429894447327&amp;y=50.081184387207&amp;id=12914136&amp;source=firm">Jadi.cz Praha</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=15.056777954102&amp;y=50.770107269287&amp;id=2099659&amp;source=firm">JAdi.cz Liberec</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=15.172479629517&amp;y=50.72388458252&amp;id=726263&amp;source=firm">Jadi.cz</a><br>
<a class="map-link" href="//mapy.cz/zakladni?q=V%C3%ADtkova+244%2F8%2C+Praha">Adresa</a>

i:banners

Template for unified banner output.

In the examples below, the i:**** tags are the important part -- the rest of the template markup will differ per shop due to legacy code.

twig
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})" plugin="swiper">
    <source format="1150x630" src="desktop"/>
</i:banners>
html
<!-- generated output -- subject to change! -->

<div class="banner swiper-container">
    <div class="banner-wrap swiper-wrapper">
        <div class="banner-item banner--item__1 banner--item__first swiper-slide">
            <picture>
                <img width="1150" height="630"
                          srcset="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp 1x,//i00.eu/img/999997/2300x1260/25nkjd5z/2229.webp 2x"
                          src="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp">
            </picture>
        </div>
        <div class="banner-item banner--item__2 banner--item__last swiper-slide">
            <picture>
                <img class="auto-lazyload swiper-lazy" width="1150" height="599"
                          data-srcset="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp 1x,//i00.eu/img/999997/2300x1260/b9whiv1f/2237.webp 2x"
                          src="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp"
                          data-src="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp"
                          srcset="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp 1x,//i00.eu/img/999997/2300x1260/b9whiv1f/2237.webp 2x"
                          data-loaded="true">
            </picture>
        </div>
    </div>
</div>

Example using an inner wrapper div.

twig
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})" wrap="div.wrap.www-rap">
    <source format="1150x630" src="desktop"/>

    <h2 data-role="title"></h2>
    <div data-role="description"></div>
    <div data-role="cta"></div>
</i:banners>
html
<div class="banner">
    <div class="banner-wrap">
        <div class="banner-item banner--item__1 banner--item__first">
            <div class="wrap www-rap">
                <picture>
                    <img width="1150" height="630"
                              srcset="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp 1x,//i00.eu/img/999997/2300x1260/25nkjd5z/2229.webp 2x"
                              src="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp">
                </picture>
                <div class="banner-info">
                    <h2 class="banner-info__headline">První Slide</h2>
                    <div class="banner-info__description">Popisek....</div>
                    <a class="button banner-info__button" href="https://www.simplia.cz">CTA</a>
                </div>
            </div>
        </div>
        <div class="banner-item banner--item__2">
            <div class="wrap www-rap">
                <picture>
                    <img class="auto-lazyload" width="1150" height="630"
                              data-srcset="//i00.eu/img/999997/1150x630a/79l5pfe2/2234.webp 1x,//i00.eu/img/999997/2300x1260/acf5nmee/2234.webp 2x"
                              src="//i00.eu/img/999997/1150x630a/79l5pfe2/2234.webp"
                              data-src="//i00.eu/img/999997/1150x630a/79l5pfe2/2234.webp"
                              srcset="//i00.eu/img/999997/1150x630a/79l5pfe2/2234.webp 1x,//i00.eu/img/999997/2300x1260/acf5nmee/2234.webp 2x"
                              data-loaded="true">
                </picture>
                <div class="banner-info">
                    <h2 class="banner-info__headline">Druhý slide</h2>
                    <div class="banner-info__description">popis :)</div>
                    <a class="button banner-info__button">CTA</a>
                </div>
            </div>
        </div>
        <div class="banner-item banner--item__3 banner--item__last">
            <div class="wrap www-rap">
                <picture>
                    <img class="auto-lazyload" width="1150" height="599"
                              data-srcset="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp 1x,//i00.eu/img/999997/2300x1260/b9whiv1f/2237.webp 2x"
                              src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1150 599'%3E%3C/svg%3E"
                              data-src="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp">
                </picture>
                <div class="banner-info">
                    <h2 class="banner-info__headline">Třetí slide</h2>
                </div>
            </div>
        </div>
    </div>
</div>

Nesting banner classes.

twig
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})" wrap="div.inner-wrap-class" banner-item-class="custom-item-class" banner-wrap-class="extra-banner-wrap">
    <source format="1150x630" src="desktop"/>
</i:banners>
html
<div class="banner">
    <div class="banner-wrap extra-banner-wrap">
        <div class="banner-item banner--item__1 banner--item__first banner--item__last custom-item-class">
            <div class="inner-wrap-class">
                <picture>
                    <img width="1150" height="630"
                         srcset="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp 1x,//i00.eu/img/999997/2300x1260/25nkjd5z/2229.webp 2x"
                         src="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp">
                </picture>
            </div>
        </div>
    </div>
</div>

Banner title tooltip.

twig
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})">
    <source format="1150x630" src="desktop"/>

    <h2 data-role="title" tooltip></h2>
    <span data-role="cta"></span>
</i:banners>
html
<div class="banner">
    <div class="banner-wrap">
        <div class="banner-item banner--item__1 banner--item__first banner--item__last">
            <picture>
                <img width="1150" height="630"
                          srcset="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp 1x,//i00.eu/img/999997/2300x1260/25nkjd5z/2229.webp 2x"
                          src="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp">
            </picture>
            <div class="banner-info">
                <h2 class="banner-info__headline">
                    První Slide
                    <span class="banner-info__headline-tooltip-text">Popisek....</span>
                </h2>
                <a class="button banner-info__button" href="https://www.simplia.cz">CTA</a>
            </div>
        </div>
    </div>
</div>

Banner Parameters

ParameterRequiredDescription
sourceyesrepository.banner.findBy()
prioritynoallowed values: high / low (default: high). low -- lazyload on all images; high -- respects visible-slides
visible-slidesnonumber of banners without lazyload (default: 1)
wrapnoinner banner wrapper
classnoadd a custom class
banner-item-classnoadd a custom class to the banner items wrapper
banner-wrap-classnoadd a custom class to individual banner wrappers
picture-classnoadd a custom class to the picture wrapper
pluginnoadd helper classes for a specific plugin, e.g. swiper
clicknoconfigure banner click behavior. Allowed values: banner / cta / off.
qualitynoimage compression quality for all sources. Allowed values: low / normal / high / lossless. If omitted, the shop default is used.

Banner Attributes

AttributeRequiredDescription
arrowsnoshow arrows for slide navigation
dotsnoshow slide navigation dots
progressnoshow progress bar
thumbnailsnoshow thumbnails with banner titles
transparentnoimage has transparency
fillnopad image with white borders

Banner source elements

data-roleRequiredAttributes
desktopyesformat -- required banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified (default: 80vw), class -- add a custom class, quality -- image compression quality (low / normal / high / lossless) overriding the banner-level quality for this source
tabletnoformat -- banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified, media -- same as HTML5 media, class -- add a custom class, quality -- image compression quality (low / normal / high / lossless) overriding the banner-level quality for this source
mobilenoformat -- banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified, media -- same as HTML5 media, class -- add a custom class, quality -- image compression quality (low / normal / high / lossless) overriding the banner-level quality for this source

Complete data-role list for banners

data-roleRequiredAttributes
info-boxnotag definition
titlenotag definition
descriptionnotag definition
ctanotag definition
twig
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})" plugin="swiper" class="custom-class,super-class" click="banner" arrows dots progress>
    <source format="1150x630" src="desktop"/>
    <source media="(min-width: 440px) and (max-width: 768px)" format="748x486,249x162" sizes="100vw" src="tablet"/>
    <source media="max-width: 440px" format="640x790,320x340" sizes="100vw" src="mobile"/>

    <div data-role="info-box" class="infobox-extra-class" ></div>
    <h2 data-role="title"></h2>
    <div data-role="description"></div>
    <span data-role="cta"></span>
</i:banners>
html
<!-- generated output -- subject to change! -->

<div class="banner custom-class super-class swiper-container">
    <div class="banner-wrap swiper-wrapper">
        <div class="banner-item banner--item__1 banner--item__first swiper-slide">
            <a href="https://www.simplia.cz">
                <picture>
                    <source srcset="//i00.eu/img/999997/640x790a/5e37hrnn/2227.webp 640w,//i00.eu/img/999997/320x340a/5072sf1e/2227.webp 320w"
                            media="max-width: 440px" sizes="100vw">
                    <source srcset="//i00.eu/img/999997/748x486a/cr5pv3u6/2228.webp 748w,//i00.eu/img/999997/249x162a/85hs2grx/2228.webp 249w"
                            media="(min-width: 440px) and (max-width: 768px)" sizes="100vw">
                    <img width="1150" height="630"
                         srcset="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp 1x,//i00.eu/img/999997/2300x1260/25nkjd5z/2229.webp 2x"
                         src="//i00.eu/img/999997/1150x630a/562ojxe8/2229.webp">
                </picture>
                <div class="banner-info infobox-extra-class">
                    <h2 class="banner-info__headline">První Slide</h2>
                    <div class="banner-info__description">Popisek....</div>
                    <span class="button banner-info__button">CTA</span>
                </div>
                <div class="banner-progress">
                    <div class="progress"></div>
                </div>
            </a>
        </div>
        <div class="banner-item banner--item__2 banner--item__last swiper-slide">
            <picture>
                <source srcset="//i00.eu/img/999997/640x790a/1ihskwis/2239.webp 640w,//i00.eu/img/999997/320x340a/4dkf8gy0/2239.webp 320w"
                        media="max-width: 440px" sizes="100vw">
                <source srcset="//i00.eu/img/999997/748x486a/697q3ssb/2238.webp 748w,//i00.eu/img/999997/249x162a/25bq8xs2/2238.webp 249w"
                        media="(min-width: 440px) and (max-width: 768px)" sizes="100vw">
                <img class="auto-lazyload swiper-lazy" width="1150" height="599"
                     data-srcset="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp 1x,//i00.eu/img/999997/2300x1260/b9whiv1f/2237.webp 2x"
                     src="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp"
                     data-src="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp"
                     srcset="//i00.eu/img/999997/1150x630a/a7mwzmns/2237.webp 1x,//i00.eu/img/999997/2300x1260/b9whiv1f/2237.webp 2x"
                     data-loaded="true">
            </picture>
            <div class="banner-info infobox-extra-class">
                <h2 class="banner-info__headline">Druhý slide</h2>
            </div>
            <div class="banner-progress">
                <div class="progress"></div>
            </div>
        </div>
    </div>
    <div class="pagination swiper-pagination"></div>
    <div class="button-next swiper-button-next"></div>
    <div class="button-prev swiper-button-prev"></div>
</div>