Активный пункт меню: класс active на PHP и JavaScript

Как подсветить текущий раздел в меню сайта: сравнение адреса на PHP, вариант с массивом пунктов, решение на JavaScript и как это делается в 1С-Битрикс.

При вёрстке шаблона нужно, чтобы пункт меню текущего раздела был выделен. В статичном HTML класс active ставят руками, а на сайте с общим шаблоном его надо вычислять: страница перезагружается, и класс, добавленный по клику, пропадает.

Вариант 1. PHP: сравниваем адрес страницы

<?php
$current = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$menu = [
    '/' => 'Главная',
    '/news/' => 'Новости',
    '/about/' => 'О сайте',
];
?>
<nav><ul>
<?php foreach ($menu as $link => $title):
    $active = $link === '/' ? $current === '/' : strpos($current, $link) === 0; ?>
    <li><a href="<?= $link ?>"<?= $active ? ' class="active" aria-current="page"' : '' ?>><?= htmlspecialchars($title) ?></a></li>
<?php endforeach; ?>
</ul></nav>

Пункт активен, если адрес страницы начинается с его ссылки, — поэтому «Новости» подсвечиваются и на странице отдельной новости. Главная сравнивается точно, иначе она была бы активна везде. Атрибут aria-current="page" сообщает экранным дикторам, где находится пользователь.

Вариант 2. Меню с параметром в адресе

Если разделы открываются по параметру (/index.php?page=news):

<?php $page = $_GET['page'] ?? 'index'; ?>
<a href="?page=index"<?= $page === 'index' ? ' class="active"' : '' ?>>Главная</a>
<a href="?page=news"<?= $page === 'news' ? ' class="active"' : '' ?>>Новости</a>

Значение по умолчанию 'index' решает частую проблему: при первом заходе параметра нет и главная не подсвечивалась.

Вариант 3. JavaScript

<script>
document.querySelectorAll('.menu a').forEach(function (link) {
  const path = new URL(link.href).pathname;
  const here = location.pathname;
  if (path === '/' ? here === '/' : here.startsWith(path)) {
    link.classList.add('active');
    link.setAttribute('aria-current', 'page');
  }
});
</script>

Скрипт сравнивает пути, а не полные адреса, поэтому не зависит от домена и протокола — менять код при переезде сайта не придётся. Минус — подсветка появляется после загрузки скрипта, поэтому серверный вариант надёжнее.

В 1С-Битрикс

Компонент bitrix:menu сам отмечает текущий пункт: в шаблоне меню у элемента есть флаг $arItem["SELECTED"]. Достаточно вывести класс по нему.

Все статьи

Расскажите о задаче — подберём платформу и оценим работу

Обсудить проект