Вкладки удобно собирать прямо из свойств элемента инфоблока: одно свойство – одна вкладка. В исходной версии заметки для этого тянули jQuery и плагин Responsive-Tabs, а разметку строили на цепочке if/elseif с ошибочными условиями вроде "!PROPERTY_ANALYTICS" (строковый литерал всегда истинный – это ничего не проверяет). В 2026 всё делается чище: контент берём из DISPLAY_PROPERTIES в шаблоне компонента, а переключатель пишем на чистом JS по паттерну доступных вкладок W3C ARIA – с поддержкой клавиатуры и скринридеров.
Шаг 1. Выводим свойства как вкладки в шаблоне компонента
Скопируйте шаблон компонента (например, bitrix:news.detail) в свой и работайте в его template.php. Массив $arResult["DISPLAY_PROPERTIES"] содержит только заполненные свойства с готовыми к выводу значениями DISPLAY_VALUE, поэтому лишние проверки не нужны – Битрикс сам не кладёт сюда пустые свойства. Определим список свойств-вкладок и пройдёмся по нему:
<?php
$tabCodes = ['ANALYTICS', 'DESIGN', 'PROGRAMMING', 'TESTING', 'SUPPORT'];
$tabs = [];
foreach ($tabCodes as $code) {
if (!empty($arResult['DISPLAY_PROPERTIES'][$code])) {
$tabs[$code] = $arResult['DISPLAY_PROPERTIES'][$code];
}
}
?>
<?php if ($tabs): ?>
<div class="tabs">
<div class="tabs__list" role="tablist" aria-label="Информация о проекте">
<?php $i = 0; foreach ($tabs as $code => $prop): $i++; ?>
<button class="tabs__tab" role="tab"
id="tab-<?= mb_strtolower($code) ?>"
aria-controls="panel-<?= mb_strtolower($code) ?>"
aria-selected="<?= $i === 1 ? 'true' : 'false' ?>"
tabindex="<?= $i === 1 ? '0' : '-1' ?>">
<?= htmlspecialcharsbx($prop['NAME']) ?>
</button>
<?php endforeach; ?>
</div>
<?php $i = 0; foreach ($tabs as $code => $prop): $i++; ?>
<div class="tabs__panel" role="tabpanel"
id="panel-<?= mb_strtolower($code) ?>"
aria-labelledby="tab-<?= mb_strtolower($code) ?>"
<?= $i === 1 ? '' : 'hidden' ?>>
<?= $prop['DISPLAY_VALUE'] ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
Первая вкладка активна: у её кнопки aria-selected="true" и tabindex="0", у остальных – false и -1. Панели неактивных вкладок скрыты атрибутом hidden.
Шаг 2. Почему важна ARIA-разметка
Простое переключение display:none по клику «для зрячих» ломает доступность: скринридер не понимает, что это вкладки, и не сообщает, какая активна. Паттерн W3C решает это набором ролей и атрибутов:
role="tablist"– контейнер заголовков вкладок;role="tab"+aria-selected– сама вкладка и её состояние;role="tabpanel"+aria-labelledby– область контента, связанная со своей вкладкой;aria-controls– связь вкладки с панелью, которой она управляет.
Кнопки делаем настоящими <button>, а не <a href="#tab-1">: ссылки-якоря прыгают по странице и засоряют историю браузера.
Шаг 3. Доступный переключатель на чистом JS
Скрипт вешает клик и стрелочную навигацию с клавиатуры (влево/вправо, Home/End) – этого ждут пользователи скринридеров от вкладок:
document.querySelectorAll('.tabs').forEach(function (root) {
var tabs = Array.from(root.querySelectorAll('[role="tab"]'));
function activate(tab) {
tabs.forEach(function (t) {
var selected = t === tab;
t.setAttribute('aria-selected', selected);
t.tabIndex = selected ? 0 : -1;
document.getElementById(t.getAttribute('aria-controls')).hidden = !selected;
});
tab.focus();
}
root.addEventListener('click', function (e) {
var tab = e.target.closest('[role="tab"]');
if (tab) activate(tab);
});
root.addEventListener('keydown', function (e) {
var i = tabs.indexOf(document.activeElement);
if (i === -1) return;
if (e.key === 'ArrowRight') activate(tabs[(i + 1) % tabs.length]);
else if (e.key === 'ArrowLeft') activate(tabs[(i - 1 + tabs.length) % tabs.length]);
else if (e.key === 'Home') activate(tabs[0]);
else if (e.key === 'End') activate(tabs[tabs.length - 1]);
});
});
Типичные ошибки
- Строковые «условия» вроде
"!PROPERTY_ANALYTICS". Непустая строка в PHP всегда истинна – такая проверка ничего не фильтрует. Проверяйте реальный ключ массиваDISPLAY_PROPERTIES. - Одинаковые id у разных вкладок. В исходнике два свойства вели на
#tab-4– id должны быть уникальны, иначе ломается связь tab↔panel. - Вкладки-ссылки вместо кнопок.
<a href="#">прыгает по странице; используйте<button>. - Нет навигации с клавиатуры. Без обработки стрелок вкладки недоступны части пользователей – это регресс по a11y.
- Забыли про кеш компонента. Правки в шаблоне могут не проявиться, пока не сброшен кеш компонента и страницы.
Похожие приёмы работы со свойствами инфоблока разобраны в гайдах «Как вывести определённое поле элемента инфоблока» и «Получить название свойства из типа Справочник». А если контент вкладок нужно показывать только на отдельных страницах – см. «Вывод блоков только на определённых страницах».