One navigation, not a mobile copy

The catalogue needed one semantic set of destinations that could change presentation without becoming a second, reduced mobile information architecture.

My first mobile navigation for C62Y was a second navigation.

The desktop catalogue had a left rail with categories, search, reference links, and local product sections. I hid that rail at a narrow width and created a shorter list behind a “Menu” link near the top of the page.

It looked tidy. It also created two information architectures in one template.

The shortened menu omitted reference pages I assumed were less important on a phone. Its labels drifted from the desktop navigation. When I added a category, I updated one list and forgot the other. Keyboard behavior depended on a script that treated a link as a button. With the script broken, the compact control pointed to # and the hidden navigation remained hidden.

I had solved a crowded layout by duplicating meaning, reducing capability, and adding a new failure mode.

The better design began with a less exciting requirement: the site would have one semantic set of destinations. Presentation could change. The navigation’s content and ordinary link behavior would not.

The left rail had mixed three jobs

Before I could make the navigation responsive, I had to understand what the desktop rail contained.

It mixed:

  • Global site destinations such as the catalogue home and reference library.
  • Category navigation such as power tools and measuring equipment.
  • Local page links such as specifications, manuals, and related products.

They looked like one vertical list because the desktop layout had space for one vertical list. On a narrow screen, collapsing all of them behind one button produced a long menu whose hierarchy depended on indentation and memory.

The content work separated the jobs. Global navigation remained consistent across the site. Category browsing belonged to the catalogue context. Local page links belonged after the product identity, near the sections they described.

This reduced the compact menu before any link was removed. The improvement came from assigning scope, not deciding that mobile users deserved fewer destinations.

The desktop layout could still place some regions near one another. The document no longer pretended proximity made them one component.

Width did not tell me the user’s intent

I had justified the reduced mobile menu by imagining a hurried user who needed only products and search. That story was convenient and unsupported.

A phone could be used beside the equipment, where manuals and reference information were more important than on a desk. A narrow browser window on a desktop did not change the user’s task at all. A person using zoom could trigger the compact layout for accessibility, not because they wanted a simplified site.

Viewport width described available presentation space. It did not grant permission to infer intent.

I kept every global destination in the compact presentation. I changed grouping, label length where the label could remain equally clear, and when secondary context appeared. I did not maintain a mobile-only content policy.

This removed another subtle cost. With one destination set, analytics, testing, active-state logic, and access keys no longer had to account for two implementations of the same route.

Responsive navigation became a problem of interaction and layout rather than content synchronization.

The navigation began as a heading and list of ordinary links in the document. Without CSS or JavaScript, it was visible and usable.

CSS placed it in the desktop rail at wider widths. At narrow widths, the list remained in normal flow near the top.

That baseline was longer than the enhanced compact version, but it preserved the task. A failed script could make the page less convenient and could not make it unnavigable.

The enhancement script had a strict sequence:

  1. Find the navigation and verify the required DOM methods.
  2. Create a real button with an accessible label.
  3. Connect the button state to the navigation region.
  4. Insert the button into the document.
  5. Apply the enhanced class that allows the list to begin collapsed.

The order prevented the most damaging partial state. The navigation was never hidden before the control capable of revealing it existed and worked.

I did not call this a sophisticated architecture at the time. It was a direct response to a failure that had left a menu control visible and every destination inaccessible.

The link that wanted to be a button

The first compact control was an anchor with href="#". It looked consistent with navigation links and behaved badly.

Activating it changed the URL fragment, sometimes moved the page to the top, and announced itself as a link even though it did not navigate anywhere. Keyboard handlers compensated for some behavior and multiplied inconsistency.

The control changed interface state, so it became a button. The links inside the menu remained links.

The distinction improved behavior without custom code. The button participated in keyboard activation correctly. It could expose expanded state. It did not need a fake destination or a click handler that canceled navigation.

This was an early lesson in choosing an element by its action rather than its appearance. CSS could make a button fit the visual system. Script should not make a link imitate a button when the platform already provided one.

The button label described the region rather than the implementation. “Browse catalogue” was clearer than “Toggle.” Expanded and collapsed state was available programmatically and reflected visually with text and an icon that did not carry meaning alone.

I initially moved keyboard focus into the first navigation link when the menu opened. It felt helpful and made the next action surprising for someone who wanted to close the menu or continue through the page in ordinary order.

The final disclosure kept focus on the button. Opening made the links available immediately after it in the tab sequence. Closing removed them from the interactive path and returned the interface to the state represented by the same focused button.

If the user followed a link, navigation behaved normally. If they pressed Escape while focus was inside the open menu, the menu closed and focus returned to the button. Clicking outside did not become the only close method.

I tested the interaction with keyboard alone, at increased zoom, and after long labels wrapped. The menu did not use a fixed height for its open state, because content and text size determined that height.

The test exposed a problem with an animated max-height trick. The chosen maximum clipped a translated test label and made duration proportional to content length. I removed the decorative animation. State clarity mattered more than motion.

CSS and script needed one source of truth

The first implementation used a CSS media query to hide the desktop list and JavaScript’s viewport width to decide whether the compact behavior was active. At the breakpoint edge, rounding and scrollbar differences allowed them to disagree.

The script could think the menu was in desktop mode while CSS had hidden it. Resizing an open menu could preserve an inline display: none into the wide layout.

I simplified responsibility. CSS owned layout. The script owned disclosure state only when the enhanced control was present. Wide-layout rules made the navigation visible regardless of collapsed state, and the script did not write inline display values.

On resize, state could remain collapsed internally without hiding the wide list. Returning to narrow width restored the last deliberate compact state. I later decided that defaulting closed after a wide session was more predictable and reset it explicitly at the transition.

The exact policy mattered less than avoiding two independent breakpoint engines.

This problem was a small preview of later state-management lessons. When two layers can both decide whether something exists, disagreement becomes a product state even if neither layer models it.

The desktop rail indicated the current category with a muted background and darker text. In the compact menu, the treatment was hard to distinguish among tightly stacked links and disappeared in forced-color settings.

I added a textual current-page indication available to assistive technology and used weight, border, and position in addition to color. The current link remained a link because revisiting or copying the URL was still valid.

The page heading also established location. Navigation state supplemented it rather than becoming the only orientation cue.

For local section links, the active state was not updated continuously while scrolling. The first attempt used scroll position to highlight one section and flickered near boundaries. It added motion and uncertain location to a page whose headings and URL fragments already provided dependable navigation.

I removed the live scroll spy. A feature can look informative while making the interface less stable.

Search did not belong inside the menu button

The desktop rail included a search field. My first compact design placed it inside the collapsed menu. Searching then required opening a navigation control even though search was one of the primary catalogue tasks.

I moved the compact search entry beside the navigation button. The full form remained in the document and could occupy different layout regions at different widths without being duplicated.

At a narrow width, the form used the available line and the button sat beside it. At wider widths, the same form moved into the rail. Source order still made sense because search followed the global catalogue entry point.

This challenged another visual assumption: everything in the left rail was not one component. Search and navigation happened to share a column on desktop and had different task priority on narrow screens.

Responsive layout was most successful when it revealed those distinctions rather than carrying the desktop grouping into a smaller box.

Touch changed target size, not semantics

I increased the compact menu’s target size and spacing for touch. I did not add touch-only gestures or remove keyboard-visible focus treatment.

The same button and links supported pointer, touch, and keyboard activation. Hover styles remained optional feedback. Important subnavigation did not depend on hovering a category.

The first desktop category menu had revealed children on hover. On touch, the parent link and expansion action competed. I replaced the pattern with visible category pages rather than building a complex dual-purpose control.

A person could follow the category and browse its subcategories there. The global menu stayed shallow, predictable, and complete.

This was a useful form of subtraction. Responsive work did not require reproducing every desktop interaction on touch. It required preserving the destination and task through an interaction suited to the platform.

The compact menu looked correct with the short English labels I had chosen. I added deliberately long test labels and increased the browser’s minimum font size.

The button icon collided with text. A fixed line height clipped a two-line link. Indentation left too little measure for a nested category. The close state relied on an icon positioned as if the button were always one line.

I removed fixed heights, kept icons in normal layout, and reduced nesting. The navigation row aligned content at the start when labels wrapped instead of centering one line against a two-line block.

The fixes improved ordinary content too. A slightly longer category no longer triggered a local exception. The menu could accommodate user settings without becoming visually broken.

I later learned much more about localization and writing direction, but this early pressure test established the useful habit: labels are content with unpredictable dimensions, not tokens chosen to fit a component.

The failure state belonged in the test plan

After the hidden-navigation incident, I added a simple matrix:

  • HTML only: every destination visible and usable.
  • HTML and CSS, no script: every destination visible in narrow and wide layouts.
  • Full enhancement: compact disclosure at narrow width, visible rail at wide width.
  • Script stops before control insertion: baseline remains visible.
  • Script stops after control insertion but before enhancement class: button may be redundant, links remain visible.
  • Resize while open and closed: wide navigation remains visible and narrow state is predictable.
  • Keyboard and zoom: no hidden focus targets or clipped labels.

The test matrix focused on partial execution rather than only named browsers. Browser compatibility still mattered, but a current browser could experience a blocked script, extension interference, or transient load failure.

The matrix also made implementation order reviewable. Progressive enhancement was no longer a value I claimed. It was a set of states the page could demonstrate.

Removing the duplicate list had an operational benefit. A category entered one source and appeared wherever the navigation was rendered. Active state used one route model. Link checking covered one destination graph. Labels changed once.

The CSS was more complex than a permanently visible list and less complex than two components with synchronized content. The JavaScript became smaller because it managed one disclosure instead of constructing an alternate menu.

The accessibility story improved for the same reason. There was one reading order, one set of labels, one current-page state, and one focus model to test.

This was my first strong experience of accessibility, resilience, and maintainability pointing toward the same architecture. They were not separate quality layers added after the visual design. One semantic navigation made all three more achievable.

The menu was allowed to be ordinary

I had wanted the mobile navigation to feel novel enough to justify the redesign. The final interaction was a button revealing a list of links.

Its success came from details that did not photograph dramatically: correct element choice, safe initialization, complete destinations, meaningful scopes, predictable focus, text that wrapped, and a wide layout that could not inherit a hidden inline state.

The ordinariness was useful. Navigation should spend very little of a person’s attention on understanding itself.

The more interesting design work happened in deciding what was global, categorical, local, and search. Once those relationships were correct, the interaction could rely on familiar browser behavior.

One prototype stored the selected category and open local section in JavaScript state. Refreshing the page reset both. Copying the URL could not reproduce the view, and the browser’s Back button moved between pages without restoring the interface I had left.

I returned category and section state to URLs. Categories were routes. Local sections used stable fragments. The compact menu’s open or closed presentation remained ephemeral because it did not identify content worth sharing.

This division kept durable location in the platform’s navigation model and transient disclosure in the component. The browser could restore history, open a link in a new tab, and expose destinations to search and assistive technology without a custom router.

The active-link treatment derived from the current route rather than a click handler. Arriving through search, a bookmark, or a manually entered URL therefore produced the same orientation as clicking through the menu.

It was another case where a richer client abstraction would have added less capability than respecting the primitive already present. The navigation behaved like navigation because destinations stayed addresses, not hidden application state.

What changed in my practice

The duplicate mobile menu had treated responsive design as maintaining a second reduced interface for one class of devices. The rebuilt navigation treated responsiveness as presenting one information architecture under different space constraints.

That changed the questions I asked:

  • Is this truly one set of destinations or several scopes placed together?
  • Does width change presentation or actual access?
  • What remains if enhancement fails halfway through?
  • Does the element’s native behavior match the action?
  • Can the label wrap and the input method change without inventing another component?

The result was not a universal navigation pattern. Larger, deeper products may need different structures. C62Y needed a small global list, category entry points, local section links, and search. Naming those jobs kept the component honest.

The next interface problem resisted this kind of simplification. The comparison table was genuinely two-dimensional. A narrow viewport could not show every relationship at once, and turning it into a stack of cards preserved content while destroying comparison. That required a different kind of compromise.