4

In Drupal 7 I could hide regions as reactions to certain conditions with Context; Here is a pseudocode to explain what I actually did with this module:

If $node = 1;

Than programmatically hide $region = sidebar;

In Drupal 8 for some reason, at least in this era, this functionality has been removed from the module. You can no longer hide regions as a reaction to whatever condition.

Hiding regions is still possible with CSS but it should be noted that programmatically hiding regions is better than CSS hiding as it is more swift and sound, as well as more elegant.

What I've tried instead:

Given the fact Context 8 doesn't include that functionality, I tried to use CSS to hide the region in the given node; I knew from Drupal 7 that if you are inside an node and go to the DOM tree, you can see a unique node class that will serve you in such a particular CSS action (hiding a region in a particular node).

In my Drupal 8 site I went to the DOM but didn't quite find such a class (as appears in Drupal 7 sites).

Therefore I tried using what worked for me in Drupal 7 wondering if from any case it just no longer appear in the DOM. I went to my CSS file and added:

.page-node-364 .region-sidebar-first {display: none !important}

It didn't work, nor similar tryings such as:

#node-364 .region-sidebar-first {display: none !important}
.node-364 .region-sidebar-first {display: none !important}
.364 .region-sidebar-first {display: none !important}

And so forth...

Other actions on that node class variations (neglecting region-sidebar-first) also didn't work even with !important declarations on the CSS and what I tried seemed just to be invalid.

  • I flushed all caches after each try.

Why I'm confused:

What I did saw at DOM and used as a class didn't cause any effect (.364 as mentioned above):

enter image description here


My question:

Due that Context isn't the solution this time, and that seemingly, no usable id or class appears in DOM, I thus ask professional themers here if it is even possible to hide regions for a node in Drupal 8, solely through the CSS, without creating a unique twig file to that particular node.

enter image description here

  • How about hiding the block(s) that are in that region for that particular page? will this do? – No Sssweat Aug 7 '16 at 0:24
  • There are many blocks there appearing for diff CTs and nodes. It will be problematic and inflexible in that case. – JohnDoea Aug 7 '16 at 8:54
  • If you can't find a solution in context, why not hide the region in a page preprocess hook? The node is already preloaded. You can check the node id and unset the variable of the region. – 4k4 Aug 7 '16 at 9:58
  • Must say I never used hooks before (are you sure it is suited to Drupal 8? I heard that in D8 there is something that replaces it). Nonetheless, it sounds an elegant solution; You are most welcome to detail of it in an answer. – JohnDoea Aug 7 '16 at 10:40
3
+100

4k4 suggestion to use the preprocess_page Drupal-function can be done like this:

Preprocess functions go in your themes themeName.theme file, you may need to create this file if your theme does not have one - be sure to clear the Drupal cache after adding or changing code in this file.

function theme-name_preprocess_page(&$variables) {
  // Set the node ID if we're on a node page.
  $nid = isset($variables['node']) ? $variables['node']->id() : '';

  // Unset a region for one node ID.
  if ($nid == '7') {
    unset($variables['page']['sidebar_second']);
  }

  // Unset a region for multiple node ID's.
  if (in_array($nid, ['1','2','3'])) {
    unset($variables['page']['sidebar_first']);
  }
}

If you would rather use CSS (not a bad technique at all), you can add path classes to body also from theme-name.theme, but this time via the preprocess_html function:

use Drupal\Component\Utility\Html;

function theme-name_preprocess_html(&$variables) {
  // Add path classes to body.
  $path = \Drupal::request()->getPathInfo();
  $path_args = explode('/', $path);
  if (count($path_args) >= 3) {
    $variables['attributes']['class'][] = 'path-' . Html::cleanCssIdentifier(ltrim($path, '/'));
  }
}
  • You have to replace HOOK with your extensions machine name, i.e. your theme or module name, as in themename_preprocess_page() – Jeff Burnz Aug 7 '16 at 19:23
  • What is the error message? – Jeff Burnz Aug 10 '16 at 1:18
  • Oh, well this just means there are two functions with the same name: business_preprocess_page(), take the contents of the function you are using from the answer and place it inside the existing business_preprocess_page() declaration (I assume this is on line 33, if you added the second one on line 229), a text editor that has line numbers helps, better still and IDE that warns of duplicates etc, like PHPStorm - delete the duplicate. PHP does not allow duplicated function names. – Jeff Burnz Aug 10 '16 at 10:47
  • Jeff, the first solution works fine but my theme seems not to fit to it, so I tried solution 2 (adding a node class to each node); Please see the attached images --- The solution seems not to work even though there is no error... – JohnDoea Aug 10 '16 at 12:34
  • Well if you remove a whole region then I assume you will need to compensate for that by changing the layout, usually by CSS or changing the classes etc in the layout (if using something like Bootstrap etc). You'd need to clear the cache, otherwise I can't say why it might not be working other than maybe that is the front page? In which case there will already be a class - usually path-frontpage or similar. – Jeff Burnz Aug 10 '16 at 12:50
1

Go to your theme's folder and in your themename.theme file:

function themename_preprocess_page(&$variables) {
  $variables['nid'] = str_replace('/node/', ' ', \Drupal::service('path.current')->getPath());
}

Then in templates folder edit page.html.twig (if you don't have one, copy the one from core /core/themes/bartik/templates and copy it to your theme's templates folder).

Find {{ page.sidebar_first }} and change it to:

{% if nid not in [364, 367] %}{{ page.sidebar_first }}{% endif %}

clear/flush cache to see changes.

0

Here are some ways to do this:

The first way: Reuse class visually-hidden

<?php
use Drupal\node\NodeInterface;
function YourTheme_preprocess_region(&$vars) {
  if ($vars['region'] == 'sidebar_first') {
    if (($node = \Drupal::routeMatch()->getParameter('node')) && $node instanceof NodeInterface) {
      $nid = $node->id();
      if (in_array($nid, ['1', '2'])) {
        $vars['attributes']['class'][] = 'visually-hidden';
      }
    }
  }
}

this way very simple. You just need use function hook_preprocess, don't need add css, don't need override twig template. But I don't like this way because region is hidden. But server need process to render this region.

The second way: unset region before render.

<?php
function YourTheme_preprocess_page(&$vars) {
  if (($node = \Drupal::routeMatch()->getParameter('node')) && $node instanceof NodeInterface) {
    $nid = $node->id();
    if (in_array($nid, ['1', '2'])) {
      unset($vars['page']['sidebar_second']);
    }
  }
}

In this case. You may be need override twig template, but better for performance.

  • May I ask what is the purpose of the second condition && $node instanceof NodeInterface? I'm wondering because I notice on some pages routeMatch() will return an array (one item, the node id), not the node object. Is this why? – Jeff Burnz Aug 10 '16 at 11:47

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.