Reference Omeka Classic plugin

Theming and Markup

This page describes how Block Suite's blocks take their look from the theme, their public markup and CSS hooks, and how a theme can override them.

Two kinds of blocks

Blocks the Theme Engine already styles print the engine's own markup and classes, so every RefBytes theme (Vitrine, Confetti, Plinth, Overprint) restyles them with no extra CSS:

Block Engine markup
Hero .v-hero (--overlay, --split, --below, --plain), .v-hero__image, .v-hero__content, .v-hero__title, .v-hero__text, .v-hero__credit, .v-kicker, .v-button
Lead Paragraph .v-lead
Callout .v-callout
Pull Quote figure.v-pullquote > blockquote
Columns (flowing) .v-columns
Call to Action .v-cta inside .section-tint, .section-primary, .section-accent or .section-dark with .section-contained
Item Cards, Item Slider ul.v-results > li.v-card (the theme's own common/engine/card.php)
Spotlight article.v-spotlight, .v-spotlight__media, .v-spotlight__body, .v-spotlight__title, dl.v-spotlight__fields
Logo Wall ul.v-logos, .v-logos__caption
Divider .v-divider--ornament, .v-divider--space

Blocks the engine has no component for (Statistics, Timeline, Item Slider's row and buttons, Tabs, Accordion, Search Box, split Columns) use Block Suite's own classes: the same as Block Suite for Omeka S (.bst-stats, .bst-timeline, .card-slider-block, .bst-tabs-block, .bst-accordion, .bst-search), so a theme's integration styles for the S module apply on Classic too.

Every block's root element carries bst-block and bst-block--<name> (bst-block--hero, bst-block--stats…), and Exhibit Builder wraps it in <div class="exhibit-block layout-bs-<name>">.

Cascade layers

Block Suite's stylesheets put their rules in the engine's engine.content cascade layer. A theme's rules in @layer theme, its unlayered integration stylesheet and an admin's custom CSS all override them, whatever their specificity. With a theme that is not built on the engine, Block Suite also loads blocksuite-standalone.css, an unlayered stylesheet scoped to .bst-block that gives the engine classes a plain look and keeps the theme's button, a and heading styles from reaching the block's controls.

Tokens

Colors, radius and spacing come from the engine's --v-* tokens, through --bst-* tokens (the same names as in Block Suite for Omeka S), each with a fallback for themes that define no tokens:

Token Reads Fallback Used for
--bst-surface --v-surface Canvas Stat cards, inputs, slider buttons
--bst-surface-alt --v-surface-alt 6% CanvasText Search panel
--bst-text, --bst-text-muted --v-text, --v-text-muted CanvasText, 72% Text, descriptions, inactive tabs
--bst-accent-text --v-primary-text --bst-text Figures, timeline dates
--bst-border, --bst-border-strong --v-border, --v-border-strong 20%, 55% CanvasText Rules; input and button borders (3:1)
--bst-accent, --bst-on-accent --v-primary, --v-on-primary LinkText, Canvas Buttons, selected tab, timeline markers
--bst-link --v-link LinkText Suggested searches
--bst-radius, --bst-radius-button --v-radius, --v-radius-button 6px Corners
--bst-gap, --bst-touch --v-space-m, --v-touch 1.5rem, 2.75rem Space between cards; 44px targets

To restyle Block Suite alone, set --bst-* tokens on .bst-block or one block, in your theme layer:

@layer theme {
    .bst-block { --bst-radius: 0; }
    .bst-stats { --bst-accent-text: var(--v-accent); }
}

Markup of Block Suite's own blocks

Statistics

<div class="bst-block bst-block--stats bst-stats" data-style="plain|cards" data-align="center|start">
  <h2 class="bst-stats__heading">…</h2>
  <div class="bst-stats__intro v-flow">…</div>
  <ul class="bst-stats__list">
    <li class="bst-stats__item"><span class="bst-stats__value">56</span><span class="bst-stats__label">Seasons</span><span class="bst-stats__description">…</span></li>
  </ul>
</div>

Timeline

<div class="bst-block bst-block--timeline bst-timeline">
  <h2 class="bst-timeline__heading">…</h2>
  <div class="bst-timeline__intro">…</div>
  <ol class="bst-timeline__list">
    <li class="bst-timeline__event [bst-timeline__event--image]">
      <p class="bst-timeline__date"><time datetime="1938-12-18">December 18, 1938</time></p>
      <div class="bst-timeline__body">
        <h3 class="bst-timeline__title"><a href="…">…</a></h3>
        <figure class="bst-timeline__media"><img class="bst-timeline__image" …><figcaption class="bst-timeline__caption">…</figcaption></figure>
        <div class="bst-timeline__text">…</div>
      </div>
    </li>
  </ol>
</div>

Item Slider

<div class="bst-block bst-block--slider card-slider-block item-slider-block" role="region" aria-roledescription="carousel" aria-labelledby="…-heading"
     data-autoplay="false" data-interval="6000" data-visible="3" style="--cards-visible: 3">
  <div class="card-slider-block__header">
    <h2 class="card-slider-block__heading v-preview__heading" id="…-heading">…</h2>
    <div class="card-slider-block__controls">
      <button class="card-slider-block__rotation bst-button bst-button--small bst-button--outline">Stop automatic slide show</button>
      <button class="card-slider-block__prev" aria-label="Previous items">…</button>
      <button class="card-slider-block__next" aria-label="Next items">…</button>
    </div>
  </div>
  <div class="card-slider-block__viewport">
    <ul class="card-slider-block__track v-results v-results--static" data-layout="grid"><li class="v-card">…</li>…</ul>
  </div>
  <div class="card-slider-block__live bst-sr-only" aria-live="polite" aria-atomic="true"></div>
</div>

The viewport is a horizontal scroll area with snap points. The buttons stay hidden until the script runs and only show when the row is wider than the slider; the block then has data-scrollable.

Tabs

<div class="bst-block bst-block--tabs bst-tabs-block" id="bst-tabs-1" data-bst-ready="true">
  <h2 class="bst-tabs-block__heading" id="bst-tabs-1-heading">…</h2>
  <div class="bst-tabs-block__intro">…</div>
  <div role="tablist" class="bst-tabs-block__tablist" aria-labelledby="bst-tabs-1-heading">
    <button role="tab" class="bst-tabs-block__tab" id="bst-tabs-1-tab-0" aria-controls="bst-tabs-1-panel-0" aria-selected="true" tabindex="0">…</button>
  </div>
  <div role="tabpanel" class="bst-tabs-block__panel bst-tabs-block__panel--active" id="bst-tabs-1-panel-0" aria-labelledby="bst-tabs-1-tab-0" tabindex="0">
    <h3 class="bst-tabs-block__panel-heading">…</h3>   <!-- shown only without JavaScript -->
    <div class="bst-tabs-block__content">…</div>
  </div>
</div>

Accordion

<div class="bst-block bst-block--accordion bst-accordion" id="bst-accordion-1" data-allow-multiple="false">
  <h2 class="bst-tabs-block__heading bst-accordion__heading">…</h2>
  <div class="bst-accordion__item">
    <h3 class="bst-accordion__header">
      <button type="button" class="bst-accordion__trigger" id="…-button-0" aria-expanded="true" aria-controls="…-panel-0">
        <span class="bst-accordion__label">…</span><span class="bst-accordion__icon" aria-hidden="true"></span>
      </button>
    </h3>
    <div class="bst-accordion__panel" id="…-panel-0" role="region" aria-labelledby="…-button-0" data-open>
      <div class="bst-accordion__content">…</div>
    </div>
  </div>
</div>

Closed panels get hidden="until-found". Do not set display: none on .bst-accordion__panel in a theme, or find-in-page breaks; put spacing on .bst-accordion__content.

Search Box

<div class="bst-block bst-block--search bst-search" data-scope="site|items">
  <h2 class="bst-search__heading" id="…-heading">…</h2>
  <form class="bst-search__form" role="search" action="/search" aria-labelledby="…-heading">
    <label class="bst-search__label [bst-sr-only]" for="…-input">Search</label>
    <div class="bst-search__row">
      <input type="search" class="bst-search__input" name="query" …>
      <button type="submit" class="bst-button bst-search__button">Search</button>
    </div>
  </form>
  <div class="bst-search__suggestions"><p class="bst-search__suggestions-label">Try:</p><ul>…</ul></div>
</div>

JavaScript

blocksuite.js has no dependencies. It adds bst-js to <html> (also added by a one-line head script on exhibit pages, so the first tab shows alone before the script runs), sets up every slider, tab block and accordion on DOMContentLoaded, and exposes BlockSuite.init(element) for blocks added later. When a tab or section opens, its panel fires a bubbling bst:panel-shown event and the window a resize event, so maps and viewers inside can measure themselves.

Overriding templates

Exhibit layouts are found through Exhibit Builder's view paths, so a theme can replace any of them by copying the file into the theme:

themes/<theme>/exhibit-builder/exhibit_layouts/bs-hero/layout.php
themes/<theme>/exhibit-builder/exhibit_layouts/bs-hero/layout.css

The shared partials that layouts and shortcodes render can be overridden at the theme root:

themes/<theme>/blocksuite/cards.php      slider.php  stats.php  search.php  cta.php
themes/<theme>/blocksuite/timeline.php   tabs.php    accordion.php  card.php

Keep the class names and ARIA attributes if you want the script and the stylesheets to keep working. Templates use $this->blockSuite() for options, records, images, dates and escaping.

Log in for Support