How can I hide a block on specific content types in Drupal 8? There's the setting for displaying blocks only on specified content types, but not for hiding them. Looks like the PHP filter is out in D8, so not sure how to go about this. I'm sure it's a simple fix.


You can use this module:

Block Visibility Groups

Here you can configure a visibility group which hides blocks for a specific content type.

The visibility groups not only provide more options for block visibility, they are also reusable, that means you can apply the same settings on multiple blocks.

Ctools also provides the functionality to hide blocks for content types, but there was an issue, I don't know if this is resolved.

  • Hah, good idea. I needed a solution to make up for settings in another Block Visibility Group, so I don't know why I didn't think to set up a second one with the negated condition. Thanks!
    – Mrweiner
    Oct 18 '16 at 17:46
  • The issue was that negating content type condition causes block to be removed from every non-node enity page. And this module perpetuates it, since it uses ctools to accomplish content type validation. More on the topic drupal.org/project/block_visibility_groups/issues/2820631
    – Dominika
    Nov 3 '20 at 13:14

Another way you can do this, just via code (in this example, in your theme's .theme file), is like so:

 * Implements theme_preprocess_block().
function themename_preprocess_block(&$variables) {
  // Remove page title block on 'article' content type.
  if ($variables['elements']['#id'] == 'themename_page_title') {
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node && $node->getType() == 'article') {
      $variables['content'] = [];
  • The above code has some issue in if ($block_id == 'themename_page_title') because there is no variable define for $block_id. So the actual code is if($variables['plugin_id'] == 'themename_page_title').
    – Manav
    Mar 27 '18 at 9:13

Using geerlingguy's code as is, you'll get a notice about $block_id variable being undefined. Place $block_id = $variables['elements']['#id']; before the if statement to get rid of the notice.


I tried multiple methods, including the one provided by CTools, Block Visibility Groups and Context. Context works, but it's tedious, since you have to recreate entire blocks layout for specific condition and it crashes when installed with Menu Position. So far the best solution seems to be hook_block_access()

use Drupal\block\Entity\Block;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\Core\Access\AccessResult;

 * Implements hook_block_access().
function MYMODULE_block_access(Block $block, $operation, AccountInterface $account) {

  $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof NodeInterface) { //checking if we're on node page
      if($node->type->entity->label() == NODE_TYPE && $block->getRegion() == REGION){
          if( $operation == 'view' && $block->getOriginalId() == BLOCK_ID){
              return AccessResult::forbiddenIf($block
              ->getRegion() == REGION)
    return AccessResult::neutral();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.