# How to Customize the Side Menu Collapse Behavior and Width Adjustment Settings in Astro Big Doc

> Customize Astro Big Doc side menu collapse behavior and width. Adjust CSS transitions and JS logic to control animation speeds and set custom widths for a personalized navigation experience.

- Repository: [Micro Web Stacks/astro-big-doc](https://github.com/microwebstacks/astro-big-doc)
- Tags: how-to-guide
- Published: 2026-03-07

---

**You can customize the side menu collapse behavior and width adjustment settings in Astro Big Doc by modifying the CSS transition properties in `src/layout/ClientNavMenu.astro` and the width logic in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js), allowing you to control animation speeds, disable transitions, or set custom widths like `250px` instead of the default `20vw`.**

The Astro Big Doc theme from `microwebstacks/astro-big-doc` provides a responsive documentation layout with a collapsible side navigation. Understanding how to customize the side menu collapse behavior and width adjustment settings allows you to tailor the user experience to match your design requirements, whether you need faster animations, fixed pixel widths, or instant state changes.

## Understanding the Side Menu Architecture

The side menu implementation separates concerns between two distinct mechanisms:

- **Submenu Collapse**: Toggles the `hidden` class on nested `<ul class="nested pages_menu">` elements, using CSS `max-height` transitions for smooth slide animations.
- **Global Menu Width**: Controls the entire navigation container's width via the `set_open_state` function in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js), switching between `0vw` (closed) and `20vw` (open).

Both mechanisms rely on CSS transitions defined in `src/layout/ClientNavMenu.astro` for animation smoothing, while JavaScript handles state toggling and localStorage persistence.

## Customizing Submenu Collapse Behavior

### How the Collapse Logic Works

When a user clicks a parent menu item's arrow icon, the event handler in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js) executes the following logic:

```javascript
// In src/layout/client_nav_menu.js
toggler[i].addEventListener("click", function (e) {
  // Toggle the nested <ul> visibility
  this.parentElement.parentElement.querySelector("ul")?.classList.toggle("hidden");
  // Toggle the "expanded" state on the parent <div>
  this.parentElement.classList.toggle("expanded");
  // Persist the new state in localStorage
  const section_name = section_from_pathname(window.location.pathname);
  expand_toggle_save(section_name, toggler[i].getAttribute("data-url"));
  e.preventDefault();
});

```

The `hidden` class controls the `max-height` property through CSS, while the `expanded` class rotates the arrow icon 90 degrees.

### Adjusting the CSS Transition Speed

The animation duration for submenu expansion is controlled by the `transition-duration` property in `src/layout/ClientNavMenu.astro`:

```css
/* In src/layout/ClientNavMenu.astro global style block */
ul.nested.pages_menu{
    max-height: 200vh;
    transition-property: max-height;
    transition-duration: 0.4s;  /* Default speed */
}
ul.nested.hidden.pages_menu{
    max-height: 0px;
    transition-property: max-height;
    transition-duration: 0.4s;
}

```

To make the animation faster, override the duration values:

```css
ul.nested.pages_menu,
ul.nested.hidden.pages_menu{
    transition-duration: 0.2s;  /* Faster collapse */
}

```

### Disabling Animations Completely

For instant state changes without visual transitions, set the duration to zero:

```css
ul.nested.pages_menu,
ul.nested.hidden.pages_menu{
    transition-duration: 0s;  /* Instant toggle */
}

```

Alternatively, you can remove the `transition-property` declarations entirely from the CSS rules.

## Adjusting Side Menu Width Settings

### The set_open_state Function

The global menu open/close state is managed by the `set_open_state` function in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js):

```javascript
// In src/layout/client_nav_menu.js
function set_open_state(section_name){
  const left_open = menu.sections_open[section_name];
  const menu_nav = document.querySelector("nav.pages_menu");
  
  // Disable transition for initial state to prevent animation on page load
  menu_nav.style.transition = "width 0s";
  
  if (left_open){
    menu_nav.style.width = "20vw";          // Default open width
    menu_nav.setAttribute("data-width","20vw");
    menu_nav.classList.add("open");
    menu_nav.classList.remove("closed");
  } else {
    menu_nav.style.width = "0vw";           // Closed state
    menu_nav.classList.add("closed");
    menu_nav.classList.remove("open");
  }
  
  // Re-enable smooth transition after initial setup
  setTimeout(()=>{ menu_nav.style.transition = "width 0.5s"; }, 100);
}

```

The function checks `menu.sections_open[section_name]` to determine the initial state, then applies either `20vw` (open) or `0vw` (closed) to the navigation element.

### Changing the Default Width Value

To use a fixed pixel width instead of the viewport-relative `20vw`, modify the width assignments in `set_open_state`:

```javascript
// Replace the width values in src/layout/client_nav_menu.js
menu_nav.style.width = "250px";          // Fixed width instead of 20vw
menu_nav.setAttribute("data-width","250px");

```

You must also update the CSS in `src/layout/ClientNavMenu.astro` to ensure the transition property accommodates the new unit:

```css
nav{
    width: var(--data_width);
    transition: width 0.5s;  /* Works with both vw and px units */
}

```

### Adding a Custom Width Prop to ClientNavMenu.astro

For a more flexible, component-based approach, extend the Astro component to accept a custom width prop:

```astro
---
// In src/layout/ClientNavMenu.astro
export interface Props {
  open: boolean;
  hash: string;
  openWidth?: string;   // New optional prop
}
const {hash, open, openWidth = "20vw"} = Astro.props;
const data_width = open ? openWidth : "0vw";
const open_class = open ? "open" : "closed";
---

<nav class={`${open_class} pages_menu client`} data-width={data_width} data-hash={hash}>
  <!-- Navigation content -->
</nav>

<style define:vars={{ data_width }}>
  nav{
    width: var(--data_width);
    transition: width 0.5s;
  }
</style>

<script src="./client_nav_menu.js" />

```

Now you can invoke the component with a custom width:

```astro
<ClientNavMenu open={true} openWidth="250px" hash={currentHash} />

```

## Persisting User Preferences with localStorage

Both the submenu expand states and the global menu open state are persisted in the browser's **localStorage** under the key `"menu"`. The relevant utility functions in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js) include:

- **`expand_toggle_save(section_name, href)`**: Toggles the expanded state for a specific submenu item and saves the updated map.
- **`set_open_state(section_name)`**: Reads the open/closed state for the current section and applies it to the DOM.
- **`save_menu()`**: Serializes the entire `menu` object to localStorage.

The storage schema follows this structure:

```javascript
{
  sections_open: {
    "section-name": true,  // Whether the side menu is open for this section
    // ... other sections
  },
  expanded: {
    "section-name": ["url1", "url2"],  // Array of expanded submenu URLs
    // ... other sections
  }
}

```

To reset all user preferences during development or after structural changes, clear the storage:

```javascript
localStorage.removeItem('menu');

```

## Summary

- **Submenu collapse behavior** is controlled by the `hidden` class toggle on `<ul class="nested pages_menu">` elements, with animation speed determined by the `transition-duration` property in `src/layout/ClientNavMenu.astro`.

- **Side menu width adjustment** relies on the `set_open_state` function in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js), which applies either `20vw` (open) or `0vw` (closed) by default, but can be modified to use fixed pixel values or dynamic props.

- **State persistence** automatically saves user preferences to localStorage under the `"menu"` key, tracking both global open/closed states and individual submenu expansion states per section.

- **Customization entry points** include the global CSS block in `ClientNavMenu.astro` for transition timing, the JavaScript width assignments for dimension changes, and optional Astro props for component-level flexibility.

## Frequently Asked Questions

### How do I change the animation speed for submenu expansion?

Modify the `transition-duration` value in the global CSS block of `src/layout/ClientNavMenu.astro`. The default is `0.4s` for both the `ul.nested.pages_menu` and `ul.nested.hidden.pages_menu` selectors. Changing these to `0.2s` makes the collapse faster, while `0s` disables the animation entirely.

### Can I use a fixed pixel width instead of the default 20vw for the side menu?

Yes. Edit the `set_open_state` function in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js) and replace the `20vw` string with a pixel value like `"250px"`. Alternatively, extend `ClientNavMenu.astro` to accept an `openWidth` prop, then pass your desired pixel value when instantiating the component. Ensure the CSS `transition` property in the Astro component remains compatible with the new unit.

### Where is the menu open/close state stored between page refreshes?

The state persists in the browser's **localStorage** under the key `"menu"`. The `save_menu()` function in [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js) serializes the current configuration, including which sections are open and which submenus are expanded. This allows the documentation to remember user preferences across navigation and browser sessions.

### How do I completely disable the width transition animation for the side menu?

To eliminate the sliding animation when opening or closing the entire side menu, set the transition duration to `0s` in the `set_open_state` function of [`src/layout/client_nav_menu.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/layout/client_nav_menu.js). Specifically, change `menu_nav.style.transition = "width 0.5s"` to `menu_nav.style.transition = "width 0s"`, or remove the `transition` property entirely from the `nav` CSS rule in `ClientNavMenu.astro`.