In Drupal, we can use theme_negotiator to switch themes dynamically, theme_negotiator is a service tag that allows us to create our own ThemeNegotiator, A ThemeNegotiator service implements ThemeNegotiatorInterface which specifies two important methods.

  • applies - We can use this method to provide our condition.
  • determineActiveTheme - Determines which theme to apply if our condition is evaluated to true, It basically either returns the theme machine name or NULL.

Example - 

File - my_module.services.yml

services:
  my_module.theme.negotiator:
    class: Drupal\my_module\Theme\ThemeNegotiator
    arguments:
      - '@router.admin_context'
    tags:
      - { name: theme_negotiator, priority: 1000 }

File - /src/Theme/ThemeNegotiator.php

<?php

namespace Drupal\my_module\Theme;

use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\NodeInterface;
use Drupal\Core\Theme\ThemeNegotiatorInterface;

/**
 * Provides a ThemeNegotiator for content type gist.
 */
class ThemeNegotiator implements ThemeNegotiatorInterface {

  /**
   * AdminContext service.
   *
   * @var \Drupal\Core\Routing\AdminContext
   */
  protected $adminContext;

  /**
   * Creates a new ThemeNegotiator instance.
   *
   * @param \Drupal\Core\Routing\AdminContext $admin_context
   *   AdminContext service.
   */
  public function __construct(AdminContext $admin_context) {
    $this->adminContext = $admin_context;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    $node = $route_match->getParameter('node');
    if (!$this->adminContext->isAdminRoute() &&
      $node instanceof NodeInterface &&
      $node->bundle() == "gist") {
      return TRUE;
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function determineActiveTheme(RouteMatchInterface $route_match) {
    return 'gin';
  }

}

 

Output -

ThemeNegotiator Before After