Разработка мегаменю с изображениями товаров 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка мегаменю с изображениями товаров 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    745
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка мегаменю с изображениями товаров 1С-Битрикс

Текстовый список подкатегорий работает для утилитарного магазина. Для fashion, электроники, мебели — категорию продаёт изображение: кофемашина в разделе «Кофемашины», куртка в разделе «Верхняя одежда». Мегаменю с превью товаров или изображениями разделов повышает кликабельность и снижает навигационные ошибки.

Изображения разделов инфоблока

Разделы инфоблока b_iblock_section имеют поля PICTURE и DETAIL_PICTURE. Дополнительно — пользовательское поле UF_MENU_IMAGE для изображения, специально адаптированного под мегаменю (другой кроп, другие размеры).

// При построении дерева разделов добавляем поля изображений
$res = \CIBlockSection::GetList(
    ['LEFT_MARGIN' => 'ASC'],
    ['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y', 'DEPTH_LEVEL' => [1, 2]],
    false,
    ['ID', 'NAME', 'CODE', 'SECTION_PAGE_URL', 'DEPTH_LEVEL',
     'IBLOCK_SECTION_ID', 'PICTURE', 'UF_MENU_IMAGE']
);

while ($s = $res->GetNext()) {
    // Приоритет: специальное изображение меню > стандартная картинка раздела
    $imageId = $s['UF_MENU_IMAGE'] ?: $s['PICTURE'];
    $s['MENU_IMAGE_SRC'] = $imageId ? \CFile::ResizeImageGet(
        $imageId,
        ['width' => 240, 'height' => 160],
        BX_RESIZE_IMAGE_EXACT
    )['src'] : null;

    $result[$s['ID']] = $s;
}

Изображения популярных товаров раздела

Альтернатива — показывать в мегаменю не изображение раздела, а превью 3-4 популярных товаров. Это живее и информативнее.

namespace Local\Menu;

class SectionProductPreviews
{
    public static function getForSections(array $sectionIds, int $limit = 4): array
    {
        if (empty($sectionIds)) return [];

        $cache = new \CPHPCache();
        $cacheId = 'menu_previews_' . md5(implode(',', $sectionIds));

        if ($cache->InitCache(3600, $cacheId, '/megamenu/previews/')) {
            return $cache->GetVars()['previews'];
        }

        $result = [];
        foreach ($sectionIds as $sectionId) {
            $res = \CIBlockElement::GetList(
                ['RAND' => 'ASC'], // случайные, не всегда одинаковые
                [
                    'IBLOCK_ID'         => CATALOG_IBLOCK_ID,
                    'SECTION_ID'        => $sectionId,
                    'ACTIVE'            => 'Y',
                    'PREVIEW_PICTURE'   => ['>', 0], // только с картинкой
                ],
                false,
                ['nPageSize' => $limit, 'iNumPage' => 1],
                ['ID', 'NAME', 'PREVIEW_PICTURE', 'DETAIL_PAGE_URL']
            );

            $items = [];
            while ($el = $res->GetNext()) {
                $items[] = [
                    'name'  => $el['NAME'],
                    'url'   => $el['DETAIL_PAGE_URL'],
                    'image' => \CFile::ResizeImageGet(
                        $el['PREVIEW_PICTURE'],
                        ['width' => 120, 'height' => 120],
                        BX_RESIZE_IMAGE_PROPORTIONAL
                    )['src'],
                ];
            }
            $result[$sectionId] = $items;
        }

        $cache->StartDataCache();
        $cache->EndDataCache(['previews' => $result]);

        return $result;
    }
}

Шаблон мегаменю с изображениями

// В шаблоне для каждой категории первого уровня
foreach ($arResult['MENU'] as $category):
    $previews = $productPreviews[$category['ID']] ?? [];
?>
<div class="megamenu__dropdown megamenu__dropdown--with-images">
    <div class="megamenu__inner">

        <!-- Колонки подкатегорий слева -->
        <div class="megamenu__nav">
            <?php foreach ($category['children'] as $sub): ?>
            <a href="<?= htmlspecialchars($sub['SECTION_PAGE_URL']) ?>"
               class="megamenu__subcat"
               data-section="<?= $sub['ID'] ?>">
                <?php if ($sub['MENU_IMAGE_SRC']): ?>
                <img src="<?= $sub['MENU_IMAGE_SRC'] ?>"
                     alt="<?= htmlspecialchars($sub['NAME']) ?>"
                     width="60" height="40" loading="lazy">
                <?php endif ?>
                <span><?= htmlspecialchars($sub['NAME']) ?></span>
            </a>
            <?php endforeach ?>
        </div>

        <!-- Превью товаров справа -->
        <?php if (!empty($previews)): ?>
        <div class="megamenu__products">
            <div class="megamenu__products-label">Популярные товары</div>
            <div class="megamenu__products-grid">
                <?php foreach ($previews as $product): ?>
                <a href="<?= htmlspecialchars($product['url']) ?>"
                   class="megamenu__product-card">
                    <img src="<?= htmlspecialchars($product['image']) ?>"
                         alt="<?= htmlspecialchars($product['name']) ?>"
                         width="120" height="120" loading="lazy">
                    <span class="megamenu__product-name">
                        <?= htmlspecialchars($product['name']) ?>
                    </span>
                </a>
                <?php endforeach ?>
            </div>
        </div>
        <?php endif ?>

    </div>
</div>
<?php endforeach ?>

CSS для layout с изображениями

.megamenu__dropdown--with-images .megamenu__inner {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 0;
    min-height: 300px;
}

.megamenu__nav {
    border-right: 1px solid #eee;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.megamenu__subcat {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-radius: 4px;
    transition: background 0.15s;
    text-decoration: none;
    color: inherit;
}

.megamenu__subcat:hover,
.megamenu__subcat.is-active {
    background: #f5f7fa;
}

.megamenu__products-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
    padding: 1rem 1.5rem;
}

.megamenu__product-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    text-decoration: none;
    color: inherit;
    font-size: 0.8125rem;
}

.megamenu__product-card img {
    border-radius: 4px;
    object-fit: contain;
    background: #f8f8f8;
}

Динамическая подгрузка превью

При наведении на подкатегорию — подгружаем товары этой подкатегории через AJAX, не загружаем сразу все:

document.querySelectorAll('.megamenu__subcat').forEach(link => {
    link.addEventListener('mouseenter', async () => {
        const sectionId = link.dataset.section;
        if (link.dataset.loaded) return;

        const data = await fetch(`/local/ajax/menu-products.php?section=${sectionId}`)
            .then(r => r.json());

        const grid = link.closest('.megamenu__dropdown').querySelector('.megamenu__products-grid');
        grid.innerHTML = data.products.map(p =>
            `<a href="${p.url}" class="megamenu__product-card">
                <img src="${p.image}" alt="${p.name}" width="120" height="120" loading="lazy">
                <span>${p.name}</span>
            </a>`
        ).join('');

        link.dataset.loaded = '1';
    });
});

Производительность и кеширование

Загружать изображения всех товаров всех разделов при первом открытии страницы — избыточно. Стратегия:

  • Изображения разделов (UF_MENU_IMAGE) — загружаются вместе с деревом, кешируются 1 час
  • Превью товаров — ленивая загрузка по hover через AJAX, кеш 30 минут на раздел
  • Изображения через loading="lazy" — браузер не грузит скрытые панели

Сроки реализации

Конфигурация Срок
Мегаменю с изображениями разделов 4–5 дней
+ превью популярных товаров, Ajax-подгрузка +2–3 дня
+ анимации, доступность, мобильная версия +2–3 дня