This page describes the public markup, CSS hooks and JavaScript behaviour of each block so a theme can restyle or extend them.
Assets
When a page contains at least one BlockSuite block, the module appends to the page head:
asset/css/card-slider-tabs.css(all four rendered blocks)asset/js/card-slider-tabs.js(all four rendered blocks)
The script is plain JavaScript with no dependencies. It initialises every .card-slider-block and every .bst-tabs-block on DOMContentLoaded. Blocks inserted into the DOM later (for example by a theme's AJAX loading) are not initialised automatically.
Each rendered block is wrapped by Omeka in the usual <div class="block block-<layout>">, so you can also target .block-cardSlider, .block-itemSlider, .block-tabs and .block-tabsGroup.
Slider markup (Card Slider and Item Slider)
<div class="card-slider-block" role="region" aria-label="…"
data-autoplay="true|false" data-interval="4000" data-visible="3">
<h2 class="card-slider-block__heading">…</h2>
<div class="card-slider-block__viewport">
<div class="card-slider-block__track">
<div class="card-slider-block__card" role="group" aria-label="Slide 1 of 5">
<div class="card-slider-block__inner">…</div>
</div>
</div>
</div>
<button class="card-slider-block__prev" type="button" hidden>‹</button>
<button class="card-slider-block__next" type="button">›</button>
<div class="card-slider-block__live sr-only" aria-live="polite"></div>
</div>
The Item Slider adds item-slider-block to the wrapper and item-slide to each card.
| Class | Element |
|---|---|
.card-slider-block__heading |
Optional <h2> heading |
.card-slider-block__track |
Flex row that is translated horizontally |
.card-slider-block__card |
One slide; flex-basis: calc(100% / var(--cards-visible, 3)) |
.card-slider-block__inner |
Card surface (white, 1px border, 8px radius, flex column) |
.card-slider-block__image |
Card Slider image, 4:3, object-fit: cover |
.card-slider-block__content, __title, __desc, __link |
Card Slider text and link button |
.item-slide__thumbnail, .item-slide__placeholder |
Item Slider image or "No image" SVG placeholder |
.item-slide__meta |
Item Slider property list |
.item-prop, .item-prop--dcterms-title, … |
One property line, with a per-term modifier |
.prop-label, .prop-value |
Property label and first value |
.item-slide__link |
Item Slider link button |
.card-slider-block__prev, __next |
Arrow buttons, absolutely positioned at the vertical centre |
Slider behaviour
data-visibleis the configured desktop count. The script sets the CSS custom property--cards-visibleon the wrapper to 1 below 768px,min(2, desktop)below 1024px, and the desktop count above. The stylesheet also has matching media queries as a fallback before the script runs.- The track moves by setting
transform: translateX(-index * 100 / visible %); there is atransform 0.4s easetransition. - The previous arrow gets the
hiddenattribute at the first position and the next arrow at the last position. Arrows are only rendered when there is more than one card. - Keyboard: ArrowLeft and ArrowRight while focus is inside the wrapper.
- Pointer:
pointerdown/pointermove/pointerupon the track; a horizontal move over 50px advances or goes back, smaller moves snap back. Images havedragstartprevented. - Autoplay (
data-autoplay="true") usessetIntervalwithdata-intervalmilliseconds, stops at the last position, and pauses onmouseenter/focusin, resuming onmouseleave/focusout. Any manual navigation restarts the timer. - The live region text is set to
Slide N of Mon each move.
Tabs markup (Tabs (HTML) and Tabs (Blocks))
<div class="bst-tabs-block" id="bst-tabs-{blockId}">
<h2 class="bst-tabs-block__heading">…</h2>
<div class="bst-tabs-block__intro">…</div> <!-- Tabs (Blocks) only -->
<div role="tablist" class="bst-tabs-block__tablist" aria-label="…">
<button role="tab" id="bst-tab-{blockId}-0" aria-controls="bst-panel-{blockId}-0"
aria-selected="true" tabindex="0" class="bst-tabs-block__tab" type="button">…</button>
</div>
<div role="tabpanel" id="bst-panel-{blockId}-0" aria-labelledby="bst-tab-{blockId}-0"
class="bst-tabs-block__panel bst-tabs-block__panel--active" tabindex="0">…</div>
<div role="tabpanel" id="bst-panel-{blockId}-1" … class="bst-tabs-block__panel" hidden tabindex="0">…</div>
</div>
A Tabs (Blocks) container adds bst-tabs-block--group to the wrapper and is itself wrapped in the standard block <div> (with grid position classes when the page uses the grid layout). The blocks inside a panel keep their own standard block wrappers.
| Class | Element |
|---|---|
.bst-tabs-block__heading |
Optional <h2> |
.bst-tabs-block__intro |
Blocks before the first divider (Tabs (Blocks) only) |
.bst-tabs-block__tablist |
Flex, wrapping, 2px bottom border |
.bst-tabs-block__tab |
Tab button; [aria-selected="true"] is bold with a 3px bottom border |
.bst-tabs-block__panel |
Panel; .bst-tabs-block__panel--active marks the visible one, [hidden] is display: none |
Tabs behaviour
- Clicking a tab, or pressing ArrowLeft, ArrowRight (both wrap), Home or End while a tab has focus, activates that tab: it becomes
aria-selected="true"withtabindex="0", all others gettabindex="-1", and only its panel is shown. - Each
.bst-tabs-blockonly manages the tabs and panels that belong to it directly, so tab blocks nested inside a panel of another tab block work independently. - The default tab is decided server-side and written into the markup (
aria-selected,hidden,--active), so the page renders correctly before the script runs.
Overriding templates
Copy any of these into your theme to change the markup:
view/common/block-layout/card-slider.phtml
view/common/block-layout/item-slider.phtml
view/common/block-layout/tabs.phtml
view/common/block-layout/tabs-group.phtml
The variables each template receives are listed in Block Data. If you keep the class names, role attributes, aria-controls and id pattern, the bundled script continues to work; otherwise dequeue it by not using those classes and provide your own.