Amazon template (HTML, CSS, JS) for integration. Guide.

Instructions for novice web developers and Cotonti CMF users who want to create a modern, adaptive website header with multiple offcanvas menus like on Amazon.

Rating based on reviews:
Total stars received: 0
Total reviews: 0
Average rating: 0
Filed under: User Blog

Complete Guide to Creating Responsive Navigation with Slide-Out Menus (Amazon-Like Header)

Introduction

This article is a detailed guide for beginner web developers and Cotonti CMF users who want to create a modern, responsive website header with several off-canvas menus. We will analyze a ready-made template that mimics the navigation of the popular Amazon online store. You will learn how three independent side menus (two on the left and one on the right) work, how they are built with HTML and CSS, and how they are controlled with JavaScript. All files (HTML, CSS, JS) are provided separately and are ready to use in your projects.

This material is purely educational. You are free to take this code as a basis, modify it, and integrate it into your themes for Cotonti CMF or any other CMS. We will go through each block of code step by step, explaining "what goes where and why" so that you get a complete picture.


1. Project Overview and File Structure

We have three files in front of us:

  • index.html — page markup.
  • style.css — all styles.
  • script.js — menu logic.

This is a classic approach that separates structure, presentation, and behavior. The HTML remains clean, with no CSS or script lines (except for linking external libraries). Such code is easier to maintain and modify.

The project uses two external libraries:

  • Bootstrap 5.3.2 (CSS and JS) — only for the grid, some components, and icons.
  • Font Awesome 6 — for icons (arrows, cart, hamburger, etc.).

All our menus and styles are written manually, without using ready-made Bootstrap components (e.g., offcanvas). This was done intentionally to ensure full control over behavior and animations.

Now let's move on to the main part — how it all works.


2. HTML: Page Skeleton and Element Layout

The HTML document represents a typical modern site structure. It consists of several main blocks:

  • Top bar (.top-line) — logo, search, account, orders, and cart icons.
  • Bottom bar (.nav-line) — All button and navigation links (Today's Deals, Customer Service, etc.).
  • Three independent off-canvas menus with overlays.
  • Main content (placeholder).
  • Footer.

Let's examine each block in detail.

2.1. Header: Top Bar .top-line

<div class="top-line">
  <a href="/" class="logo"><span>A</span>mazon</a>
  <div class="search-box">
    <select><option>All</option><option>Books</option></select>
    <select><option>All Departments</option><option>Arts & Crafts</option></select>
    <input type="text" placeholder="Search Amazon">
    <button><i class="fas fa-search"></i></button>
  </div>
  <div class="header-icons">
    <a href="#" id="accountListsLink"><span>Hello, sign in</span><strong>Account & Lists</strong></a>
    <a href="#"><span>Returns</span><strong>& Orders</strong></a>
    <a href="#" class="cart-icon"><i class="fas fa-shopping-cart"></i><span class="cart-count">0</span></a>
  </div>
</div>

There are three child elements arranged in a row thanks to display: flex on .top-line.

Logo — a simple link with the class .logo. The letter "A" is wrapped in a <span> so it can be styled separately (yellow). The logo itself is pushed to the left edge.

Search box — a .search-box block that takes up all available space due to flex: 1. It contains two dropdowns (categories), a text field, and a button. The outer border is yellow to match Amazon's style.

User icons — another flex container .header-icons with three elements. The first link Account & Lists has the ID accountListsLink, which is later used in JavaScript to open the right menu. The other two links don't lead anywhere yet, but in a real project they would point to the corresponding pages. The cart icon contains an item counter (currently 0).

Important: the entire header is wrapped in a flex row, and when space is insufficient (e.g., on tablets), elements can wrap to the next line thanks to flex-wrap: wrap.

2.2. Bottom Navigation Bar .nav-line

<div class="nav-line">
  <button class="mobile-nav-toggle" id="mobileNavToggle"><i class="fas fa-bars"></i></button>
  <button class="all-btn" id="allBtn"><i class="fas fa-bars"></i> All</button>
  <div class="nav-links" id="navLinks">
    <a href="#">Today's Deals</a>
    <a href="#">Customer Service</a>
    <a href="#">Gift Cards</a>
    <a href="#" id="helpSettingsLink">Help & Settings</a>
  </div>
</div>

This block is also a flex container and contains three parts:

  • Hamburger button .mobile-nav-toggle — shown only on mobile devices (via a media query). It serves to open the mobile menu (the set of links navLinks). Hidden on desktops (display: none).
  • "All" button — the main element that opens the left off-canvas shop menu. It has a yellow background and a "burger" icon. The click handler is attached to #allBtn.
  • Navigation links — wrapped in #navLinks. On desktop they are displayed in a row, on mobile they are hidden and drop down as a vertical list when the hamburger is clicked. The "Help & Settings" link has id="helpSettingsLink" so it can be found by the script to open the second left menu.

Thus, we have two navigation methods: via the All button (product catalog) and via text links (help and settings).

2.3. Off-Canvas Menu and Overlay System

There are three off-canvas menus and three overlays in the document:

  1. Shop (the "All" button) — left menu.
  2. Help & Settings — left menu.
  3. Account & Lists — right menu.

Each has its own overlay (semi-transparent background) and menu container. The overlay and menu are placed directly in <body> before the main content, but they could also be placed at the end — it's not critical since they are fixed positioned.

Let's examine the first menu as an example:

<div class="offcanvas-overlay" id="overlay-shop"></div>
<div class="offcanvas-menu" id="offcanvas-shop">
  <div class="offcanvas-header">...</div>
  <div class="offcanvas-user">...</div>
  <div class="offcanvas-body">
    <!-- menu layers -->
  </div>
</div>

Overlay (#overlay-shop) — an empty div that is initially invisible (opacity: 0, visibility: hidden). When the menu opens, it receives the class .open, which makes it visible and darkens the screen. Clicking the overlay closes the corresponding menu.

Menu (#offcanvas-shop) has fixed positioning on the left, initially shifted off-screen (transform: translateX(-100%)). When the class .open is added, the transformation is reset to translateX(0), and the menu slides in smoothly. The menu structure is always the same:

  • offcanvas-header — title with a close button (X).
  • offcanvas-user — a greeting block with a user icon.
  • offcanvas-body — the main area where menu levels (main and submenus) are placed.

For the right Account & Lists menu, the class .offcanvas-menu-right is used, which differs only in that it is attached to the right side (right: 0; left: auto;) and initially shifted to the right (transform: translateX(100%)). Otherwise, the logic is the same.

2.4. Level System in Left Menus

In the left menus (Shop and Help & Settings), a multi-level structure with animated transitions is used. This is done with nested div elements having the class .menu-level, which are positioned absolutely inside .offcanvas-body. Thanks to this, each level occupies the entire available space, and when switching levels, one slides smoothly to the left while the other appears from the right.

Here is how it looks in the shop markup:

<div class="offcanvas-body">
  <!-- Main level -->
  <div class="menu-level active" id="mainLevelShop"> ... </div>

  <!-- Electronics submenu -->
  <div class="menu-level next" id="submenu-electronics"> ... </div>

  <!-- Computers submenu -->
  <div class="menu-level next" id="submenu-computers"> ... </div>

  <!-- Other submenus -->
</div>

Each menu-level is an independent layer. Only one layer is visible at a time — the active one (class active); the rest are either in the initial state (class next — shifted to the right by 100%) or hidden on the left (class hidden-left). Transitions are animated via CSS transition: transform 0.3s ease.

Main level (#mainLevelShop) contains product categories. Some of them have nested submenus (e.g., Electronics). These items are marked with the class .has-submenu and a data-submenu attribute whose value indicates the corresponding layer (e.g., data-submenu="electronics"#submenu-electronics).

Submenu (e.g., #submenu-electronics) starts with a "back" button (back-button) that returns to the main level. Then follows a list of subcategories (links with the class .subcategory-item). A submenu can also contain its own submenus (nesting is unlimited, although the demo uses two levels).

The Help & Settings menu is structured similarly: there is a main level #mainLevelHelp and several submenus (#submenu-help-seasons, #submenu-help-days).

The right Account & Lists menu does not use levels; it's just a scrollable list of links. Therefore, its .offcanvas-body has overflow-y: auto instead of overflow: hidden; position: relative;.

2.5. Main Content and Footer

After the menus comes a <div class="container mt-5"> with a title and empty space — this imitates content. The footer is standard, containing four columns with links. These parts do not affect the menu operation but show how the template looks in full context.


3. CSS: Turning Markup into an Interface

Now let's move on to the styles. They are located in the style.css file and are responsible for the appearance, positioning, and animations of all elements.

3.1. CSS Custom Properties

At the very beginning, variables are declared in the :root pseudo-class:

:root {
  --amazon-dark: #131921;
  --amazon-light-dark: #232f3e;
  --amazon-yellow: #febd69;
  --amazon-white: #ffffff;
  --menu-width: 365px;
}

These are the colors and the base menu width. Using variables makes it easy to change the color scheme in the future: just modify the values in one place. The --menu-width variable is used to set the width of the off-canvas containers.

3.2. Header and Navigation Styles

Top bar .top-line has a dark background, white text, and a flex layout. flex-wrap allows elements to wrap if they don't fit in a single line (useful on small screens). align-items: center vertically centers all elements.

The logo is styled: the font is large and bold, and the letter "A" inside the span is yellow.

The search box .search-box is a flex container with a border. Its flex: 1 makes it occupy all the available space between the logo and the icons. Inside, the select, input, and button are styled without borders, with appropriate padding and font sizes.

The user icons .header-icons is another flex container, with links arranged vertically (flex-direction: column) to display text in two lines (e.g., "Hello, sign in" on top, "Account & Lists" below). The cart icon is slightly larger, and the counter is positioned absolutely relative to it.

Bottom bar .nav-line is similar to the top bar but with a different background. The "All" button has a yellow background, black text, and a flex layout for the icon and text.

The navigation links .nav-links allow horizontal scrolling if they don't fit (overflow-x: auto) and are usually displayed in a row.

3.3. Overlay and Common Off-Canvas Styles

The overlay .offcanvas-overlay is a fixed, full-screen element with a semi-transparent black background. By default, it is invisible (opacity: 0; visibility: hidden;). When the class .open is added, both properties change to 1 and visible, with a smooth transition transition: opacity 0.2s, visibility 0.2s.

For left menus, the class .offcanvas-menu is used. It is also fixed, takes the full height of the screen, has a width of var(--menu-width) (but no more than 85vw on very narrow screens). transform: translateX(-100%) shifts it past the left edge. transition: transform 0.3s ease ensures a smooth slide-in when the .open class is added (the transformation becomes translateX(0)).

The right menu .offcanvas-menu-right differs only in its position: left: auto; right: 0; and an initial shift of translateX(100%). When opened, it slides in from the right.

Inside the menu, the structure is:

  • offcanvas-header — dark background, white text, flex row with a title and close button.
  • offcanvas-user — slightly lighter, with a user icon.
  • offcanvas-body — occupies the remaining space (flex: 1), has position: relative; overflow: hidden;. This is necessary because absolutely positioned menu levels will be placed inside.

3.4. Menu Level System (for Left Menus)

Each .menu-level is position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow-y: auto;. Thanks to this, the layer completely covers the parent .offcanvas-body and can scroll if the content doesn't fit.

By default, a layer has the class .next, which sets transform: translateX(100%) — meaning the layer is shifted to the right and invisible. When a layer becomes active (.active), its transform: translateX(0) is applied, and it comes to the foreground with z-index: 2. If the previous layer slides to the left, it gets the class .hidden-left with transform: translateX(-100%).

Thus, three classes control the layer's position:

  • .active — the currently visible layer.
  • .next — a layer positioned "to the right" waiting its turn.
  • .hidden-left — a layer that has moved to the left (e.g., the main level when a submenu is open).

The transition between them is animated via transition: transform 0.3s ease.

3.5. Elements Inside the Menu

Section titles .menu-section-title — gray text, uppercase, small font.

Menu items .menu-item — a flex row spanning the full width, with padding, a bottom border. On hover, the background changes to light gray.

If an item contains a submenu, it additionally has the class .has-submenu. Inside it, there is .menu-arrow (a right arrow) pushed to the right edge via margin-left: auto.

The "back" button .menu-item.back-button has a darker background and bold font.

Sub-items (in submenus) use the class .subcategory-item — block elements with their own padding.

Separator .menu-separator — just a gray line.

3.6. Styles for the Right Menu

The right menu doesn't need levels, so its .offcanvas-body simply scrolls. Inside, an .account-menu-list is used, styled similarly to menu items but without absolute positioning. The "Sign in" button is styled separately.

3.7. Responsiveness

The media query @media (max-width: 768px) includes several changes:

  • In the top bar, the search wraps to a new line (order: 3), making it full width.
  • The hamburger button .mobile-nav-toggle becomes visible (display: block).
  • The navigation links #navLinks turn into a dropdown menu: absolute positioning under the bar, hidden by default (display: none), and shown when the .show class is added (via JS).
  • Links in the dropdown become block-level with padding and separators.

Note that the off-canvas menu width is limited to max-width: 85vw so it doesn't extend beyond the viewport on small screens.


4. JavaScript: Bringing the Menu to Life

The script.js file contains all the logic for managing the three off-canvas menus and mobile navigation. It is wrapped in an Immediately Invoked Function Expression (IIFE) to avoid global pollution.

4.1. Shop Menu ("All" Button)

const allBtn = document.getElementById('allBtn');
const overlayShop = document.getElementById('overlay-shop');
const offcanvasShop = document.getElementById('offcanvas-shop');
const closeShop = document.getElementById('offcanvasCloseShop');
const mainLevelShop = document.getElementById('mainLevelShop');

Here we get the elements by their id. If an element is not found, the script won't break because we check for the existence of the allBtn button before attaching a handler (implicitly, via the variable's existence). In real code, it's useful to add checks.

Opening and closing functions:

function openShopMenu() {
  overlayShop.classList.add('open');
  offcanvasShop.classList.add('open');
  document.body.style.overflow = 'hidden';
  resetShopMenu();
}
function closeShopMenu() {
  overlayShop.classList.remove('open');
  offcanvasShop.classList.remove('open');
  if (!document.getElementById('offcanvas-help').classList.contains('open') &&
      !document.getElementById('offcanvas-account').classList.contains('open')) {
    document.body.style.overflow = '';
  }
}

Opening: we add the class open to the overlay and menu, block page scrolling (body overflow hidden), and reset the menu levels to the main one (resetShopMenu function).

Closing: we remove the open class, but restore scrolling only if no other menu is open. This prevents scroll flickering when switching between menus.

Resetting levels:

function resetShopMenu() {
  mainLevelShop.classList.add('active');
  mainLevelShop.classList.remove('hidden-left');
  offcanvasShop.querySelectorAll('.menu-level').forEach(level => {
    if (level !== mainLevelShop) {
      level.classList.add('next');
      level.classList.remove('active');
    }
  });
}

This function ensures that the main level becomes active again and all submenus move to the "next" state (shifted to the right). This is needed every time the menu opens so the user always starts from the beginning.

Handlers:

  • allBtn.addEventListener('click', ...) — opens the shop menu.
  • overlayShop.addEventListener('click', closeShopMenu) — closes on overlay click.
  • closeShop.addEventListener('click', closeShopMenu) — closes via the X button.

Submenus in the shop:

const shopSubmenuTriggers = offcanvasShop.querySelectorAll('.menu-item.has-submenu');
shopSubmenuTriggers.forEach(trigger => {
  trigger.addEventListener('click', function(e) {
    e.stopPropagation();
    const submenuId = this.dataset.submenu;
    const submenu = document.getElementById('submenu-' + submenuId);
    if (!submenu) return;
    mainLevelShop.classList.remove('active');
    mainLevelShop.classList.add('hidden-left');
    submenu.classList.remove('next');
    submenu.classList.add('active');
  });
});

For each item with a submenu, we attach a click handler. On click:

  • We find the corresponding layer by its id, formed as 'submenu-' + data-submenu value (e.g., submenu-electronics).
  • We shift the main level to the left (class hidden-left).
  • We remove the next class from the target submenu and add active to make it appear.

The "back" buttons work similarly but in the opposite direction:

const shopBackButtons = offcanvasShop.querySelectorAll('[data-back]');
shopBackButtons.forEach(btn => {
  btn.addEventListener('click', function(e) {
    e.stopPropagation();
    const parentLevel = this.closest('.menu-level');
    parentLevel.classList.remove('active');
    parentLevel.classList.add('next');
    mainLevelShop.classList.remove('hidden-left');
    mainLevelShop.classList.add('active');
  });
});

Here we find the parent level (the current submenu), hide it (next), and show the main level.

4.2. Help & Settings Menu

The principle is absolutely identical to the shop menu, but its own elements and IDs are used. The functions openHelpMenu, closeHelpMenu, resetHelpMenu work the same way. The only difference is how the submenu IDs are formed: 'submenu-help-' + submenuId. That's why in the markup these submenus have IDs like submenu-help-seasons.

When opening Help & Settings, we also close any other open menus to avoid overlapping:

helpLink.addEventListener('click', function(e) {
  e.preventDefault();
  if (offcanvasShop.classList.contains('open')) closeShopMenu();
  if (document.getElementById('offcanvas-account').classList.contains('open')) {
    closeAccountMenu();
  }
  openHelpMenu();
});

4.3. Right Account & Lists Menu

There are no submenus here, so the logic is simpler. When opening, we just add the open class; when closing, we remove it. When opening, we also close any other menus.

4.4. Closing with the Escape Key

document.addEventListener('keydown', function(e) {
  if (e.key === 'Escape') {
    if (offcanvasShop.classList.contains('open')) closeShopMenu();
    if (offcanvasHelp.classList.contains('open')) closeHelpMenu();
    if (offcanvasAccount.classList.contains('open')) closeAccountMenu();
  }
});

This is a global handler that closes any open menu when the Escape key is pressed.

4.5. Mobile Navigation (Hamburger)

const mobileNavToggle = document.getElementById('mobileNavToggle');
const navLinks = document.getElementById('navLinks');
mobileNavToggle.addEventListener('click', function(e) {
  e.stopPropagation();
  navLinks.classList.toggle('show');
});
document.addEventListener('click', function(e) {
  if (!navLinks.contains(e.target) && e.target !== mobileNavToggle) {
    navLinks.classList.remove('show');
  }
});

Clicking the hamburger toggles the show class on #navLinks, making it visible (in CSS: #navLinks.show { display: flex; }). Clicking anywhere in the document except the menu itself and the hamburger hides it. This is a standard pattern for dropdown menus.

4.6. Important JavaScript Nuances

  • e.stopPropagation() is used so that a click on a button or menu item doesn't bubble up to document and cause other menus to close.
  • Checking other open menus in the closing functions ensures that body overflow is not restored prematurely.
  • Resetting levels every time the menu opens prevents the situation where a user sees a submenu left over from the previous session.

5. How to Integrate into Cotonti CMF or Another Engine

To use this template in your project:

  1. Copy the contents of index.html into your theme file (e.g., header.tpl in Cotonti). Usually the site header is included separately.
  2. Include style.css in the <head> section of your template (or add the contents to the main theme CSS file). Make sure the paths to Bootstrap and Font Awesome are correct.
  3. Include script.js before the closing </body> with the defer attribute so the script runs after the DOM is loaded. If your engine includes jQuery, that won't interfere — our script doesn't use jQuery.
  4. Replace the links in the menus with real URLs for your site. For Cotonti, these might be tags like {PHP.cfg.mainurl}, {PHP|cot_url('page', 'm=news')}, etc.
  5. If desired, change the colors and menu width in the CSS variables (:root).

6. Possible Improvements and Extensions

  • Adding accordion animation for mobile: currently, submenus always work as layer slides. On mobile, you could change the behavior so that subcategories expand within the item (like on the original Amazon site).
  • Dark theme: using CSS variables and a data-theme attribute, you can easily switch the appearance.
  • Accessibility improvements: add aria-* attributes, keyboard navigation within the menu.
  • Cart integration: replace the static counter with a dynamic one via JavaScript.

7. Conclusion

We have thoroughly explored how a modern responsive template with multiple independent slide-out menus is built. You learned how to create a semantic structure with HTML, style and animate elements with CSS, and control their behavior with JavaScript. This code can serve as an excellent starting point for creating your own themes for Cotonti CMF and other CMSs.

Don't be afraid to experiment: change widths, colors, add new items and levels. Understanding the basic principles outlined in this article will help you confidently create your own interfaces.

Happy coding!



Reviews

No reviews yet


Comments (0)

No comments yet
Only registered users can post new comments

Recommended Products and Services

Cotonti CMF: Plugin Installation, Integration, and Adaptation

Cotonti CMF: Plugin Installation, Integration, and Adaptation

professional services for the installation, deep integration and adaptation of plug-ins for Cotonti
Index36: Modern Theme for Cotonti CMF

Index36: Modern Theme for Cotonti CMF

Index36, a website theme for Cotonti, is a complete website management ecosystem. The main focus is

Page Discussion in Telegram

Content author

webitproff

Offline

Sodium Carbonate

Last logged: 2026-08-31 03:01

About me briefly
Support and development of web projects on the CMF Cotonti: private messengers via the website, open and closed small social networks, trading platforms and marketplaces, freelance and services exchange portal, catalogs of goods from wholesale suppliers, dropshipping platforms, online stores, and much more.
View developments and download
Public portfolio of my works and developments
Telegram for messages
@webitproff
Telegram channel
@s/aBuyFILE
  • Page published: 2026-07-14 18:17
  • Last update: 2026-07-14 18:32
  • Language:

Связанные статьи

Recommended forum topics for this article

"Index36" - основной шаблон сайта для Cotonti. Руководство по установке

"Index36" - основной шаблон сайта для Cotonti. Руководство по установке

Инструкция по установке темы "Index36" на сайт Cotonti Siena CMF. Удачной установки и красивого
#188 | Постов: 16 | Просмотров: 2298