Navigation Architecture at Scale
As page count eclipses 200, traditional hierarchical dropdown menus become a severe usability liability. They hide options until explicit hover actions, force reliance on short-term memory, and trigger cascading usability failures with imprecise cursor movements.
Mega-Menu Implementation
Mega-menus are imperative for a 223-page architecture. By exposing the full breadth of a macro-category simultaneously, users can visually compare all available choices without friction.
Desktop Mega-Menu Specifications
| Feature | Implementation |
|---|---|
| Two-Dimensional Layout | Options grouped logically within large drop-down panel |
| Visual Anchors | Subtle iconography for high-priority items |
| Featured Content | Highlighted CTAs (e.g., "Know Your Rights" printable) |
| Whitespace | Ample spacing to denote hierarchy vs. nested indentations |
<nav class="mega-nav" aria-label="Main navigation">
<ul class="mega-nav__list">
<li class="mega-nav__item">
<button class="mega-nav__trigger"
aria-expanded="false"
aria-controls="menu-emergency">
Emergency Help
</button>
<div class="mega-nav__panel" id="menu-emergency" hidden>
<div class="mega-nav__columns">
<div class="mega-nav__column">
<h3>Immediate Help</h3>
<ul>
<li><a href="/printables/red-card/">Red Card</a></li>
<li><a href="/emergency/hotlines/">Crisis Hotlines</a></li>
</ul>
</div>
<div class="mega-nav__column">
<h3>Rapid Response</h3>
<ul>
<li><a href="/resources/legal-observer/">Legal Observer</a></li>
<li><a href="/resources/coalition/">Find Local Network</a></li>
</ul>
</div>
<div class="mega-nav__featured">
<a href="/printables/" class="mega-nav__cta">
Download All Printables →
</a>
</div>
</div>
</div>
</li>
<!-- Additional menu items -->
</ul>
</nav>
Mega-Menu Accessibility (WCAG)
| Requirement | Implementation |
|---|---|
| Keyboard Navigation | Tab and Enter support |
| ARIA Roles | aria-expanded, aria-controls, aria-haspopup |
| Focus Trapping | Focus remains within menu until dismissed |
| Escape Key | Closes menu and returns focus to trigger |
// Mega-menu keyboard handling
const megaNav = document.querySelector('.mega-nav');
megaNav.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeAllPanels();
document.activeElement.closest('.mega-nav__item')
?.querySelector('.mega-nav__trigger')?.focus();
}
});
function closeAllPanels() {
megaNav.querySelectorAll('.mega-nav__panel').forEach(panel => {
panel.hidden = true;
panel.previousElementSibling.setAttribute('aria-expanded', 'false');
});
}
Mobile Navigation Patterns
Navigating 223 pages on a 375-pixel viewport requires strict spatial economy. The traditional hamburger menu is critically insufficient for deep hierarchies if implemented as a single, endlessly scrolling vertical list.
Accordion Progression
The mobile menu must utilize a nested accordion structure. Tapping a macro-category expands sub-sections inline, pushing other items down rather than forcing page loads.
<nav class="mobile-nav" aria-label="Mobile navigation">
<div class="mobile-nav__accordion">
<details class="mobile-nav__section">
<summary class="mobile-nav__trigger">
Emergency Help
<span class="mobile-nav__count">12 resources</span>
</summary>
<ul class="mobile-nav__links">
<li><a href="/printables/red-card/">Red Card</a></li>
<li><a href="/emergency/hotlines/">Crisis Hotlines</a></li>
<li><a href="/resources/legal-observer/">Legal Observer</a></li>
</ul>
</details>
<details class="mobile-nav__section">
<summary class="mobile-nav__trigger">
Know Your Rights
<span class="mobile-nav__count">22 guides</span>
</summary>
<!-- Nested subsections -->
</details>
</div>
</nav>
.mobile-nav__section {
border-bottom: 1px solid var(--color-border);
}
.mobile-nav__trigger {
display: flex;
justify-content: space-between;
padding: 1rem;
font-weight: 600;
cursor: pointer;
}
.mobile-nav__section[open] .mobile-nav__trigger {
background: var(--color-highlight);
}
.mobile-nav__links {
padding: 0 1rem 1rem;
}
.mobile-nav__links a {
display: block;
padding: 0.75rem 0;
border-bottom: 1px solid var(--color-border-light);
}
Sticky Bottom Navigation for Crisis
Emergency resources must bypass standard menu interaction entirely. A persistent sticky bottom bar ensures zero-click discovery during high-stress scenarios.
<nav class="crisis-bar" aria-label="Emergency actions">
<a href="/emergency/" class="crisis-bar__item crisis-bar__item--emergency">
<span class="crisis-bar__icon">🆘</span>
<span class="crisis-bar__label">Emergency</span>
</a>
<a href="tel:+18001234567" class="crisis-bar__item">
<span class="crisis-bar__icon">📞</span>
<span class="crisis-bar__label">Hotline</span>
</a>
<a href="/printables/red-card/" class="crisis-bar__item">
<span class="crisis-bar__icon">🔴</span>
<span class="crisis-bar__label">Red Card</span>
</a>
</nav>
.crisis-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-around;
background: var(--color-surface);
padding: 0.5rem 0 env(safe-area-inset-bottom);
box-shadow: 0 -2px 10px rgba(0,0,0,0.15);
z-index: 1000;
}
.crisis-bar__item--emergency {
background: var(--color-error);
color: white;
border-radius: 8px;
padding: 0.5rem 1rem;
}
Sectional Sidebars (In-Page Navigation)
For mid-level navigation within 7-12 page resource sections, a top-anchored "In This Section" dropdown replaces the desktop sidebar on mobile.
<nav class="section-nav" aria-label="Section navigation">
<details class="section-nav__dropdown">
<summary class="section-nav__trigger">
In This Section: Facility Monitoring
<span class="section-nav__chevron">▼</span>
</summary>
<ul class="section-nav__links">
<li><a href="./overview/">Overview</a></li>
<li><a href="./data-sources/" aria-current="page">Data Sources</a></li>
<li><a href="./monitoring-tools/">Monitoring Tools</a></li>
</ul>
</details>
</nav>
.section-nav {
position: sticky;
top: 0;
background: var(--color-surface);
z-index: 100;
border-bottom: 1px solid var(--color-border);
}
.section-nav__trigger {
display: flex;
justify-content: space-between;
width: 100%;
padding: 1rem;
font-weight: 600;
}
.section-nav__dropdown[open] .section-nav__chevron {
transform: rotate(180deg);
}
Mobile Usage in Immigrant Communities
Smartphone reliance within immigrant communities is exceptionally high. Research shows up to 98% of specific demographics utilize mobile devices for internet access, often as their sole digital conduit.
Smartphones have transitioned from auxiliary communication devices to the primary mechanism for navigating legal systems, submitting applications, and storing crucial documentation.
Design Constraints
Technical Realities
| Constraint | Impact |
|---|---|
| Prepaid data plans | Limited monthly data allocation |
| Older Android devices | Slower processors, less RAM |
| 3G connectivity | Rural border areas, detention peripheries |
| Intermittent connection | Spotty coverage during travel |
Design Implications
Mobile-first design must encompass:
- Strict data conservation
- Performance budgeting
- Offline resilience
- One-handed operation
Thumb-Zone Navigation
During an active encounter with law enforcement, users likely have only one hand free. Interface design must respect the "Thumb Zone."
Zone Mapping
| Zone | Location | Content Type |
|---|---|---|
| Green (Easy) | Lower center | Primary actions, emergency buttons |
| Yellow (Stretch) | Sides, upper center | Secondary navigation |
| Red (Hard) | Top corners | Destructive actions, settings |
Implementation
/* Position critical actions in thumb zone */
.emergency-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 1rem;
display: flex;
gap: 1rem;
}
.action-button--primary {
min-height: 56px; /* Larger than standard */
min-width: 56px;
padding: 1rem 1.5rem;
font-size: 1.125rem;
}
Touch Target Sizes
| Standard | Minimum Size | Advocacy Recommendation |
|---|---|---|
| Apple HIG | 44px | 56px for emergency actions |
| Google Material | 48dp | 56dp for crisis interfaces |
| WCAG | 44×44px | 56×56px under stress |
/* Emergency button sizing */
.button--emergency {
min-width: 56px;
min-height: 56px;
padding: 1rem;
/* Prevent accidental double-tap */
touch-action: manipulation;
}
/* Spacing to prevent mis-taps */
.button-group {
gap: 12px; /* Minimum spacing between targets */
}
Progressive Web App (PWA)
Service Worker Strategy
Critical "Know Your Rights" materials must remain accessible during total connectivity loss.
// sw.js - Service Worker
const CACHE_NAME = 'advocacy-v1';
const CRITICAL_URLS = [
'/',
'/emergency/',
'/know-your-rights/',
'/printables/red-card/',
'/css/main.css',
'/js/app.js'
];
// Install: cache critical resources
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(CRITICAL_URLS))
);
});
// Fetch: serve from cache, update in background
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(response => {
// Return cache, fetch update in background
const fetchPromise = fetch(event.request)
.then(networkResponse => {
caches.open(CACHE_NAME)
.then(cache => cache.put(event.request, networkResponse.clone()));
return networkResponse;
});
return response || fetchPromise;
})
);
});
Caching Strategies by Content Type
| Content Type | Strategy | Rationale |
|---|---|---|
| App Shell | Cache-first | Load instantly regardless of connection |
| KYR Text | Stale-while-revalidate | Immediate offline, silent updates |
| Form Submissions | Background Sync | Queue locally, transmit when online |
| Real-time Data | Network-first | Fresh data paramount, cache fallback |
Manifest Configuration
{
"name": "Immigration Rights Guide",
"short_name": "Rights Guide",
"start_url": "/",
"display": "standalone",
"background_color": "#1a1a2e",
"theme_color": "#4361ee",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
Offline Indicators
Clear offline indicators reassure users that cached content remains accurate:
<div class="offline-banner" role="alert" hidden>
<span class="offline-icon" aria-hidden="true"></span>
<p>You're offline. This page is saved and accurate.</p>
</div>
// Show/hide offline indicator
window.addEventListener('online', () => {
document.querySelector('.offline-banner').hidden = true;
});
window.addEventListener('offline', () => {
document.querySelector('.offline-banner').hidden = false;
});
Graceful Degradation
// Check connectivity before critical actions
async function submitReport(data) {
if (!navigator.onLine) {
// Queue for later
await queueForSync(data);
showNotification('Report saved. Will submit when online.');
return;
}
// Normal submission
await fetch('/api/report', {
method: 'POST',
body: JSON.stringify(data)
});
}
Data Conservation
Image Optimization
<!-- Responsive images with modern formats -->
<picture>
<source srcset="/images/hero.avif" type="image/avif">
<source srcset="/images/hero.webp" type="image/webp">
<img src="/images/hero.jpg"
alt="Community support"
loading="lazy"
decoding="async"
width="800"
height="450">
</picture>
Lazy Loading Strategy
<!-- Critical images: eager load for LCP -->
<img src="/images/hero.webp" loading="eager">
<!-- Below fold: lazy load -->
<img src="/images/content.webp" loading="lazy">
Font Optimization
/* System font stack for zero font download */
.body-text {
font-family: -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Oxygen, Ubuntu,
sans-serif;
}
/* Subset fonts for specific languages */
@font-face {
font-family: 'Noto Sans';
src: url('/fonts/noto-latin.woff2') format('woff2');
unicode-range: U+0000-00FF; /* Latin only */
font-display: swap;
}
Core Web Vitals Targets
Performance Budgets
| Metric | Target | Measurement |
|---|---|---|
| LCP | < 2.5s | 75th percentile mobile |
| FID/INP | < 100ms | Responsive to panic inputs |
| CLS | < 0.1 | No accidental mis-taps |
JavaScript Budget
| Resource | Budget |
|---|---|
| Total JS | < 100KB compressed |
| Critical JS | < 20KB inline |
| Deferred JS | Lazy load on interaction |
CSS Budget
| Resource | Budget |
|---|---|
| Critical CSS | < 14KB inline |
| Full CSS | < 50KB |
| Above-fold | Inline in <head> |
3G Network Optimization
Preload Critical Resources
<head>
<!-- Preload critical fonts -->
<link rel="preload" href="/fonts/noto-latin.woff2"
as="font" type="font/woff2" crossorigin>
<!-- Preload critical CSS -->
<link rel="preload" href="/css/critical.css" as="style">
<!-- DNS prefetch for external resources -->
<link rel="dns-prefetch" href="//tile.openstreetmap.org">
</head>
Connection-Aware Loading
// Adapt to connection quality
const connection = navigator.connection || {};
const effectiveType = connection.effectiveType || '4g';
if (effectiveType === '2g' || effectiveType === 'slow-2g') {
// Disable non-critical images
document.querySelectorAll('img[data-optional]')
.forEach(img => img.remove());
// Use text-only map alternative
document.querySelector('.map-container').hidden = true;
document.querySelector('.map-text-alternative').hidden = false;
}
Mobile Navigation Patterns
Bottom Navigation
<nav class="bottom-nav" aria-label="Main navigation">
<a href="/emergency/" class="bottom-nav__item">
<span class="bottom-nav__icon" aria-hidden="true"></span>
<span class="bottom-nav__label">Emergency</span>
</a>
<a href="/know-your-rights/" class="bottom-nav__item">
<span class="bottom-nav__icon" aria-hidden="true"></span>
<span class="bottom-nav__label">Rights</span>
</a>
<a href="/find-help/" class="bottom-nav__item">
<span class="bottom-nav__icon" aria-hidden="true"></span>
<span class="bottom-nav__label">Find Help</span>
</a>
</nav>
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-around;
background: var(--color-surface);
padding: 0.5rem 0 env(safe-area-inset-bottom);
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
}
.bottom-nav__item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.75rem;
min-width: 64px;
min-height: 56px;
}
Swipe Gesture Caution
Swipe gestures are learned behaviors that degrade under panic. Never require swiping for critical actions:
// Supplement swipe with visible buttons
carousel.addEventListener('swipe', handleSwipe);
// Always show navigation buttons
<button class="carousel-prev">Previous</button>
<button class="carousel-next">Next</button>
Testing Checklist
Device Testing
- [ ] Tested on 3-year-old Android device
- [ ] Tested on throttled 3G connection
- [ ] Tested with airplane mode (offline)
- [ ] Tested one-handed operation
- [ ] Tested with large text accessibility setting
Performance Testing
- [ ] Lighthouse mobile score > 90
- [ ] LCP < 2.5s on 3G
- [ ] Total page weight < 500KB
- [ ] PWA installable
- [ ] Offline mode functional
Related Resources
- Performance Guide - Core Web Vitals details
- Accessibility - Motor accessibility
- Component Library - Mobile components
- Technical SEO - Mobile optimization