Drupal 8 DIY: Creating Content Tabs with Theme Libraries and Slick

Continuing from our previous post, Drupal 8 DIY: Creating a Slideshow with Theme Libraries and Slick, we wanted to build on the power of theme libraries provide us in Drupal 8.

While continuing to showcase examples from Scanse.io, we wanted to share another functionality we implemented with theme libraries -- Content tabs. Drupal 7 has a popular module called, Quicktabs that does this well. However, this module was not ready for Drupal 8 and, even if it was, its reliance on blocks didn’t really fit with our Paragraphs implementation. So, another reason to DIY in the theme layer.


Creating your own content tabs

To achieve this functionality, we decided to lean on theme libraries and slick again. But wait… slick is for slideshows right? Yes, it is. But when you think about it, how different are content tabs? Instead of a dot pager along the bottom, we have a title pager along the top. Instead of sliding right to left, we fade in and out. We decided it would work quite well in this case.


The HTML Markup

As expected our markup is very similar when compared to the slideshow markup presented in Drupal 8 DIY: Creating a Slideshow with Theme Libraries and Slick. The content being rendered within .tabs__tab-item is more complex in this use case. However, this content is styled as a completely decoupled component. In an effort to make the tabs component reusable, we set this up so the tabs display does not care what is actually rendered within the tab itself.



LiDAR for every application

  • Robotic & UAVs


Create a Theme Library

Here we continue to use the same slick theme library that we started for our slideshow. To make this work, we add the following new code for .js-slick-single-item-tabs in slick.config.js.



(function ($, Drupal, window, document) {

  Drupal.behaviors.THEMESlickConfig = {
    attach: function (context, settings) {


        dots: true,
        infinite: true,
        speed: 500,
        fade: true,
        adaptiveHeight: true,
        customPaging: function(slider, i) {
          var title = $(slider.$slides[i]).find('.article__title').text();
          return '' + title + '';
        responsive: [
            breakpoint: 720,
            settings: {
              customPaging: function(slider, i) {
                return '';


} (jQuery, Drupal, this, this.document));

When comparing the slick configuration for .js-slick-single-item-center and .js-slick-single-item-tabs, there are different settings for customPaging. This setting allows us to override the default pager markup. Here, we are contextually getting the text from .article__title and adding it to the pager. The pager will still be at the bottom of the slideshow by default. With a few CSS lines, we move this to the top. In the responsive array we revert back to the dotted pager as this tabbed display didn’t work on smaller screens.


Note: slick’s responsive settings are unfortunately not mobile first. You first define your desktop display and then make adjustments for smaller screens within the responsive array.


Bring it together

Just like the slideshow, we bring this all together in a Twig template.



{# Create classes array #}
{% set classes = [
] %}

{{ attach_library('THEME/slick') }}

  • {% for item in items %}
  • {{ item.content }} {% endfor %}
  • {{>


As we concluded in the previous post, we like the flexibility theme libraries give us on the front-end. Front-end developers now have the tools they need to implement the latest front-end libraries without waiting for a contrib module or diving into custom module development.

However, we feel there is another win here. Conceptually, if Drupal is our content management system, does layout logic belong in Drupal configuration? In most cases, we would say no. The content management system’s job is to load three videos on the page. Whether these videos are presented in a stacked list, a slideshow or content tabs, should be up to the front-end theme. Theme libraries make this possible and give us one more way to decouple our theme.