If you have been building WordPress sites for a while, you already know the pain of wiring together custom post loops, custom queries, and template logic across a dozen PHP files. The Query Loop block in Full Site Editing changes that equation entirely. It moves your query logic directly into the block editor, lets you build and preview dynamic content layouts visually, and outputs clean, performant markup without a single line of custom PHP.

This guide covers everything you need to build real, production-ready dynamic layouts with the Query Loop block: how it works internally, how to configure it for different content types, how to use nested blocks to control exactly what content appears, and how to extend it with filters and block variations for advanced use cases.


What the Query Loop Block Actually Does

The Query Loop block is a wrapper block that runs a WordPress query and renders its inner blocks once for each post in the results. Think of it as a PHP while (have_posts()) loop translated into a block structure.

The block has two main components:

  1. The Query Loop itself — the outer block that holds the query parameters (post type, number of posts, filters, ordering) and the inner template
  2. The Post Template — the inner block that defines what renders for each post, using post-aware child blocks like Post Title, Post Featured Image, Post Excerpt, Post Date, and Post Author

The result is a fully dynamic content display that updates automatically as you publish, edit, or delete posts. No JavaScript. No manual refreshing. The server renders the correct output on every request.


Setting Up Your First Query Loop Block

Step 1: Add the Block

In the Site Editor or any block-enabled template, insert the Query Loop block from the block inserter. You will be prompted with a setup screen offering three starting points:

  • Choose a pattern — select a pre-built layout from your registered patterns (or core defaults)
  • Start blank — build from an empty Post Template
  • Inherit query from URL — use the current page’s query context (useful for archive templates)

Step 2: Configure the Query

With the outer Query Loop block selected, the block toolbar and inspector panel expose the query parameters:

Parameter What It Controls Default
Post Type Which CPT or built-in type to query Posts
Number of Items How many posts to display per page 3
Offset How many posts to skip from the start 0
Order Newest first, oldest first, alphabetical, etc. Newest first
Sticky Posts Exclude, include, or only show sticky posts Exclude
Filters Filter by category, tag, author, or keyword None
Inherit from template Use the URL query (archive/search context) Off on pages, on in archive templates

Step 3: Build the Post Template

Click into the Post Template block (the inner block area). This is where you define what renders for each post. Add any combination of post-aware blocks: Post Featured Image, Post Title, Post Date, Post Author, Post Excerpt, Post Categories, Post Tags, and Read More.

You can also wrap these blocks in Group blocks, Columns blocks, or Stack blocks to achieve any layout structure. The Post Template block renders all of these child blocks once per post.


Building a Real-World Post Grid

A practical three-column post grid uses the Query Loop block with the Post Template set to grid layout. In the editor, the structure looks like this:

  • Query Loop block (6 posts, newest first)
  • Post Template block (grid layout, 300px minimum column width)
    • Group block
      • Post Featured Image (linked, 16:9 ratio)
      • Post Categories
      • Post Title (h3, linked)
      • Post Excerpt (30 words)
      • Post Date
  • Pagination block

Setting the Post Template block layout to Grid with a minimum column width of 300px creates a responsive grid that automatically adjusts from 1 to 2 to 3 columns based on available viewport width. No media queries needed in your theme CSS.

Grid Layout vs List Layout

Grid layout stacks post template iterations in a CSS grid. List layout stacks posts vertically — useful for traditional blog archives, recent posts sidebars, or any linear content list. You switch between them in the Post Template block’s layout inspector panel.


Query Loop with Custom Post Types

The Query Loop block works with any custom post type registered with show_in_rest: true. This is a critical requirement — the block editor communicates with WordPress through the REST API, so CPTs must be REST-accessible.

When registering a CPT for use with Query Loop, ensure these arguments are set:

  • show_in_rest set to true — enables REST API access and block editor support
  • has_archive set to true or a custom slug — enables archive template routing
  • supports including the fields your Post Template blocks will need: title, editor, thumbnail, excerpt

Once registered, your CPT appears in the Query Loop block Post Type dropdown. For CPT archives, create a block template named archive-{post-type-slug}.html in your theme’s templates directory. Add a Query Loop block with Inherit Query from Template enabled — it will automatically use WordPress’s main archive query.


Filtering and Limiting Query Results

Category and Tag Filters

The Filters section in the Query Loop inspector restricts results to specific categories or tags. This is how you build a Latest Tutorials section showing only posts in the Tutorial category, or a Related Posts section showing posts sharing a tag with the current post.

For context-aware related posts in a single post template, set Query Loop to inherit the template query, then add a tag filter that dynamically uses the current post’s tags. WordPress 6.5 and later support this through the block’s query context API.

Offset to Avoid Duplicates

If your homepage hero section shows the latest post, set subsequent Query Loop sections to offset by 1. This skips the first post in the query, preventing the same post from appearing in both the hero and the post grid below it.

Excluding the Current Post

Use the exclude_current_post parameter available in the Query Loop block to prevent the current post from appearing in its own Related Posts section. This is a built-in parameter — no PHP filter needed for this common use case.


Pagination, Load More, and No Results

The Pagination Block

The Pagination block lives outside the Post Template but inside the Query Loop. It renders numbered page links connected to the query context. Options include Previous/Next links, numbered links with configurable midsize, and first/last page shortcuts.

For archive templates with Inherit Query enabled, the Pagination block automatically connects to the URL paged query variable. Clicking page 2 updates the URL and loads the correct results.

The No Results Block

The No Results block is a sibling of the Post Template inside the Query Loop. It renders only when the query returns zero posts. Put any content inside it: a message, a search form, links to popular content, or a CTA. It is essential for search results templates and filtered archives where empty results are possible.

A complete search results template uses this structure: Query Loop (inherit query) containing Post Template, No Results with a search block and suggestions, and a Pagination block.


Advanced: Extending Query Loop with PHP Filters

The Query Loop block runs WordPress’s WP_Query under the hood. The query_loop_block_query_vars filter lets you modify the query variables before execution — adding meta queries, date ranges, complex taxonomy queries, or any WP_Query argument the UI does not expose.

This filter receives the query variables array and the block attributes, giving you full control. Common uses for this filter include:

  • Excluding posts with a specific custom field value (e.g., hide sponsored posts from a category archive)
  • Filtering by a date range (only posts published in the last 30 days)
  • Ordering by a custom meta key (e.g., sort by view count or rating)
  • Restricting results to posts where a specific ACF field is populated
  • Adding a post__not_in exclusion list based on user history or previous sections

Block Variations for Reusable Query Presets

If you regularly configure the same query — latest three tutorials in a grid, recent product updates, top-rated portfolio pieces — register a block variation. Variations pre-configure Query Loop with specific settings and a named structure, then appear in the block inserter under a custom name like Latest Tutorials Grid or Featured Projects.

Register variations using wp.blocks.registerBlockVariation in your theme’s editor script, passing the core/query block name and your default attributes.


Block Bindings: Displaying Custom Fields in Query Results

WordPress 6.5 introduced the Block Bindings API, which lets blocks display dynamic values from custom fields and post meta. Combined with Query Loop, this creates data-driven layouts without custom block code.

For bindings to work, the meta field must be registered with register_meta() using 'show_in_rest' => true. Once registered, you can bind a Paragraph block’s content attribute to a meta field key. The Paragraph then shows the correct field value for each post in the Query Loop iteration.

Practical Meta Binding Use Cases

  • Event date — bind a Paragraph to a _event_date meta field in an events CPT archive
  • Price display — bind to a _product_price field in a simple products CPT
  • Reading time — bind to a calculated _reading_time meta field populated on post save
  • Review rating — bind a Paragraph or heading to a numeric rating meta field

Performance Considerations

The Query Loop block runs server-side queries on every page load. Because the output is entirely server-rendered HTML with no client JavaScript, pages with Query Loop blocks are fully cacheable by standard WordPress caching plugins.

Caching Strategy

Standard page caching works perfectly for most Query Loop implementations. The exception is personalized queries — filters tied to the logged-in user, role-based content, or cart-aware results. For those cases, use fragment caching via transients or ensure your caching plugin excludes those specific pages.

Complex Query Performance

If you use the query_loop_block_query_vars filter to add meta queries on large datasets, add database indexes to wp_postmeta for the meta keys you are filtering. Without indexes, meta queries scan the entire postmeta table on every request — a serious performance problem at scale.

Image Lazy Loading

Post Featured Image blocks support native lazy loading. Ensure all images below the fold have lazy loading enabled. WordPress applies this automatically for most images, but verify in DevTools that the first above-fold image in your Query Loop does NOT have the lazy attribute, as lazy-loading the LCP image delays rendering.


Real-World Layout Patterns

Magazine Homepage

Multiple Query Loop blocks stacked vertically with different category filters create a magazine layout: a hero section with 1 featured post, a 3-column news grid with 6 posts, a sidebar list with 5 opinion pieces. Each section has its own Query Loop with independent settings and caches independently.

Documentation Archive

A docs CPT with Query Loop ordered by menu order and filtered by parent category creates a documentation index that automatically updates as you add or reorder articles. No PHP template code needed.

Portfolio Grid with Custom Data

A portfolio CPT with Block Bindings for client name, project year, and service type creates a data-rich portfolio grid entirely in the block editor — featuring image, title, and bound custom fields for each project.


Troubleshooting Common Issues

Issue Likely Cause Fix
CPT not in Post Type dropdown show_in_rest is false Register CPT with show_in_rest: true
Showing all posts instead of filtered Inherit query is ON in a non-archive context Disable Inherit from Template, set filters manually
Pagination not working Pagination block inside Post Template Move Pagination to be a sibling of Post Template inside Query Loop
No Results never shows No Results block inside Post Template Move No Results to be a sibling of Post Template
Same post in multiple sections No offset configured Use offset parameter to skip already-shown posts
Custom meta not displaying Meta not registered with show_in_rest Register meta with register_meta() and show_in_rest: true

What Query Loop Cannot Do

The Query Loop block is powerful but has limits worth knowing:

  • No JavaScript-powered infinite scroll out of the box — standard Pagination only does server-side page navigation. Infinite scroll requires a plugin or custom Interactivity API implementation.
  • No live AJAX filtering — filtering by category, tag, or custom field requires a full page reload unless you add Interactivity API-powered filtering through a plugin or custom code.
  • Limited sorting UI — custom meta key sorting requires the query_loop_block_query_vars filter. There is no editor UI for exposing custom sort fields to content editors.
  • One post type per Query Loop — for mixed-type results, you need a custom REST endpoint or a plugin that extends the block.

Accessibility Considerations for Query Loop Layouts

Dynamic content layouts built with the Query Loop block must meet accessibility standards, especially since they often appear prominently on homepages and archive pages where screen reader users and keyboard navigators spend significant time.

Heading hierarchy matters. If your page title is an h1 and your Query Loop section heading is an h2, the Post Title blocks inside the Query Loop should be h3. Many developers set Post Title blocks to h2 by default, which creates duplicate heading levels and confuses screen reader users who navigate by heading structure. Always audit the heading hierarchy of your complete page including Query Loop output to ensure it follows a logical descent: h1 → h2 → h3 → h4.

Link destinations must be distinguishable. A common post grid pattern links the Post Featured Image, Post Title, and a Read More button all to the same post URL. This creates three consecutive links with the same destination, which screen readers announce as three separate navigation options going to the same place. The better approach is to link only the Post Title, make the featured image decorative (not linked), and use a single clear call-to-action link. If you want the entire card to be clickable, use CSS to stretch the Post Title link over the entire card area using position: relative on the card and position: absolute on the link.

Pagination needs clear labeling. The Pagination block generates Previous and Next links plus numbered page links. Ensure these have descriptive aria-labels that communicate context — “Go to page 3 of blog posts” is more helpful than just “3”. The core Pagination block handles this natively, but verify the output in your specific implementation.

No Results content must be helpful. When a search or filter returns zero results, the No Results block should provide actionable alternatives: a search form, popular content links, or category navigation. An empty results page with only “No posts found” leaves users stranded with no path forward.


Query Loop vs Custom PHP Loops: When to Use Each

The Query Loop block replaces the need for custom PHP loops in most standard use cases, but there are scenarios where PHP remains the better choice.

Use Query Loop when: you need standard post archives, category grids, recent posts sections, related posts displays, search results, or any content listing that maps to standard WP_Query parameters. The block provides visual editing, requires zero maintenance code, and produces clean, cached output.

Use custom PHP when: you need complex multi-query aggregation (pulling from multiple post types into a single sorted list), external API data mixed with WordPress content, real-time personalization based on user behavior or session data, or queries that depend on computation-heavy custom logic that cannot be expressed through WP_Query parameters alone.

For most theme developers, the Query Loop block handles 80 to 90 percent of dynamic content needs. Reserve custom PHP for the remaining edge cases where the block’s capabilities genuinely fall short. Do not default to PHP loops out of habit when the Query Loop block can accomplish the same result with less code and better editor integration.

The hybrid approach also works well: use Query Loop blocks for standard content displays throughout your theme, and create custom PHP-backed block patterns for the specific edge cases that need programmatic control. This gives you the best of both worlds — visual editing where possible, code where necessary.


Frequently Asked Questions

Can I use multiple Query Loop blocks on the same page?

Yes, you can place as many Query Loop blocks on a single page as your design requires. Each Query Loop runs its own independent WP_Query with its own parameters, filters, and pagination. A common homepage pattern uses three or four Query Loops: one for featured posts, one for recent news, one for tutorials, and one for community highlights. Each section queries different categories or post types independently. The only consideration is performance — each Query Loop adds a database query, so keep the total number reasonable and ensure your hosting can handle the load.

In a single post template, add a Query Loop block below the Post Content block. Disable “Inherit from template” and configure the block to filter by the same category or tag as the current post. Enable “Exclude current post” to prevent the post from appearing in its own related posts section. For more sophisticated related posts logic (weighted by multiple shared taxonomies or custom relevance scoring), use the query_loop_block_query_vars filter to modify the underlying WP_Query with your custom relevance algorithm.

Does the Query Loop block work with WooCommerce products?

WooCommerce products are a custom post type (product) with show_in_rest enabled, so they appear in the Query Loop block’s Post Type dropdown. You can build product grids, featured products sections, and category-filtered product displays using the Query Loop block. However, WooCommerce also provides its own Products block with additional commerce-specific features like Add to Cart buttons, price displays, and sale badges. For standard product listing layouts, either approach works. For full WooCommerce functionality (cart integration, product filtering by attributes), use WooCommerce’s native blocks.

The default Pagination block uses server-side page navigation, which triggers a full page reload. For load-more or infinite scroll behavior without page reloads, you need the WordPress Interactivity API or a third-party plugin that adds AJAX pagination to the Query Loop block. The Interactivity API approach registers a directive on the Query Loop block that intercepts pagination clicks, fetches the next page via the REST API, and appends the results to the existing content. This is the recommended approach for WordPress 6.5 and later because it integrates cleanly with the block ecosystem without third-party dependencies.


Start Building Dynamic Layouts Today

The Query Loop block fundamentally changes how WordPress handles dynamic content. Instead of maintaining PHP template files with custom loop logic, you have a visual, configurable block that produces identical output with less maintenance and better editor integration.

Start with the basics: a blog archive template, a recent posts section on your homepage, a category-filtered grid. Once you understand how Post Template iterates and how inner blocks respond to query context, the advanced techniques follow naturally.

The Query Loop block is not just a convenience feature. It is the mechanism through which Full Site Editing delivers truly dynamic, data-driven WordPress sites from within the block editor. If you are building block themes, mastering it is non-negotiable.

For a deeper look at how to structure your block theme to make the most of query-driven templates, read our guide on building your first block theme from scratch. And for performance context on why server-rendered query outputs outperform JavaScript-heavy alternatives, the block themes vs Elementor performance breakdown shows the numbers in detail.