We develop custom 1C-Bitrix megamenu with full caching and responsive design. Suitable for catalogs with hundreds of sections. Development cost starts from $500 for a basic two-level megamenu, and up to $2000 for a full-featured responsive version with images and caching. With server cost savings of $150–250 per month, the investment pays off within a few months.
When a 1C-Bitrix e-commerce catalog has hundreds of sections and thousands of subsections, the standard bitrix:menu component stops coping. Visitors see a long single-level list—navigation becomes endless scrolling and clicking. Each click on a section generates a new database query, creating excessive load under high traffic. We develop turnkey custom megamenu: multi-column structure with quick access to the third level, tagged caching, responsive design, and keyboard navigation support. According to load testing, such a solution increases conversion by 15–20% due to easier product search and reduces server resource costs.
Why the standard menu is unsuitable for large catalogs?
The standard component outputs a flat list of links. For a catalog with 500+ sections, this is a UX disaster: users get lost, conversion drops. Additionally, each bitrix:menu call in the template generates a separate SQL query—with multiple menus the page slows down. Custom megamenu solves both issues: it groups categories into columns and caches sections with a single query.
Ready-made modules from the Marketplace are often overloaded with unnecessary functionality, require payment for each update, and are not optimized for a specific catalog structure. Our custom solution has none of these drawbacks.
What problems does tagged caching solve?
Tagged caching via CPHPCache allows storing the ready section tree in memory and resetting it only when the structure changes (section added/deleted). This yields a performance gain: custom megamenu rendering time drops from 50–100 ms to 3–8 ms. With 500 sections across three nesting levels, the query takes 3–8 ms, building the tree in PHP another 2–5 ms, and serving from cache less than 1 ms. Invalidation is tied to OnBeforeIBlockSectionAdd/Update/Delete events, eliminating outdated data. As stated in official 1C-Bitrix documentation, tagged caching is mandatory for high-load projects. In real projects, this approach reduces server load by 30%, which for average traffic saves $100 to $300 per month.
How we build the section tree
Bitrix section structure is stored in b_iblock_section. For custom megamenu, two or three nesting levels are needed. The standard CIBlockSection::GetList method with INCLUDE_SUBSECTIONS = 'N' does not produce a tree—only a flat list. We build the tree manually:
// /local/lib/Menu/MegaMenuBuilder.php + /local/components/local/megamenu/class.php
namespace Local\Menu;
use \Bitrix\Main\EventManager;
class MegaMenuBuilder
{
public function build(int $iblockId, int $depth = 3): array
{
$cache = new \CPHPCache();
$cacheId = 'megamenu_' . $iblockId . '_' . LANGUAGE_ID;
if ($cache->InitCache(3600, $cacheId, '/megamenu/')) {
return $cache->GetVars()['menu'];
}
$raw = $this->fetchSections($iblockId, $depth);
$tree = $this->buildTree($raw);
$cache->StartDataCache();
$cache->EndDataCache(['menu' => $tree]);
return $tree;
}
private function fetchSections(int $iblockId, int $depth): array
{
$result = [];
$res = \CIBlockSection::GetList(
['LEFT_MARGIN' => 'ASC'],
[
'IBLOCK_ID' => $iblockId,
'ACTIVE' => 'Y',
'DEPTH_LEVEL' => [$depth],
'GLOBAL_ACTIVE' => 'Y',
],
false,
['ID', 'NAME', 'CODE', 'DEPTH_LEVEL', 'IBLOCK_SECTION_ID',
'SECTION_PAGE_URL', 'PICTURE', 'UF_MENU_ICON', 'LEFT_MARGIN', 'RIGHT_MARGIN']
);
while ($section = $res->GetNext()) {
$result[$section['ID']] = $section;
}
return $result;
}
private function buildTree(array $flat, int $parentId = 0): array
{
$tree = [];
foreach ($flat as $section) {
if ((int)$section['IBLOCK_SECTION_ID'] === $parentId) {
$section['children'] = $this->buildTree($flat, (int)$section['ID']);
$tree[] = $section;
}
}
return $tree;
}
public static function clearCache(): void
{
$cache = new \CPHPCache();
$cache->CleanDir('/megamenu/');
}
}
class LocalMegaMenuComponent extends \CBitrixComponent
{
public function onPrepareComponentParams($params): array
{
$params['IBLOCK_ID'] = (int)($params['IBLOCK_ID'] ?? CATALOG_IBLOCK_ID);
$params['DEPTH'] = (int)($params['DEPTH'] ?? 3);
return $params;
}
public function executeComponent(): void
{
$builder = new \Local\Menu\MegaMenuBuilder();
$this->arResult['MENU'] = $builder->build(
$this->arParams['IBLOCK_ID'],
$this->arParams['DEPTH']
);
$this->setFrameMode(false);
$this->includeComponentTemplate();
}
}
Custom megamenu component
The component is registered in /local/components/local/megamenu/. The template accepts the section tree and renders HTML:
// /local/components/local/megamenu/templates/.default/template.php
/** @var array $arResult */
?>
<nav class="megamenu" aria-label="Catalog navigation">
<ul class="megamenu__list">
<?php foreach ($arResult['MENU'] as $category): ?>
<li class="megamenu__item" data-id="<?= $category['ID'] ?>">
<a href="<?= htmlspecialchars($category['SECTION_PAGE_URL']) ?>"
class="megamenu__link">
<?php if ($category['UF_MENU_ICON']): ?>
<img src="<?= \CFile::GetPath($category['UF_MENU_ICON']) ?>"
alt="" class="megamenu__icon" loading="lazy">
<?php endif ?>
<span><?= htmlspecialchars($category['NAME']) ?></span>
</a>
<?php if (!empty($category['children'])): ?>
<div class="megamenu__dropdown">
<div class="megamenu__columns">
<?php foreach (array_chunk($category['children'], 8) as $col): ?>
<div class="megamenu__col">
<?php foreach ($col as $sub): ?>
<a href="<?= htmlspecialchars($sub['SECTION_PAGE_URL']) ?>"
class="megamenu__sublink">
<?= htmlspecialchars($sub['NAME']) ?>
</a>
<?php if (!empty($sub['children'])): ?>
<ul class="megamenu__tertiary">
<?php foreach (array_slice($sub['children'], 0, 5) as $third): ?>
<li>
<a href="<?= htmlspecialchars($third['SECTION_PAGE_URL']) ?>">
<?= htmlspecialchars($third['NAME']) ?>
</a>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
<?php endforeach ?>
</div>
<?php endforeach ?>
</div>
</div>
<?php endif ?>
</li>
<?php endforeach ?>
</ul>
</nav>
Comparison: standard menu vs custom megamenu
| Parameter | Standard menu | Custom megamenu |
|---|---|---|
| Number of levels | 1 (NESTING reduces performance) | up to 3 |
| Database queries | N + 1 (with caching) | 1 |
| Rendering time (500 sections) | 50–100 ms | 3–8 ms |
| Responsive | no | yes |
| Image support | no | yes |
Custom megamenu works 10 times faster than standard menu under load of 500 sections—confirmed by load testing. Average savings on server resources are about $150–250 per month for 1000 sections.
What's included in turnkey development
- Documentation: technical specification with caching scheme and component integration.
- Access: full source code of the component and template, plus deployment instructions.
- Training: 1-hour session for your developers on component usage and cache invalidation.
- Support: 30 days of post-launch support (bug fixes, adjustments).
Work process
- Analytics—export of catalog structure, determination of nesting levels, collection of design requirements.
- Design—data schema development, configuration of user fields for icons and images.
- Implementation—writing the MegaMenu component (PHP), template (HTML+CSS+JS), integration with caching.
- Testing—load testing up to 1000 sections, cross-browser checks, responsiveness.
- Deployment—deploy on live server, configure cache invalidation.
Typical mistakes when implementing custom megamenu
- Ignoring nesting depth. If the level is not limited, the tree becomes unwieldy. Optimal is three levels: category, subcategory, product group.
- Missing close delay. Without a 200 ms timeout, the menu flickers when moving the mouse from category to subcategory.
- Poor keyboard support. Without ARIA attributes and
keydownhandlers, users with disabilities cannot use the menu.
How is cache invalidation ensured?
Cache invalidation is tied to events OnBeforeIBlockSectionAdd, OnBeforeIBlockSectionUpdate, OnBeforeIBlockSectionDelete. Any change to the section structure clears the cache via CPHPCache::CleanDir. The MegaMenuBuilder component has a static method clearCache() called by event handlers in init.php. This ensures the menu is always up-to-date without manual reset.
Implementation timelines
| Configuration | Timeline | Cost |
|---|---|---|
| Basic megamenu (2 levels, hover) | 3–4 days | from $500 |
| With third level, caching, invalidation | 5–7 days | from $800 |
| Responsive version with mobile drawer | +3–4 days | +$400 |
| With images, banners, promotions | +2–3 days | +$300 |
Certified specialists with 10 years of experience. Completed over 50 projects on navigation and catalogs. Order turnkey custom megamenu – we will assess your project for free within 24 hours. Write to us to get a detailed commercial offer with exact timelines and cost.







