# UX Patterns for Devs: UX Patterns Glossary URL: /glossary Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/glossary/index.mdx A comprehensive glossary of UX patterns, design principles, and web development terminology. *** title: UX Patterns Glossary description: A comprehensive glossary of UX patterns, design principles, and web development terminology. --------------------------------------------------------------------------------------------------------- import { TermsListContainer } from "@/components/glossary/terms-list-container"; Welcome to our comprehensive glossary of UX patterns and web development terminology. This resource is designed to help developers and designers understand the key concepts, patterns, and principles discussed throughout our documentation. ## Browse by Letter # UX Patterns for Devs: Text vs Number vs Email Input: When to Use Each HTML5 Type (2025) URL: /pattern-guide/choosing-input-types Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/pattern-guide/choosing-input-types.mdx Select the most appropriate HTML input type based on your data collection needs and user experience requirements *** title: "Text vs Number vs Email Input: When to Use Each HTML5 Type (2025)" description: "Select the most appropriate HTML input type based on your data collection needs and user experience requirements" icon: TextCursorInput status: complete ---------------- import { LazyDecisionFlow } from "@/components/decision-flow/lazy-decision-flow"; import { edges as inputTypeEdges, nodes as inputTypeNodes, } from "@/components/decision-flow/data/input-types"; import { ComparisonGrid } from "@/components/pattern-comparison/comparison-grid"; import { ComparisonHero } from "@/components/pattern-comparison/comparison-hero"; import { DecisionFlowSection } from "@/components/pattern-comparison/decision-flow-section"; import { ExamplesGrid } from "@/components/pattern-comparison/examples-grid"; import { ImplementationMetrics } from "@/components/pattern-comparison/implementation-metrics";
Selecting the right input type is crucial for creating efficient and user-friendly forms. Each input type serves specific purposes and comes with built-in features and validations. The choice impacts user experience, data accuracy, and form completion rates. Use our interactive decision flow below to guide your choice based on factors like data type, validation requirements, and user interaction patterns. Follow the path that best matches your needs to find the recommended input type for your form.
export const comparisonData = { patterns: [ { title: "Text Input", subtitle: "Best for single-line text entry and basic data collection", href: "/patterns/forms/text-field", icon: "Input", theme: "pattern", criteria: [ "Single-line text entry", "Basic user input", "Short responses", "Simple data collection", "Form fields like name, email", ], }, { title: "Textarea", subtitle: "Ideal for multi-line content and rich text editing", href: "/patterns/forms/textarea", icon: "TextSelect", theme: "pattern", criteria: [ "Multi-line text entry", "Long-form content", "Rich text editing", "Comments and descriptions", "Detailed responses", ], }, { title: "Select", subtitle: "Perfect for choosing from predefined options", href: "/patterns/forms/selection-input", icon: "ListBox", theme: "pattern", criteria: [ "Predefined options", "Space-efficient interface", "Large option sets", "Structured data input", "Hierarchical selection", ], }, { title: "Radio", subtitle: "Best for mutually exclusive choices", href: "/patterns/forms/radio", icon: "CircleOff", theme: "pattern", criteria: [ "Single choice from few options", "Mutually exclusive selections", "Visual comparison needed", "Immediate option visibility", "Simple decision making", ], }, { title: "Checkbox", subtitle: "Ideal for multiple selections and toggles", href: "/patterns/forms/checkbox", icon: "CheckSquare", theme: "pattern", criteria: [ "Multiple selections allowed", "Boolean states", "Independent options", "Toggle functionality", "Group selections", ], }, ], }; export const implementationData = { patterns: [ { pattern: "Text Input", accessibility: { label: "Accessibility Support", value: 90, status: "green", description: "Strong native support", }, mobile: { label: "Mobile Usability", value: 95, status: "green", description: "Excellent", }, browser: { label: "Browser Support", value: 100, status: "green", description: "Universal", }, }, { pattern: "Number Input", accessibility: { label: "Accessibility Support", value: 85, status: "green", description: "Good native support", }, mobile: { label: "Mobile Usability", value: 80, status: "yellow", description: "Numeric keyboard", }, browser: { label: "Browser Support", value: 95, status: "green", description: "Well supported", }, }, { pattern: "Date Input", accessibility: { label: "Accessibility Support", value: 75, status: "yellow", description: "Varies by browser", }, mobile: { label: "Mobile Usability", value: 85, status: "green", description: "Native pickers", }, browser: { label: "Browser Support", value: 80, status: "yellow", description: "Inconsistent UI", }, }, { pattern: "File Input", accessibility: { label: "Accessibility Support", value: 80, status: "green", description: "Basic support", }, mobile: { label: "Mobile Usability", value: 75, status: "yellow", description: "Device dependent", }, browser: { label: "Browser Support", value: 90, status: "green", description: "Well supported", }, }, { pattern: "Password Input", accessibility: { label: "Accessibility Support", value: 85, status: "green", description: "Good support", }, mobile: { label: "Mobile Usability", value: 90, status: "green", description: "Password keyboard", }, browser: { label: "Browser Support", value: 100, status: "green", description: "Universal", }, }, { pattern: "Color Input", accessibility: { label: "Accessibility Support", value: 70, status: "yellow", description: "Limited support", }, mobile: { label: "Mobile Usability", value: 75, status: "yellow", description: "Varies by device", }, browser: { label: "Browser Support", value: 85, status: "yellow", description: "Modern browsers", }, }, { pattern: "Range Input", accessibility: { label: "Accessibility Support", value: 75, status: "yellow", description: "Needs ARIA enhancement", }, mobile: { label: "Mobile Usability", value: 80, status: "yellow", description: "Touch friendly", }, browser: { label: "Browser Support", value: 90, status: "green", description: "Well supported", }, }, ], }; export const examplesData = { examples: [ { pattern: "Text Input", examples: [ { title: "Search Fields", description: "Free-form text search", imageUrl: "/examples/search-text-input.webp", }, { title: "Email Input", description: "Email address entry", imageUrl: "/examples/email-input.webp", }, { title: "Username Field", description: "Account creation", imageUrl: "/examples/username-input.webp", }, { title: "Phone Number", description: "Contact information", imageUrl: "/examples/phone-input.webp", }, ], }, { pattern: "Textarea", examples: [ { title: "Comment Box", description: "User feedback entry", imageUrl: "/examples/comment-textarea.webp", }, { title: "Bio Editor", description: "Profile description", imageUrl: "/examples/bio-textarea.webp", }, { title: "Message Composer", description: "Email composition", imageUrl: "/examples/message-textarea.webp", }, { title: "Review Writing", description: "Product reviews", imageUrl: "/examples/review-textarea.webp", }, ], }, { pattern: "Select", examples: [ { title: "Country Selection", description: "Location picker", imageUrl: "/examples/country-select.webp", }, { title: "Language Chooser", description: "Website localization", imageUrl: "/examples/language-select.webp", }, { title: "Category Filter", description: "Product filtering", imageUrl: "/examples/category-select.webp", }, { title: "Time Zone", description: "Regional settings", imageUrl: "/examples/timezone-select.webp", }, ], }, { pattern: "Radio", examples: [ { title: "Payment Methods", description: "Checkout options", imageUrl: "/examples/payment-radio.webp", }, { title: "Shipping Options", description: "Delivery selection", imageUrl: "/examples/shipping-radio.webp", }, { title: "Size Selection", description: "Product variants", imageUrl: "/examples/size-radio.webp", }, { title: "Rating System", description: "Feedback collection", imageUrl: "/examples/rating-radio.webp", }, ], }, { pattern: "Checkbox", examples: [ { title: "Filter Options", description: "Multi-select filters", imageUrl: "/examples/filter-checkboxes.webp", }, { title: "Terms Agreement", description: "Legal consent", imageUrl: "/examples/terms-checkbox.webp", }, { title: "Feature Toggle", description: "Settings panel", imageUrl: "/examples/features-checkbox.webp", }, { title: "Task List", description: "Todo application", imageUrl: "/examples/tasks-checkbox.webp", }, ], }, ], }; ## Next steps Ready to implement your chosen pattern? Check out our detailed implementation guides: How to implement and style text inputs Building accessible select components Best practices for option selection # UX Patterns for Devs: Choose the Right Pattern URL: /pattern-guide Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/pattern-guide/index.mdx undefined *** title: "Choose the Right Pattern" index: true ----------- Compare similar patterns and make informed decisions based on your specific use case and requirements. ## Pattern Guides # UX Patterns for Devs: Dropdown vs Radio vs Checkbox: Choosing the Right Form Input (2025) URL: /pattern-guide/input-selection-guide Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/pattern-guide/input-selection-guide.mdx Learn how to select the most appropriate input types for your web forms. Get guidance on when to use text fields, dropdowns, checkboxes, and other form controls. *** title: "Dropdown vs Radio vs Checkbox: Choosing the Right Form Input (2025)" summary: "Choose the right input type for your form" description: "Learn how to select the most appropriate input types for your web forms. Get guidance on when to use text fields, dropdowns, checkboxes, and other form controls." icon: Text ---------- ## When to use Different Types of Text Fields? ```mermaid graph TD A[Do users need to enter freeform text?] -->|Yes| B[Does it require a single line?] B -->|Yes| C[Use Standard Text Field ``] B -->|No| D[Use Textarea ` ``` ## Implementation Requirements ### Making Elements Keyboard Accessible #### Native Interactive Elements Already keyboard accessible by default: * `` * ` ``` ### With Helper Text Text field with additional guidance below the input. ```html
Must be 3-20 characters, letters and numbers only
``` ### Search Text Field Optimized for search with specific styling and behavior. ```html ``` ## Examples ### Interactive Demo ### With Validation States ### With Helper Text ### With Character Counter ### With Icons ### Different Input Types ### Required Field Indicators ### Basic Implementation ```html
Please enter a username
``` ## Best Practices ### Content & Usability **Do's ✅** * Provide a **clear and descriptive label**. * Use **placeholder text sparingly** and never as a replacement for a label. * Indicate **required fields** clearly and provide helpful validation feedback. * Use **real-time validation** to prevent errors early. * Ensure sufficient **touch target size** for mobile users. * Allow users to **copy, paste, and autocomplete** when appropriate. * **Use input masks sparingly**—they can improve formatting but may frustrate users if too rigid. * Offer **formatting hints** when users must follow a specific pattern (e.g., phone numbers, dates). * Provide **default values** when applicable to reduce typing effort. **Don'ts ❌** * Don't use placeholder text instead of a visible label. * Avoid long character limits without a counter. * Don't require unnecessary or sensitive information without justification. * Don't enforce **case sensitivity** unless absolutely necessary. * Avoid disabling **copy-paste** for passwords or sensitive fields, as this can harm usability. *** ### Required Field Implementation Guidelines #### 1️⃣ Best Practice: Explicit "Required" Label ✅ **Most accessible** – clear for all users, including screen readers. ```html ``` **Pros ✅** * Works for **all users**, including screen readers and color-blind users. * No need for extra ARIA attributes. **Cons ❌** * Takes slightly more space in the UI. #### 2️⃣ Alternative: Asterisk (\*) with ARIA Explanation ✅ **Common practice**, but needs `aria-describedby` for screen reader users. ```html

Fields marked with an asterisk are required.

``` **Pros ✅** * Keeps UI cleaner while maintaining accessibility. * Screen readers will announce **"Fields marked with an asterisk are required."** **Cons ❌** * **Requires additional explanation** (`aria-describedby`). * **Without the extra message, asterisks alone are not accessible**. #### 3️⃣ Alternative: Required Field with Visually Hidden Text ✅ **Keeps UI minimal while ensuring accessibility.** ```html ``` **Pros ✅** * **Looks clean visually** while still accessible. * **Screen readers announce it as "Email Required"**. **Cons ❌** * **Not visible for sighted users** who rely on visual cues. #### 4️⃣ Alternative: Required Field with an Inline Icon + Tooltip ✅ **More user-friendly**, provides additional guidance. ```html

Fields marked with an asterisk are required.

``` **Pros ✅** * **Visually clear** while keeping text minimal. * Works well when paired with a **tooltip on hover or focus**. **Cons ❌** * **Requires CSS for styling** (ensuring asterisks are not the only indicator). * Users **might not see tooltip hints** if they don't hover over the icon. #### 5️⃣ Alternative: Required Field with `required` Attribute Only ⚠ **Not recommended as a standalone solution!** ```html ``` **Pros ✅** * Works well for **basic validation**. * Screen readers **will announce the field as required**. **Cons ❌** * No **visible indicator for sighted users** before form submission. * **Errors only appear after submission**, which may confuse users. * Some browsers may **not enforce required fields consistently**. *** ### Accessibility **Do's ✅** * Associate the text field with a `
{path[path.length - 1]} ); } return path.map(item => ); }; ``` **CSS-Only Separators** ```css /* Avoid DOM elements for separators */ .breadcrumb-item:not(:last-child)::after { content: "›"; margin: 0 0.5rem; } ``` ## Usability Testing Insights Research shows that users: * Understand breadcrumb purpose immediately when properly styled (87% of users) * Use breadcrumbs for upward navigation (52% of users) * Click middle hierarchy levels more than home (68% of clicks) * Have 23% lower engagement on mobile due to space constraints * Prefer ">" separator over other symbols (72% preference) ### Testing Recommendations **A/B Test Variables:** * Separator symbols (>, /, →, |) * Truncation methods (ellipsis, collapsing, scrolling) * Current page inclusion/exclusion * Mobile presentation styles ## Localization ### Text Expansion Considerations Breadcrumb text can expand 30-200% when translated: ```css /* Allow for text expansion */ .breadcrumb { min-width: 0; flex-wrap: wrap; } .breadcrumb-item { min-width: 0; overflow-wrap: break-word; } ``` ### RTL (Right-to-Left) Support ```css /* Automatic RTL flipping */ .breadcrumb { display: flex; flex-direction: row; } /* Flip separator in RTL */ [dir="rtl"] .breadcrumb-item:not(:last-child)::after { content: "‹"; } ``` ### Cultural Considerations * **Home Label:** "Home" doesn't translate literally in all languages * **Separator Symbols:** Avoid culturally specific symbols * **Truncation:** Consider character-based vs word-based truncation * **Reading Direction:** Some cultures read hierarchy differently ## Code Examples ### Basic Implementation This example uses semantic HTML to provide a clear structure for the breadcrumb navigation. ```html ``` ### JSON-LD Structured Data This example demonstrates how to dynamically generate the breadcrumb JSON-LD structured Data using JavaScript. ```javascript const breadcrumbs = [ { title: "Home", url: "https://example.com" }, { title: "Products", url: "https://example.com/products" }, { title: "Current Page" }, ]; function generateBreadcrumbSchema(breadcrumbs) { return { "@context": "https://schema.org", "@type": "BreadcrumbList", itemListElement: breadcrumbs.map((crumb, index) => { const isLastItem = index === breadcrumbs.length - 1; const baseItem = { "@type": "ListItem", position: index + 1, name: crumb.title, }; // Only add the "item" property if it's not the last item and has a URL if (!isLastItem && crumb.url) { baseItem.item = crumb.url; } return baseItem; }), }; } ``` ## SEO ### Structured Data * Implement breadcrumb structured data using [Schema.org markup](https://schema.org/BreadcrumbList) to help search engines understand your site's hierarchy * This improves the way your site appears in search results and helps search engines better understand your content structure Example JSON-LD structured data: ```json { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" }, { "@type": "ListItem", "position": 2, "name": "Products", "item": "https://example.com/products" }, { "@type": "ListItem", "position": 3, "name": "Current Page" } ] } ``` ### Testing & Validation * Use Google's [Rich Results Test](https://search.google.com/test/rich-results) to validate structured data * Monitor breadcrumb appearance in search results through Google Search Console * Check for proper indexing of breadcrumb pages in site architecture * Verify mobile rendering of breadcrumbs for mobile-first indexing ## Testing Guidelines ### Functional Testing **Should ✓** * [ ] Navigate to the correct page when clicking each breadcrumb link * [ ] Show the complete hierarchy path from home to current page * [ ] Update breadcrumb trail when navigating through different levels * [ ] Maintain state after page refresh * [ ] Work with browser back/forward navigation ### Accessibility Testing **Should ✓** * [ ] Be navigable using keyboard (Tab and Enter keys) * [ ] Have proper ARIA labels and roles * [ ] Announce proper hierarchy to screen readers * [ ] Maintain focus state visibility * [ ] Have sufficient color contrast (WCAG 2.2 AA) ### Responsive Testing **Should ✓** * [ ] Adapt layout for different screen sizes * [ ] Show/hide home icon appropriately * [ ] Handle text overflow gracefully * [ ] Maintain touch target sizes on mobile (minimum 44x44px) * [ ] Preserve functionality across different devices ### SEO Testing **Should ✓** * [ ] Include proper Schema.org markup * [ ] Have semantic HTML structure * [ ] Maintain consistent URL structure * [ ] Include relevant meta tags * [ ] Follow proper link hierarchy ### Performance Testing **Should ✓** * [ ] Load without significant delay * [ ] Not cause layout shifts * [ ] Handle large numbers of items efficiently * [ ] Work with dynamic content updates * [ ] Function without JavaScript (progressive enhancement) ## Browser Support ## Design Tokens (DTF) These design tokens follow the [Design Tokens Format](https://design-tokens.github.io/community-group/format/) specification and can be used with various token transformation tools to generate platform-specific variables. ```json { "breadcrumb": { "container": { "paddingY": "{spacing.3}", "paddingX": "{spacing.0}", "fontSize": "{fontSize.sm}", "background": "{colors.transparent}" }, "item": { "color": "{colors.gray.600}", "colorHover": "{colors.gray.900}", "marginRight": "{spacing.2}", "fontSize": "{fontSize.sm}" }, "separator": { "color": "{colors.gray.400}", "marginX": "{spacing.2}" }, "current": { "color": "{colors.gray.900}", "fontWeight": "{fontWeight.medium}" }, "link": { "color": "{colors.gray.600}", "colorHover": "{colors.gray.900}", "textDecoration": "{textDecoration.none}", "transition": "{transition.colors}", "focusOutline": "2px solid {colors.blue.500}" } } } ``` ## Frequently Asked Questions ' or '/'\n" + "3. Ensure all items, except the current page, are clickable links\n" + "4. Be concise and not occupy excessive space\n" + "5. Be placed near the top of the page, below the main navigation", }, { question: "What are the benefits of using breadcrumbs?", answer: "Breadcrumbs enhance user experience by:\n\n" + "1. Providing a clear path back to higher-level pages\n" + "2. Reducing the number of actions needed to navigate to previous pages\n" + "3. Offering context about the site's structure\n" + "4. Potentially improving SEO by providing internal links with relevant anchor text", }, { question: "What are common mistakes to avoid with breadcrumb navigation?", answer: "Avoid these common mistakes:\n\n" + "1. Making the breadcrumb trail too prominent, overshadowing primary navigation\n" + "2. Omitting the current page from the breadcrumb trail\n" + "3. Using inconsistent or unclear separators\n" + "4. Not providing enough space between links, making them hard to click, especially on mobile devices", }, ]} /> ## Related Patterns ## Resources ### Articles * [Breadcrumbs: 11 Design Guidelines for Desktop and Mobile](https://www.nngroup.com/articles/breadcrumbs/) by Nielsen Norman Group * [Designing Effective Breadcrumbs Navigation — Smashing Magazine](https://www.smashingmagazine.com/2022/04/breadcrumbs-ux-design/) * [Breadcrumb Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/) by W3C * [Breadcrumbs](https://a11y-style-guide.com/style-guide/section-navigation.html#kssref-navigation-breadcrumbs) - By A11y Style guide ### Libraries * [Breadcrumb: shadcn/ui](https://ui.shadcn.com/docs/components/breadcrumb) * [Breadcrumb - Origin UI](https://originui.com/breadcrumb) # UX Patterns for Devs: Hamburger Menu URL: /patterns/navigation/hambuger-menu Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/patterns/navigation/hambuger-menu.mdx Create accessible mobile menus with smooth animations and touch-friendly interactions. *** title: "Hamburger Menu" summary: "Display a menu icon for mobile devices" description: "Create accessible mobile menus with smooth animations and touch-friendly interactions." icon: Menu ---------- This page is empty for now. Please help us by [contributing](https://github.com/thedaviddias/ux-patterns-for-developers/blob/main/.github/CONTRIBUTING.md) to add content. # UX Patterns for Devs: Infinite scroll URL: /patterns/navigation/infinite-scroll Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/patterns/navigation/infinite-scroll.mdx Create seamless content loading with infinite scroll, focusing on performance, accessibility, and user experience best practices. *** title: "Infinite scroll" summary: "Loads additional content automatically as users scroll down." description: "Create seamless content loading with infinite scroll, focusing on performance, accessibility, and user experience best practices." icon: Infinity status: complete ---------------- import { GuidesBanner } from "@/components/guides-banner"; ***(Also called Continuous scrolling)*** ## Overview **Infinite Scroll** is a UI pattern that dynamically loads more content as users scroll down a page, eliminating the need for pagination or manual interaction. It provides a seamless browsing experience by continuously appending new items to the current view. This pattern is commonly used in **social media feeds, search results, and content-heavy websites** to keep users engaged without interruptions. ## Use Cases ### When to use: Use Infinite Scroll when you need to dynamically load more content as users scroll without requiring manual pagination. **Common scenarios include:** * **Social media feeds** – e.g., Twitter, Instagram, Facebook, where users consume an endless stream of content. * **News and blog sites** – e.g., showing a continuous stream of articles. * **E-commerce product listings** – e.g., dynamically loading more items as users explore the catalog. * **Search results** – e.g., reducing friction in discovering relevant items. * **Media galleries** – e.g., loading more images/videos as users scroll. ### When not to use: * **When users need to find specific content quickly** – Paginated results may be more efficient. * **For structured navigation** – If users need to compare items or revisit previous results, pagination provides better control. * **If performance is a concern** – Infinite scroll can lead to high memory usage and slow rendering. * **For content requiring user actions** – If users frequently need to interact with elements (e.g., filling forms), infinite scrolling can be disruptive. * **When reaching the footer is important** – Users may struggle to access footer content if new items keep loading. ## Benefits * **Enhances engagement** by providing a seamless browsing experience. * **Eliminates unnecessary page loads** and reduces navigation friction. * **Encourages content exploration** by presenting an uninterrupted flow of items. * **Optimized for touchscreens** where scrolling is more intuitive than clicking pagination buttons. ## Drawbacks * **Navigation challenges** – Users may struggle to return to a previous position. * **Performance issues** – Excessive DOM elements can lead to lag and slow rendering. * **Accessibility concerns** – Keyboard and screen reader users may find it harder to navigate. * **Disrupts footer visibility** – Users may never reach the footer if content loads indefinitely. ## Anatomy ```mermaid flowchart TB subgraph InfiniteScroll[Infinite Scroll Component] A[Content Container] --> B[Trigger Point] B --> C[Loading Indicator] C --> D[Newly Loaded Content] D --> E[Next Trigger Point - Optional] end ``` ### Component Structure 1. **Content Container** * Holds the dynamically loaded items. * Ensures content is structured and visually organized. * Can be a **list, grid, or other layout structure**. 2. **Trigger Point** * The detection mechanism that determines **when to load more content**. * Typically appears when the **user scrolls near the end** of the container. * Can be based on **[viewport](/glossary/viewport) visibility, scroll depth, or other triggers**. 3. **Loading Indicator** * Provides **visual feedback** while content is being retrieved. * Can be a **spinner, progress bar, or skeleton loader**. * Should **only be displayed when new content is actively loading**. 4. **Newly Loaded Content** * The additional items dynamically inserted once new data is fetched. * Should **seamlessly integrate** with previously loaded content. * May **fade in or animate** to indicate new content. 5. **Next Trigger Point (Optional)** * If more content is available, a new **Trigger Point** is added for the next batch. * Helps manage continuous loading in **long content feeds**. #### Summary of Components | Component | Required? | Purpose | | -------------------- | --------- | ------------------------------------------------------------ | | Content Container | ✅ Yes | Holds the items being dynamically loaded. | | Trigger Point | ✅ Yes | Detects when the user reaches the threshold for new content. | | Loading Indicator | ✅ Yes | Shows that content is being fetched. | | Newly Loaded Content | ✅ Yes | Represents the new batch of dynamically inserted content. | | Next Trigger Point | ❌ No | Appears if additional content is available for loading. | ## Best Practices ### Content & Usability **Do's ✅** * **Provide clear loading indicators** to inform users that content is being fetched. * **Use a 'Load More' button as a fallback** in case auto-loading fails. * **Allow users to jump back to the top** with a 'Back to Top' button. * **Save scroll position** so users don't lose their place when navigating back. **Don'ts ❌** * **Avoid infinite loops** – Ensure loading stops when all content is fetched. * **Don't break browser back navigation** – Users should be able to return to previous content states. * **Avoid excessive memory usage** – Remove off-screen items if necessary to optimize performance. ### Accessibility **Do's ✅** * **Ensure content is focusable** – New items should be reachable via keyboard navigation. * **Announce new content dynamically** using ARIA [live regions](/glossary/live-regions) (`aria-live="polite"`). * **Provide an alternative to infinite scrolling** – Offer pagination or a "Load More" option. * **Ensure users can pause or stop loading** – Unexpected content updates can be disorienting. **Don'ts ❌** * **Avoid relying solely on scrolling** – Users with assistive technologies may need alternative navigation. * **Don't change content order unexpectedly** – Screen readers should process content sequentially. ### Visual Design **Do's ✅** * **Use smooth transitions** when loading new items to maintain a natural experience. * **Indicate loading state** – Provide a spinner or skeleton loader while fetching data. * **Ensure visual continuity** – Keep layout stable to prevent sudden jumps. **Don'ts ❌** * **Don't push content down unexpectedly** – New items should append seamlessly without disrupting user flow. * **Avoid excessive whitespace** – Content should remain readable and well-structured. ### Performance Optimization **Do's ✅** * **Implement lazy loading** – Load images and assets only when needed. * **Use virtualization** – Remove off-screen items from the DOM to improve performance. * **Optimize API calls** – Fetch only necessary data to reduce network requests. **Don'ts ❌** * **Avoid fetching too much data at once** – This can slow down rendering and increase memory usage. * **Don't re-render the entire list on new data arrival** – Only update necessary elements. ## SEO Considerations * Ensure **search engines can access all content** by implementing **server-side rendering (SSR)** or an accessible paginated alternative. * Provide a **static link to all content pages** to ensure crawlers can index them. * Ensure that critical content is **available without JavaScript**. ## Testing Guidelines ### Functional Testing **Should ✓** * [ ] Confirm new content loads properly as the user scrolls. * [ ] Ensure scroll position remains stable after navigating back to the page. * [ ] Verify that users can manually load more content if needed. * [ ] Ensure the feature works across different browsers and devices. ### Accessibility Testing **Should ✓** * [ ] Verify that screen readers announce new content properly. * [ ] Ensure that keyboard users can navigate through dynamically loaded items. * [ ] Test with reduced motion settings to ensure animations don't cause issues. ### Performance Testing **Should ✓** * [ ] Measure memory usage to prevent excessive DOM elements. * [ ] Ensure API calls are efficient and minimize network overhead. * [ ] Test scrolling performance on both desktop and mobile devices. ## Related Patterns ## Frequently Asked Questions ## Resources ### Articles ### Documentation ### Libraries # UX Patterns for Devs: Link URL: /patterns/navigation/link Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/patterns/navigation/link.mdx Build accessible links with proper styling, hover states, and keyboard navigation support. *** title: "Link" summary: "Create accessible and interactive links" description: "Build accessible links with proper styling, hover states, and keyboard navigation support." icon: Link ---------- This page is empty for now. Please help us by [contributing](https://github.com/thedaviddias/ux-patterns-for-developers/blob/main/.github/CONTRIBUTING.md) to add content. # UX Patterns for Devs: Load More URL: /patterns/navigation/load-more Source: https://raw.githubusercontent.com/thedaviddias/ux-patterns-for-developers/refs/heads/main/apps/web/content/patterns/navigation/load-more.mdx Build efficient content loading with the Load More pattern, focusing on user experience and performance optimization. *** title: "Load More" summary: "Load additional content on user demand" description: "Build efficient content loading with the Load More pattern, focusing on user experience and performance optimization." icon: Plus status: complete ---------------- import { Playground } from "@/components/playground"; ## Overview **Load More** lets users request additional content dynamically instead of loading everything upfront. This pattern cuts initial page load times and gives users seamless access to more content when they need it. ## Use Cases ### When to use: Use Load More when users should explore content progressively at their own pace without getting overwhelmed. Unlike infinite scrolling, Load More gives users clear control and lets them consciously decide when to view more items. For better usability, make sure the Load More button gets **removed when all content is loaded** or updates to show that no additional items remain (like **"No More Results"**). **Common scenarios include:** * Large lists of content need pagination (news feeds, product listings) * Page performance improves by loading only a subset of data initially * Users browse progressively instead of needing all content at once * You want an alternative to infinite scrolling with more user control ### When not to use: * The full content list is small enough to load upfront without performance issues * Users need to compare multiple items at once ([pagination](/patterns/navigation/pagination) works better here) * Real-time updates or continuous data streaming is required ### Common scenarios and examples * **E-commerce**: Loading additional products in a grid or list * **News or blog feeds**: Expanding more articles dynamically * **Social media feeds**: Loading additional posts without overwhelming users * **Search results**: Fetching more results upon user request ## Benefits * **Speeds up initial page load** by reducing data overhead * **Users control** their content consumption, avoiding cognitive overload * **Better accessibility** than infinite scrolling since users keep track of their position * **Works across devices** with controlled data retrieval * **Footer stays accessible** – users can reach secondary links like policies, shipping info, and contact details * **Stops unnecessary clicks** by **removing the Load More button once everything loads** or showing **"No More Results"** * **Prevents layout jumps** – newly loaded content appears smoothly without shifting user position ## Drawbacks * **User Effort** – Users must take action to reveal more content, not seamless like infinite scroll * **Hidden Content Risk** – Users might miss that more content exists if the button lacks visibility * **Flow Interruption** – Clicking Load More breaks immersion compared to continuous scrolling * **Navigation Issues** – Returning to previously loaded sections gets tricky without proper implementation * **SEO Hurdles** – Search engines might skip dynamically loaded content without proper handling * **Accessibility Work** – Screen readers need careful ARIA implementation to announce new content * **Performance Cost** – Multiple fetch requests impact performance without optimization ## Anatomy ```mermaid flowchart TB subgraph LoadMore[Load More Component] A[Container] --> B[Initial Content List] B --> C[Load More Button] C --> D[Loading Indicator - Optional] C --> E[Additional Content] E --> F[Another Load More Button - Optional] end ``` ### Component Structure 1. **Container** * Wraps the entire load more component * Keeps content properly structured and styled 2. **Initial Content List** * Shows a **limited number of items** to avoid overwhelming users * Sets the default **starting state** before additional content loads 3. **Load More Button** * Primary trigger for **loading additional content** * Must show **clear affordance** that more content exists * Often includes **ARIA attributes** to indicate loading state 4. **Loading Indicator (Optional)** * Shows **visual feedback** while fetching new content * Usually a **spinner, progress bar, or skeleton loader** 5. **Additional Content** * **Newly loaded items** appear after clicking Load More * Must blend **seamlessly** with the initial content list 6. **Another Load More Button (Optional)** * Appears **if more content is available after the first load**. * Helps users **incrementally explore content** without scrolling endlessly. #### Summary of Components | Component | Required? | Purpose | | ------------------------ | --------- | ------------------------------------------------------------ | | Container | ✅ Yes | Wraps the content that will load more items. | | Initial Content List | ✅ Yes | Displays a limited set of items to avoid overwhelming users. | | Load More Button | ✅ Yes | Allows users to manually fetch more content. | | Loading Indicator | ❌ No | Shows progress while loading more items. | | Additional Content | ✅ Yes | The dynamically inserted content after clicking "Load More." | | Another Load More Button | ❌ No | Appears if further content can still be loaded. | ## Variations ### Basic Load More Standard button that loads additional content when clicked. ### Load More with Counter Shows how many items will be loaded (e.g., "Load 10 more items"). ### Load More with Progress Displays overall progress (e.g., "Showing 20 of 100 items"). ### Auto-Load on Scroll Proximity Automatically triggers when user scrolls near the button (hybrid approach). ### Load More with Categories Multiple load more buttons for different content sections. ### Skeleton Loading Shows placeholder content while real content loads. ## Best Practices ### Content **Do's ✅** * Show clearly that more content is available * Pick concise, meaningful labels: **"Load More"**, **"Show More"**, or **"See More Results"** * Keep transitions smooth when new content loads **Don'ts ❌** * Skip vague labels like **"Click Here"** * Never load excessive content at once; keep batches manageable * Avoid disrupting the existing layout when inserting new content ### Accessibility & UX **Do's ✅** * Make the **Load More** button keyboard accessible (`tab` and `enter` keys) * Announce new content to screen readers (`aria-live="polite"`) * Give feedback (loading indicators) to show content retrieval * **Keep keyboard focus logical** – After clicking Load More, focus shifts **to the newly loaded content**, not back to the button * **Alert assistive technologies** – `aria-live="polite"` tells screen reader users that additional items loaded **Don'ts ❌** * Keep focus on the **Load More** button after clicking (skip `disabled`) * Never use infinite scrolling without a **Load More** fallback * Stop relying solely on color for action buttons (check contrast and readable text) ### Visual Design **Do's ✅** * Put the **Load More** button prominently below existing content * Show clear visual feedback when new content loads (animations, progress indicators) * Keep spacing and alignment consistent with existing content **Don'ts ❌** * Never make the button too small for mobile tapping * Prevent sudden layout shifts when loading new content ### Layout & Positioning **Do's ✅** * Put the **Load More** button at logical content breakpoints * Loaded content appears right after existing items * Keep the user's position in the list after loading more **Don'ts ❌** * Never insert new content above the user's current view unless explicitly requested * Skip loading content off-screen without visual confirmation ## Common Mistakes & Anti-Patterns 🚫 ### No Visual Feedback **The Problem:** Users think the button broke if nothing happens immediately after clicking. **How to Fix It?** Add a **spinner or loading animation** and consider disabling the button until new content fully loads. *** ### Loading Too Many Items at Once **The Problem:** Large content batches slow performance, cause layout shifts, and overwhelm users. **How to Fix It?** Load **smaller chunks** (10–20 items per click). Use incremental updates instead of one large data fetch. *** ### Forcing Excessive Load More Clicks **The Problem:** Repeated Load More clicks frustrate users and make pages feel unresponsive. **How to Fix It?** Try **auto-loading on scroll** after a few manual loads, or increase batch size when you detect high engagement. *** ### No End of Content Indicator **The Problem:** Users can't tell when they've reached the end, clicking Load More repeatedly with no result. **How to Fix It?** Show a "You've reached the end" message (announce via aria-live="polite") or hide the button entirely when no more data exists. *** ### Missing Keyboard Accessibility **The Problem:** Load More buttons that aren't focusable or don't respond to keyboard events lock out keyboard users from loading new content. **How to Fix It?** Use a proper, focusable element like `
Showing 10 of 50 items
``` ### Load More with Intersection Observer ```javascript // Auto-load when button is near viewport const loadMoreBtn = document.querySelector('.load-more-btn'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting && !isLoading) { // Trigger load when button is 200px from viewport loadMoreContent(); } }); }, { rootMargin: '200px' }); observer.observe(loadMoreBtn); ``` ## Accessibility ### ARIA Attributes **Required ARIA attributes:** * Use `aria-controls` to associate the **Load More** button with the content being updated. * Announce loading states with `aria-live="polite"`. * If the button is removed after loading all content, update its `aria-label` to indicate that no more content is available. ### Screen Reader Support **Implementation considerations:** * Users should be informed when new content is added. * Ensure proper tab focus order when new items appear. * Use accessible button elements (`
``` ## Best Practices ### Content **Do's ✅** * Pick clear, concise labels for navigation controls * Give context ("Page 5 of 20") * Use ellipsis (...) for large page ranges * Check if pagination or infinite scroll fits your use case and content type better * Display loading indicators when fetching new content * Update URLs to reflect current page numbers **Don'ts ❌** * Skip cluttering the interface with excessive pagination controls * Never paginate short lists that fit on one page * Avoid ambiguous labels that confuse users * Stop loading unnecessary data or assets irrelevant to the current page ### Accessibility **Do's ✅** * Wrap pagination controls with semantic `