Drupal ^8.8 || ^9 - Theming - Add contextual class to Views list page

Drupal Theme - add contextual class

The Problem: The ability to style subtle differences to list pages that are generated out of a single view. Typically, the view would take a contextual argument. In my case the contextual argument is a Taxonomy term ID. The View path would be something like /view-path/% where % is the term ID. We want to set a CSS class unique to the term ID passed as an argument to the View.

I wanted to create visual difference with the use of CSS mask and background properties. To the page of term ID A, I want to use a mask and to term ID B, I want to us background

The solution: Use HOOK_preprocess_html() in a custom module to set a class on the body tag.

The Process

Within out custom module:

  1. Declare the HOOK_preprocess_html() function.
  2. Get the page we are on using \Drupal::request()->getRequestUri();.
  3. Do a check against the returned URI to ensure we are applying functionality to the correct pages.
  4. Extract the term ID from the URI and get the term Name using \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load ($termm_id);
  5. Attach a unique class using $variables['attributes']['class'][].
  6. Test and deploy.

THe HOOK_preprocess_html() Function

Our code will look something like this:

/**
 * Implements HOOK_preprocess_HOOK() for html
 */
function my_module_preprocess_html(&$variables) {
  $current_uri = \Drupal::request()->getRequestUri();
  $uri_parts = explode('/', $current_uri);
  if ( $uri_parts[1] === 'path_segment_from_view') {
    $term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load
    ($uri_parts[2]);
    if ($term) {
      $variables['attributes']['class'][] = 'some-class--' .
        strtolower($term->name->value);
    }
  }
}

If we inspect the body tag on the two pages:

  • The page at /view-path/term-1 now has a class body class="some-class--first-term-name/
  • The page at /view-path/term-2 now has a class body class="some-class--second-term-name/

The CSS

Then in our style sheets we can target each page with our unique class. Something like:

body {
    &.some-class--first-term-mame {
        .target-element {
            &::after {
                background-color: #594f54;
                -webkit-mask: url("path_to_svg.svg") no-repeat 50% 50%;
                mask: url("path_to_svg.svg") no-repeat 50% 50%;
                mask-size: cover;
            }
        }
    }
    &.some-class--second-term-mame {
        .target-element {
            &::after {
                background: transparent url("pat_to_png.png") 0 0 no-repeat;
                background-size: cover;
            }
        }
    }
}

Hire Me? Lets talk!

I am available for remote freelance work to select clients. Please contact me

Related Articles

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.