To make Load More accessible it needs the following:
Update Live Region:
After loading new content, it’s important to update a live region (using aria-live=“polite”) to inform users of the updated content, especially for screen reader users.
Manual Focus:
When new content loads, focus should be moved to the first interactive element in the new set of items, making it easier for users to navigate.
Since Bricks doesn’t support this at the moment had anyone created some JS for this that they are willing to share?
Here is some JS code to fix the issues that ChatGPT and I came up with.
document.addEventListener('DOMContentLoaded', function () {
const loadMoreBtn = document.querySelector('#load-more-btn'); // Update to match your button
const list = document.querySelector('ul.fr-article-grid-india'); // Update to match your <ul> class or selector
const debug = false; // Set to false to disable logging
const log = (...args) => debug && console.log(...args);
const warn = (...args) => debug && console.warn(...args);
if (!loadMoreBtn || !list) {
warn('Load More button or list not found');
return;
}
list.setAttribute('aria-live', 'polite');
list.setAttribute('aria-busy', 'false');
let lastItemCount = list.querySelectorAll(':scope > li').length;
lastItemCount = lastItemCount - 1; // Picks up an extra item for some reason...
log(`Initial list item count: ${lastItemCount}`);
const observer = new MutationObserver(() => {
const allItems = Array.from(list.querySelectorAll(':scope > li'));
const currentItemCount = allItems.length;
log(`Updated item count: ${currentItemCount}, Previous count: ${lastItemCount}`);
if (currentItemCount > lastItemCount) {
const newItems = allItems.slice(lastItemCount);
log('New items detected:', newItems);
const firstNewItem = newItems[0];
if (!firstNewItem) {
warn('No new list item found');
return;
}
const interactive = firstNewItem.querySelector(
'a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
);
// Element may not be Focusable at Time of .focus() so delay a bit
setTimeout(() => {
requestAnimationFrame(() => {
if (interactive) {
interactive.focus();
log('Interactive element found:', interactive);
log('Focus moved to interactive element:', interactive);
} else {
log('No interactive element found. Focusing <li> directly.');
firstNewItem.setAttribute('tabindex', '-1');
firstNewItem.focus();
}
log('Current active element:', document.activeElement);
});
}, 100);
lastItemCount = currentItemCount;
list.setAttribute('aria-busy', 'false');
}
});
observer.observe(list, { childList: true });
loadMoreBtn.addEventListener('click', () => {
log('Load More button clicked');
list.setAttribute('aria-busy', 'true');
});
});
2 Issues… which the script has fixes. For some reason the initial count is always off by 1 not sure why (as I had it display the items and it was the correct number) but I just added a -1 to it.
Also the focus event would fire before the new content had finished rendering which resulted in the focus remaining on the load more button. Added a delay to fix that.
I also notice that when keyboard navigating the CSS styling for what has the new focus would display properly (ie on the next loaded card in the list) but if using mouse the item would have focus but the styling would not show.
BTW I left the debug code in it which can be turned on by updated the debug variable flag.
Thanks for the detailed report and the JS snippet.
That said, I don’t think this is a bug. The MDN docs on ARIA live regions suggest using live regions for dynamic updates that are important for the user to receive. In this case, loading more blog posts doesn’t qualify as critical content imo. Users can simply continue navigating the list, so there’s no requirement to announce the change via a live region.
Adding something like aria-live="polite" to announce “3 more posts loaded” is a nice enhancement and we’re not against it, but it’s not required for accessibility compliance.
As for focus, there doesn’t seem to be a clear consensus on what should happen in general. If you’ve got a strong reference from W3C or similar, feel free to share it.
From my research there isn’t a WCAG Success Criterion that explicitly mandates moving focus to the first new item. A A11y expert I follow does recommend it though.
What I did find is recommendations to meet accessibility principles for dynamic content updates, particularly under Success Criterion 2.4.3 (Focus Order) and Success Criterion 4.1.2 (Name, Role, Value), as well as ARIA best practices for managing focus in dynamic interfaces.
Here are the relevant W3C resources and explanations (which Grok helped in summarizing):
Relevance: This criterion requires that focusable components receive focus in an order that preserves meaning and operability. When new content is loaded (e.g., via a “Load More” button), moving focus to the first new item ensures that keyboard and screen reader users can immediately interact with the newly added content, maintaining a logical navigation flow. The W3C notes that dynamic updates should not disrupt the user’s ability to follow the content structure.
W3C ARIA Authoring Practices - Managing Focus in Composites and Dynamic Content
Relevance: The ARIA Authoring Practices Guide explicitly recommends managing focus when new content is added dynamically. Section 3.14, “Managing Focus in Composites,” suggests that after a dynamic update (like loading more content), focus should be moved to a logical location, such as the first item in the newly loaded content, to ensure screen reader and keyboard users can continue navigating effectively. This is particularly relevant for “Load More” buttons, as it helps users perceive and interact with the new content without needing to manually navigate to it.