{"id":124703,"date":"2026-07-23T09:30:50","date_gmt":"2026-07-23T09:30:50","guid":{"rendered":"https:\/\/make.wordpress.org\/core\/?p=124703"},"modified":"2026-08-13T16:35:19","modified_gmt":"2026-08-13T16:35:19","slug":"media-library-infinite-scrolling-is-now-enabled-by-default-with-a-per-user-opt-out","status":"publish","type":"post","link":"https:\/\/make.wordpress.org\/core\/2026\/07\/23\/media-library-infinite-scrolling-is-now-enabled-by-default-with-a-per-user-opt-out\/","title":{"rendered":"Media Library infinite scrolling is now enabled by default, with a per-user opt-out"},"content":{"rendered":"<h2 id=\"background\" class=\"wp-block-heading\"><strong>Background<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The grid view of the Media Library (including the Media Modal) has supported infinite scrolling for a long time, where attachments load automatically as you scroll instead of behind a <strong>Load more<\/strong> button. That behavior was controlled by the <a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/media_library_infinite_scrolling\/\"><code>media_library_infinite_scrolling<\/code><\/a> <span tabindex='0' class='glossary-item-container'>filter<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Filter<\/span> <span class='glossary-item-description'>Filters are one of the two types of Hooks <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Hooks\">https:\/\/codex.wordpress.org\/Plugin_API\/Hooks<\/a>. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.<\/span><\/span><\/span>, which <strong>defaulted to<\/strong> <code>false<\/code> since <a href=\"https:\/\/make.wordpress.org\/core\/2021\/07\/03\/wordpress-5-8-field-guide\/\">WordPress 5.8<\/a> due to <span tabindex='0' class='glossary-item-container'>accessibility<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Accessibility<\/span> <span class='glossary-item-description'>Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both \u201cdirect access\u201d (i.e. unassisted) and \u201cindirect access\u201d meaning compatibility with a person\u2019s assistive technology (for example, computer screen readers). (https:\/\/en.wikipedia.org\/wiki\/Accessibility)<\/span><\/span><\/span>, performance, and usability concerns (<a href=\"https:\/\/core.trac.wordpress.org\/ticket\/50105\">#50105<\/a>\u00a0\/\u00a0<a href=\"https:\/\/core.trac.wordpress.org\/changeset\/50829\">r50829<\/a>\u00a0\/\u00a0<a href=\"https:\/\/core.trac.wordpress.org\/ticket\/40330\">#40330<\/a>). As a result, infinite scrolling was effectively off for everyone unless a <span tabindex='0' class='glossary-item-container'>plugin<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Plugin<\/span> <span class='glossary-item-description'>A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory <a href=\"https:\/\/wordpress.org\/plugins\/\">https:\/\/wordpress.org\/plugins\/<\/a> or can be cost-based plugin from a third-party.<\/span><\/span><\/span> or theme opted in via the filter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Load more<\/strong> button has long been a friction point for users managing large media libraries, and the smoother infinite-scroll experience was hidden behind code that most sites never enabled.<\/p>\n\n\n\n<h2 id=\"what-changed\" class=\"wp-block-heading\"><strong>What changed<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In WordPress 7.1 (<a href=\"https:\/\/core.trac.wordpress.org\/ticket\/65564\">#65564<\/a>):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Infinite scrolling is now enabled by default.<\/strong> The <code>media_library_infinite_scrolling<\/code> filter now defaults to <code>true<\/code>, so the grid view auto-loads attachments on scroll out of the box. This applies to both the Grid view of the Media Library, and the Media Modal.<\/li>\n\n\n\n<li><strong>Users can opt out individually.<\/strong> A new <strong>Infinite Scrolling<\/strong> personal option appears on the profile screen (<strong>Users &gt; Profile<\/strong>), with a checkbox labeled <em>\u201cDisable infinite scrolling in the Media Library grid view\u201d<\/em> (unchecked by default). The option is only shown to users who have the <code>upload_files<\/code> <span tabindex='0' class='glossary-item-container'>capability<span class='glossary-item-hidden-content'><span class='glossary-item-header'>capability<\/span> <span class='glossary-item-description'>A\u00a0<strong>capability<\/strong>\u00a0is permission to perform one or more types of task. Checking if a user has a capability is performed by the <code>current_user_can<\/code> function. Each user of a WordPress site might have some permissions but not others, depending on their\u00a0role. For example, users who have the Author role usually have permission to edit their own posts (the \u201cedit_posts\u201d capability), but not permission to edit other users\u2019 posts (the \u201cedit_others_posts\u201d capability).<\/span><\/span><\/span>, since the attachment grid is unreachable without it.<\/li>\n<\/ol>\n\n\n\n<h2 id=\"precedence\" class=\"wp-block-heading\"><strong>Precedence<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The effective setting is resolved in this order, from highest priority to lowest:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>The<\/strong> <code>media_library_infinite_scrolling<\/code> <strong>filter<\/strong>: a hooked filter callback always wins.<\/li>\n\n\n\n<li><strong>The user\u2019s opt-out preference<\/strong>: applies when no filter is hooked.<\/li>\n\n\n\n<li><strong>The default (<\/strong><code>true<\/code><strong>)<\/strong>: applies when neither of the above is set.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In other words: <strong>filter &gt; user preference &gt; default<\/strong>.<\/p>\n\n\n\n<h2 id=\"developer-facing-details\" class=\"wp-block-heading\"><strong>Developer-facing details<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The filter\u2019s default changed<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If your plugin or theme relies on the previous behavior (infinite scrolling off unless explicitly enabled), be aware that the default is now <code>true<\/code>. To force the previous behavior for all users regardless of their preference, you can use the filter, as it takes precedence over everything:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n\/\/ Force infinite scrolling OFF for all users (restores to the behavior that was default between 5.8 and 7.1).\n\nadd_filter( 'media_library_infinite_scrolling', '__return_false' );\n\n\/\/ Force infinite scrolling ON for all users, ignoring per-user opt-out.\n\nadd_filter( 'media_library_infinite_scrolling', '__return_true' );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Because the filter runs <em>after<\/em> the per-user preference is read, adding a callback overrides any individual user\u2019s choice.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The new user option<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The preference is stored as a user option under the <span tabindex='0' class='glossary-item-container'>meta<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Meta<\/span> <span class='glossary-item-description'>Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress.<\/span><\/span><\/span> key <code>infinite_scrolling<\/code>, as the string <code>'true'<\/code> or <code>'false'<\/code>, consistent with how existing options such as <code>syntax_highlighting<\/code> and <code>rich_editing<\/code> are persisted. It is also wired consistently through the profile form (<code>user-edit.php<\/code>), the save handler (<code>edit_user()<\/code>), and persistence in <code>wp_insert_user()<\/code> and <code>_get_additional_user_keys()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can read a user\u2019s preference programmatically:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n\/\/ The user setting is 'false' if the user has disabled infinite scrolling, 'true' (or empty) otherwise.\n\n$infinite_scrolling_disabled = 'false' === get_user_option( 'infinite_scrolling', $user_id );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note the direction of the stored value: <code>'false'<\/code> means the user has <strong>disabled<\/strong> infinite scrolling. <code>wp_enqueue_media()<\/code> reads this option to determine the pre-filter default.<\/p>\n\n\n\n<h2 id=\"backwards-compatibility\" class=\"wp-block-heading\"><strong>Backwards compatibility<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>media_library_infinite_scrolling<\/code> filter is unchanged in signature; only its default value changed (from <code>false<\/code> to <code>true<\/code>). Existing callbacks continue to work exactly as before and still take precedence.<\/li>\n\n\n\n<li>Sites that had already opted in via <code>__return_true<\/code> see no change.<\/li>\n\n\n\n<li>Sites that never touched the filter now get infinite scrolling by default; users who prefer the <strong>Load more<\/strong> button can opt out from their profile.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p class=\"wp-block-paragraph\"><em>Props to <a href=\"https:\/\/profiles.wordpress.org\/youknowriad\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>youknowriad<\/a>, <a href=\"https:\/\/profiles.wordpress.org\/khokansardar\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>khokansardar<\/a>, <\/em><a href=\"https:\/\/profiles.wordpress.org\/wildworks\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>wildworks<\/a>, <a href=\"https:\/\/profiles.wordpress.org\/davidbaumwald\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>davidbaumwald<\/a>, <a href=\"https:\/\/profiles.wordpress.org\/joedolson\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>joedolson<\/a>, <a href=\"https:\/\/profiles.wordpress.org\/sabernhardt\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>sabernhardt<\/a><em> for reviewing.<\/em><\/p>\n<p class=\"o2-appended-tags\"><a href=\"https:\/\/make.wordpress.org\/core\/tag\/7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>7-1<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes-7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes-7-1<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/media\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>media<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/media-library\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>media-library<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/media-grid\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>media-grid<\/a><\/p><nav class='o2-post-footer-actions'><ul class='o2-post-footer-action-row'><li class='o2-post-footer-action'><a href=\"https:\/\/login.wordpress.org\/?redirect_to=https%3A%2F%2Fmake.wordpress.org%2Fcore%2F2026%2F07%2F23%2Fmedia-library-infinite-scrolling-is-now-enabled-by-default-with-a-per-user-opt-out%2F%23respond&#038;locale=en_US\" title=\"Login to Reply\"  class=\"genericon  genericon-reply\"  data-action=\"login-to-reply\"  data-actionstate=\"default\" >Login to Reply<\/a><\/li><\/ul><div class='o2-post-footer-action-likes'><\/div><ul class='o2-post-footer-action-row'><\/ul><\/nav>","protected":false},"excerpt":{"rendered":"<p>Background The grid view of the Media Library (including the Media Modal) has supported infinite scrolling for a long time, where attachments load automatically as you scroll instead of behind a Load more button. That behavior was controlled by the media_library_infinite_scrolling filterFilter Filters are one of the two types of Hooks https:\/\/codex.wordpress.org\/Plugin_API\/Hooks. They provide a [&hellip;]<\/p>\n","protected":false},"author":8504741,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[4424],"tags":[5885,1443,5894,1397,776,777],"class_list":["post-124703","post","type-post","status-publish","format-standard","hentry","category-core","tag-7-1","tag-dev-notes","tag-dev-notes-7-1","tag-media","tag-media-library","tag-media-grid","mentions-davidbaumwald","mentions-joedolson","mentions-khokansardar","mentions-sabernhardt","mentions-swissspidy","mentions-wildworks","mentions-youknowriad","author-tyxla"],"revision_note":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2AvED-wrl","jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/124703","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/users\/8504741"}],"replies":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/comments?post=124703"}],"version-history":[{"count":16,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/124703\/revisions"}],"predecessor-version":[{"id":125497,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/124703\/revisions\/125497"}],"wp:attachment":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/media?parent=124703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/categories?post=124703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/tags?post=124703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}