Best method to assign a class to the current page for menu styling?

Is there a preferred method for identifying the current page in the menu? Observing other themes I haven’t found one that does this. But basically I want to set a class of “active” or similar on the menu item for the currently viewed page, issue, etc.

This being my first time using Smarty, and viewing the available variables through {debug}, I came up with this in my header.tpl:

{* Assign a variable for the current location to add a class to the body tag *}
{if $requestedOp && $requestedPage  }
  {assign var="current_page" value="`$requestedOp`-`$requestedPage`"}
{else}
  {assign var="current_page" value="$requestedOp"}
{/if}

I then add class="{$current_page}" to my body element. I can then target the individual menu items using that class on the body with CSS, like .index-about .nmi_type_about .nav-item { … }

But I am wondering if there is a better method. The main problem I see with the above is that the “Current Issue” tab is also highlighted when viewing archived issues.

Okay, I figured out a method on my own that I think works better after re-reading the theme guide. I’ll document it here.

In your custom theme’s main plugin file (YourThemePlugin.inc.php), add this to your init():

HookRegistry::register ('TemplateManager::display', array($this, 'loadTemplateData'));

Now create your loadTemplateData function. This will add the necessary classes for your body element.

public function loadTemplateData($hookName, $args) {
// Retrieve the TemplateManager and the template filename
$templateMgr = $args[0];
//$template = $args[1];

$requestedOp = $templateMgr->get_template_vars('requestedOp');
$requestedPage = $templateMgr->get_template_vars('requestedPage');
	$issue = $templateMgr->get_template_vars('issue');
	
	$isCurrentIssue = 0;
	if ($issue) {
	$isCurrentIssue = $issue->getCurrent();
	}
	
	// If the current issue...
if ( $requestedOp && $requestedPage && $isCurrentIssue ) {
  $bodyClass = $requestedOp . '-' . $requestedPage . '-current';
} elseif ( $requestedOp && $requestedPage ) {
  $bodyClass = $requestedOp . '-' . $requestedPage;
} else {
  $bodyClass = $requestedOp;
}

	$templateMgr->assign(array(
		'bodyClass' => $bodyClass,
	));
}

In your template’s header.tpl, replace the <body> tag with:

<body class="{$bodyClass}">

This worked well for me and keeps it in the theme rather than a plugin or something.

In my CSS, I did this:

// Highlight the current page
.index-about .nmi_type_about .nav-link, .view-issue-current .nmi_type_current .nav-link, .view-article-current .nmi_type_current .nav-link, .archive-issue .nmi_type_archives .nav-link, .view-issue .nmi_type_archives .nav-link, .view-article .nmi_type_archives .nav-link, .submissions-about .nmi_type_submissions .nav-link, .editorialTeam-about .nmi_type_editorial_team .nav-link, .contact-about .nmi_type_contact .nav-link { {
	background-color: #fff;
	color: #000;
}

For clarification, I am using a child theme I made of the healthSciences theme, which uses Bootstrap 4. You should adjust your CSS above accordingly to match the menu structure of your theme.

2 Likes

Hi @dalemoore

First of all, I thank you about your post. I was looking how set a class to my menu’s item for indicate the current page, with your method I have accomplished it.

1 Like