Skip to content

Pockets

The Pocket pattern allows the user to reveal longform content at their discretion

Version:
0.1.0
Status:
Published

Introduction

The Pocket component contains the page's main content in a truncated form. The purpose of this is to not overwhelm the user with content upon first arriving at the page. With the content shortened it is easier to see (and reach by keyboard or screen reader-based navigation) the functionality at the foot of the page.

A 'Show more' button at the foot of the Pocket allows the reader to unveil the obscured content. Importantly, when the unveiling takes place, a cue to continue reading is inserted between the last item of initial/preview content and the first of the unveiled content. This ensures the user does not lose their place.

Note that, although the patterns are similar, the Pocket differs from the Load more pattern in that it simply obscures content, rather than deferring the loading of content. The Pocket should be implemented without reliance on XHR.

The markup is quite simple, since the Reference implementation uses progressive enhancement, and only adds the button functionality where JavaScript runs. Just two nested wrapping elements are needed.

<div class="gel-pocket">
  <div class="gel-pocket__truncated">
    <!-- content here -->
  </div>
</div>
<main id="main" tabindex="-1">
  <div class="gel-pocket">
    <div class="gel-pocket__truncated">
      <!-- content here -->
    </div>
  </div>
</main>

The class="gel-pocket__truncated" needs to adopt a reasonable fixed height on initialization. Something set in viewport units[2] is recommended since they pertain to a proportion of the viewport and would befit a viewport of any physical height: 50vh is 50% of the height of any screen. This value is set as one of the parameters of the Reference implementation's constructor.

The same element must, of course, take overflow-y: hidden for the truncation to work.

.gel-pocket__truncated {
  overflow-y: hidden;
}

The 'foot' of the Pocket element contains the 'Show more' button, centrally justified. It has no height and appears as a single line, with the button placed centrally over it on the vertical axis, using a transform.

.gel-pocket__foot button {
  transform: translateY(-50%);
}

When the Pocket is in its unveiled/showing state, the button's text changes to 'Show less' (see Recommended behaviour, below) and a class of gel-pocket--foot-shown is applied, enabling a margin-top style to separate the transformed button from the now unveiled content.

.gel-pocket__foot.gel-pocket--foot-shown {
  margin-top: double($gel-spacing-unit);
}

When the "Continue below..." element is focused, it draws attention by showing a brief outline animation:

@keyframes focus {
  0%{
    outline-width: 0px;
  }
  50% {
    outline-width: 2px;
  }
  100% {
    outline-width: 0px; 
  }
}

.gel-pocket__continue:focus {
  outline-style: solid;
  outline-width: 0px;
  outline-offset: 2px;
  animation: focus 1s linear 1;
}

High contrast

How the component looks with a Windows High Contrast Mode theme active.

Black on white theme with all the same shapes intact

The Pocket is treated as a progressive enhancement. It does not initialize at all if JavaScript does not run or IntersectionObserver is not supported. Support for IntersectionObserver is covered by Chrome, Edge, Firefox, Opera, and various Android browsers at the time of writing[3]. Browsers that do not enhance to a Pocket simply show the content in its expanded form.

The purpose of the IntersectionObserver is to apply (polyfilled) inert[4] status to all the visually obscured children within the class="gel-pocket__truncated" element.

if (!item.isIntersecting) {
  // Add the inert attr if the element is cut off
  // or invisible
  item.target.setAttribute('inert', 'inert');
} else {
  // Remove inert from all elements when the
  // truncated element's height becomes 'auto'
  item.target.removeAttribute('inert');
}

Since inert hides items from assistive technologies like screen readers and makes them unfocusable by keyboard, IntersectionObserver creates a parity between the experience of sighted mouse users and other kinds of user. The content is hidden accessibly, until unveiled, and the 'Show more' button is the first tab stop after the last of the items above it.

Switching state

When the 'Show more' button is pressed, the content is expanded. A "Continue reading..." element is injected between the last of the preview/initial content and the first of the unveiled content. This element is focused, meaning keyboard dependent users are relocated to the correct position in the content to continue reading. The Reference implementation lets you choose your own text to override "Continued below..." if so desired.

self.constructor.prototype.showMore = function () {
  this.shown = true;
  this.next = this.truncated.querySelector('[inert]').previousElementSibling;
  this.truncated.style.height = 'auto';
  this.truncated.insertBefore(this.continue, this.next);
  this.continue.focus();
  this.button.textContent = 'Show less';
}

In this state, the 'Show more' button now reads 'Show less', and pressing it switches the Pocket back into its initial truncated state. In this case, focus is not moved anywhere. It remains on the button. The screen reader user can browse back into just the preview content from this point, or continue down into the footer.

Reference implementation

Mane apud me tuebatur armis lectiones, quae maxime competit homini est facultas modern communicationis inter hominum. Credo enim fieri potest, ut signa ostendere societatis, ut Ecclesias faciunt nexum successu cavendum sit.

Et ludunt essential parte cerebri actio constituendum praecepta Dei facere qui maxime operam. Nostra confirmare animi magnitudinem communicationis in illos Adversus habitat. Dat signum aliis dependentia nostrae memoria potenti repente respondeo, primo clamore atque elicere nostris.

Nunc volo experior ut has ideas et progressus communicationis auxilio, ut altius et in historia stadio et cuiusque personae momentum. Idque et consilii causa principalis His prolatis quorum religione precari facti sunt, maxima ex praesentis vitae magna. Multo minus in natura agunt animalia fera cooperatores. Solitum se reflecti pugna aut fuga. Sed qui prima illa initia erant, munera coram communicationis venit autem vir.

Reproductio operam inter duorum hominum feminae. Utrumque iumentum igitur singula signa marium feminarumque producendum oppositum est super feminas varios motus per membra feminae. Ad hunc autem finem animalibus Suspendisse turpis et magna modis intendere sibi a mirum in modum pennas avium ac similibus, et usque ad vesperum vestem et ducendos choros ex hominibus.

Omnes demonstrationes de rebus dici signum. sunt quibus primo instrumentorum communicationis socialis. Nostrum vigorem intensionem quemadmodum si ea ex antiquitate. Ad litteram centena decies annis maiorum et portavit; ad talia signa, ueneris amare lasciuiam. Nee mirum, quae inopinato intrat in sexus tot facies nostrae cogitationes, loquelas et actiones. Est quidem est vetus Adam.

Sed apud unumquemvis hominem quiqui admittit motus magis develop lente. ante iam plene didicerat sunt activae singula unicuique operanti cooperantibus aliis de modi. Quod communicet cum infantem mater ejus, et clamor, et risu; hoc est dicere in minimis sexualem modo imaginabile. Postea successive puer sexus rationes profectae sunt alii hominum, sed iuxta cerebrum non habet diversas vias didicit ex actione.

Open in new window

This topic does not yet have any related research available.

Further reading, elsewhere on the Web


  1. WCAG 2.1 2.4.1 Bypass Blocks, https://www.w3.org/TR/WCAG21/#bypass-blocks ↩︎

  2. CSS Viewport Units: A Quick Start — Sitepoint, https://www.sitepoint.com/css-viewport-units-quick-start/ ↩︎

  3. IntersectionObserver support table — caniuse.com, https://caniuse.com/#feat=intersectionobserver ↩︎

  4. inert polyfill — WICG, https://github.com/WICG/inert ↩︎

Copyright © 2021 BBC. This content is published under the Open Government Licence, unless otherwise noted.