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%.
<i:img src="zbozi.img" format="800x600" />
<i:img src="zbozi.img" format="800x600,300x200" sizes="(min-width: 500px) 50vw, 100vw" />Attributes
| Attribute | Required | Description |
|---|---|---|
| src | yes | Twig object |
| format | yes | image dimensions |
| sizes | no | same as HTML5 sizes -- required when multiple dimensions are specified |
| watermark | no | image will have a watermark |
| fill | no | pad the image with white borders |
| vector | no | use PNG/SVG |
| transparent | no | image has transparency |
| quality | no | low/normal/high/lossless (default: normal) |
| lazyload | no | src 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.
<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:img360 -- 360 Product View
<i:img-360 product="product" />
<i:img-360 product="product" format="800x600,300x200" sizes="(min-width: 500px) 50vw, 100vw"/>Attributes
| Attribute | Required | Description |
|---|---|---|
| product | yes | Product object |
| format | no | image dimensions (same as i:img). Default: [500x500, 1000x1000, 1500x1500, 2000x2000] |
| sizes | no | responsiveness for images (same as i:img) -- required when multiple dimensions are specified |
| zoom | no | integer zoom value (default: 3) |
| no-steps | no | hide forward/backward step buttons |
| no-fullscreen | no | hide fullscreen button |
| no-play | no | hide play/stop button |
| hide-logo | no | hide 360 view logo |
| bottom-circle | no | show bottom 360 circle |
| lazyload | no | load library and images only when the element enters the viewport |
| lazyload="click" | no | load library and images only when the element is clicked |
| hidden | no | element is hidden (display:none) and activated via JS (used for fancybox) |
| autoplay | no |
To display inside a FancyBox, add a thumbnail image and a hidden player. The specific class name does not matter -- what matters is pairing the thumbnail with the player.
<a data-src=".hidden-fancybox-360" data-type="inline" href="javascript:;" data-fancybox>
<i:img src="product.firstImage360" format="350x350" />
</a>
<i:img-360 product="product" hidden class="hidden-fancybox-360" />i:video
{%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
| Attribute | Required | Type | Description |
|---|---|---|---|
| src | yes | twig | Twig object |
| width | no | int | width in pixels (no units) |
| height | no | int | height in pixels (no units) |
| controls | no | string | true / false |
| loop | no | string | true / false |
| color | no | string | HEX color code for the icon |
| autoplay | no | ||
| 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.
<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>$('.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).
{# 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.
<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><!-- 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
| Attribute | Required | Description |
|---|---|---|
| lat="" | no | latitude of the map center |
| lon="" | no | longitude of the map center |
| zoom="" | no | default map zoom |
| height="" | no | default map height (400px) |
| controls="off" | no | hide map controls |
| grayscale | no | |
| clusters="" | no | default distance for markers in a cluster (40) |
| cluster-class="" | no | custom class for the cluster |
| view="" | no | basic / hybrid / aviation / tourist / winter (default: basic) |
| view-layers="basic,aviation" | no | enable map layer switching -- basic / hybrid / aviation / tourist / winter (default: "basic,aviation,hybrid,tourist,winter") |
i:map-point Attributes
| Attribute | Required | Description |
|---|---|---|
| lat="" and lon="" | yes | point coordinates. Either lat/lon or address must be provided |
| address="" | yes | point address. Either lat/lon or address must be provided |
| icon="/images/home.svg" | no | |
| size="20x20" | no | custom marker size. Default size: 23x32 |
| label="Centrala" | no | hover title |
| header="Opening hours" | no | card title |
| tags="praha" | no | tags separated by commas |
| code="xxx" | no | marker 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
| Class | Description |
|---|---|
| embed-map-cluster | general 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.
<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><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
| Attribute | Required | Description |
|---|---|---|
| selector | yes | map selector, e.g. .global-map |
| filter | yes | array of tag arrays |
| boolean | no | auto-center map on filtered POIs. Default: false |
<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
| Attribute | Required | Description |
|---|---|---|
| lat="" and lon="" | yes | point coordinates. Either lat/lon or address must be provided |
| address="" | yes | point address. Either lat/lon or address must be provided |
<i:map-route-link lat="50.7700158" lon="15.0595950">Popisek</i:map-route-link><!-- generated output -- subject to change! -->
<a class="map-route-link" data-lat="50.7700158" data-lon="15.0595950" href="//mapy.cz/?planovani-trasy&rc=95ra0x1qpF&rs=&rs=coor&ri=&ri=&mrp=&mrp={"c":111}">
Popisek
</a>Link to mapy.cz
Creates a URL to a POI on mapy.cz.
<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><!-- generated output -- subject to change! -->
<a class="map-link" href="//mapy.cz/zakladni?x=14.446071624756&y=50.090213775635&id=12903247&source=firm">Helveti</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=14.429894447327&y=50.081184387207&id=12914136&source=firm">Jadi.cz Praha</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=15.056777954102&y=50.770107269287&id=2099659&source=firm">JAdi.cz Liberec</a><br>
<a class="map-link" href="//mapy.cz/zakladni?x=15.172479629517&y=50.72388458252&id=726263&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.
<i:banners source="repository.banner.findBy({sectionCode: 'testovaci'})" plugin="swiper">
<source format="1150x630" src="desktop"/>
</i:banners><!-- 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.
<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><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.
<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><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.
<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><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
| Parameter | Required | Description |
|---|---|---|
| source | yes | repository.banner.findBy() |
| priority | no | allowed values: high / low (default: high). low -- lazyload on all images; high -- respects visible-slides |
| visible-slides | no | number of banners without lazyload (default: 1) |
| wrap | no | inner banner wrapper |
| class | no | add a custom class |
| banner-item-class | no | add a custom class to the banner items wrapper |
| banner-wrap-class | no | add a custom class to individual banner wrappers |
| picture-class | no | add a custom class to the picture wrapper |
| plugin | no | add helper classes for a specific plugin, e.g. swiper |
| click | no | configure banner click behavior. Allowed values: banner / cta / off. |
Banner Attributes
| Attribute | Required | Description |
|---|---|---|
| arrows | no | show arrows for slide navigation |
| dots | no | show slide navigation dots |
| progress | no | show progress bar |
| thumbnails | no | show thumbnails with banner titles |
| transparent | no | image has transparency |
| fill | no | pad image with white borders |
Banner source elements
| data-role | Required | Attributes |
|---|---|---|
| desktop | yes | format -- required banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified (default: 80vw), class -- add a custom class |
| tablet | no | format -- banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified, media -- same as HTML5 media, class -- add a custom class |
| mobile | no | format -- banner dimensions, sizes -- same as HTML5 sizes, required when multiple dimensions are specified, media -- same as HTML5 media, class -- add a custom class |
Complete data-role list for banners
| data-role | Required | Attributes |
|---|---|---|
| info-box | no | tag definition |
| title | no | tag definition |
| description | no | tag definition |
| cta | no | tag definition |
<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><!-- 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>