Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

For a visual, no-code list, add a Query Loop block and set its category filter. For PHP templates, create a secondary WP_Query; use get_posts() for a short, separate list. Do not use query_posts() for an embedded list because it replaces the page’s main query.

Choose the method that matches the page

WordPress can show category posts in several fundamentally different ways. The right choice depends on whether you need an editor-managed block, a custom PHP layout, a small widget-like list, or the category’s canonical archive page.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Method Best for Category controls Important limitation
Query Loop block Block themes and visual editing Category filter, post type, order, count, pagination and no-results settings The exact controls and styling depend on the active theme and editor
WP_Query Custom templates, landing pages and PHP-driven grids Slug, ID, multiple-category inclusion and exclusion Restore global post data after the loop
get_posts() A small secondary list such as “latest news” Most normal query arguments, including category filters Not the right foundation for a full paginated archive
Category archive template When the category itself is the page’s main subject WordPress archive routing and the main query Whether you can customize it directly depends on the theme

Decide whether you need an archive or an embedded list

Use the category archive for a category’s primary destination

A category archive is the normal URL where visitors browse all posts assigned to a category. It is appropriate when someone arrives specifically to read that topic, and when the category page should own its title, description, navigation and pagination. In a classic theme, the archive may be rendered through archive.php. A custom post type can have a template such as archive-{post_type}.php. The exact template hierarchy and available editing controls are theme-dependent.

Embed a category list when it supports other page content

An embedded list belongs on a page that has a broader purpose: for example, a home page with separate sections for News and Tutorials, or a campaign page that places a curated category grid below introductory content. A Query Loop or secondary PHP query lets each section have its own heading, number of items and visual treatment without turning the entire page into a category archive.

These are different navigation decisions, not merely two coding styles. Choose the archive when the category is the page’s main content; choose an embedded list when the category is one component of a larger layout.

List category posts without code using Query Loop

The Query Loop block is the simplest route for block themes and for editors who want to change the layout without editing PHP. It can query posts, filter them by category, display them as a list or grid, control ordering and item count, paginate longer results, and show a dedicated message when nothing matches.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Step 1: Insert the block

  1. Open the page in the WordPress editor, or open the Site Editor when you are editing a template.
  2. Insert a Query Loop block where the category list should appear.
  3. Choose the post type. For a normal blog category, select posts; choose another type only when that content type supports the taxonomy you need.

Step 2: Apply the category filter

In the Query Loop settings, open the filters or query controls and select the category. Use the category’s displayed name in the picker; the block handles the underlying term selection for you. If the category does not appear, verify that it exists and that published posts are assigned to it.

Step 3: Pick a list or grid layout

Choose a list for a compact feed or a grid for cards. The selected pattern determines the initial structure, but you can edit the Post Template inside the Query Loop. Add or remove blocks such as Post Title, Featured Image, Excerpt, Date, Author, Categories and Read More. Keep the title linked so visitors can open the full post.

Step 4: Set count and ordering

Set how many posts should appear on each page and choose the order, such as newest first. A small number works well for a landing-page section; a larger number is more suitable for an archive-like page. Do not assume that displaying a fixed first page gives visitors access to older posts.

Step 5: Add pagination when the category continues

Insert the Query Loop’s Pagination block when the filtered category can contain more posts than the first page. Test the next and previous links on the front end, not only in the editor, because theme styles can affect their visibility and spacing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Step 6: Define the empty state

Inside the Query Loop, add a No Results section. Write a short message explaining that no published posts currently match the category, and provide a useful next action such as returning to the main blog. Without this section, an empty query can leave a confusing blank area.

Step 7: Check the front-end result

Preview the page at the screen sizes your audience uses. Confirm that long titles wrap cleanly, images have meaningful alternative text where appropriate, excerpts do not create uneven card heights, and pagination remains reachable by keyboard. Save only after checking the filtered result as a visitor would see it.

Build a category list with a secondary WP_Query

Use a new WP_Query when PHP must control the markup, query arguments or placement in a custom template. This is the standard approach for a landing page that needs a bespoke card grid, a fixed section heading or several independently filtered lists.

Basic category query by slug

category_name expects the category’s URL slug, not its human-readable display name. The following example requests ten published posts from the news category and prints a simple linked title and excerpt.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
$category_posts = new WP_Query([
    'post_type'      => 'post',
    'category_name'  => 'news', // category slug
    'posts_per_page' => 10,
]);

if ($category_posts->have_posts()) :
    while ($category_posts->have_posts()) :
        $category_posts->the_post();
        ?>
        <article>
            <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
            <?php the_excerpt(); ?>
        </article>
        <?php
    endwhile;
endif;
wp_reset_postdata();
?>

The query is separate from the page’s main loop, but calling the_post() changes the current post context while the custom loop runs. wp_reset_postdata() restores the surrounding template’s post context afterward, preventing later headings, links or metadata from accidentally referring to the last item in the category list.

Use IDs or multiple-category rules when slugs are not enough

WordPress provides several category arguments for different matching rules:

  • cat accepts one category ID. It includes posts in that category and follows WordPress’s documented child-category behavior.
  • category__in accepts an array of category IDs and matches posts in any listed category. The documented behavior does not automatically include child categories.
  • category__and accepts an array of IDs and requires a post to belong to every listed category.
  • category__not_in accepts an array of IDs and excludes posts assigned to those categories.

For example, an “either News or Tutorials” query can use category__in, while a “must be in both News and Tutorials” query needs category__and. If you use IDs, verify the term IDs in the dashboard or with WordPress’s term tools rather than substituting a category name.

Control status, type and volume explicitly

Set post_type to the content type you actually want. Use post_status when the query must be explicit about published content, especially in a template that could run in an administrative preview. Set posts_per_page to the number the design can support; an unrestricted query can make a page unnecessarily heavy.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Add pagination for a multi-page custom list

A secondary query does not automatically create navigable pages just because it has many results. Pass the current page into the query and render pagination around the custom loop:

<?php
$current_page = max(1, get_query_var('paged'), get_query_var('page'));
$category_posts = new WP_Query([
    'post_type'      => 'post',
    'category_name'  => 'news',
    'posts_per_page' => 10,
    'paged'          => $current_page,
]);

if ($category_posts->have_posts()) :
    while ($category_posts->have_posts()) :
        $category_posts->the_post();
        // Render each post here.
    endwhile;

    echo paginate_links([
        'total' => $category_posts->max_num_pages,
        'current' => $current_page,
    ]);
endif;
wp_reset_postdata();
?>

Keep the pagination URL and page heading understandable, and test links when the list has zero, one and several pages. If the list is only a short section on a larger landing page, a “View all News” link to the category archive is often clearer than embedding a second pagination system.

Use get_posts() for a small, separate list

get_posts() is convenient when you need a handful of items and do not need a full archive experience. It retrieves posts that match query arguments without replacing the global main loop, making it suitable for a sidebar, footer, related-content strip or a compact “latest from this category” section.

<?php
$category_posts = get_posts([
    'category_name' => 'news',
    'numberposts'   => 5,
    'post_status'   => 'publish',
]);

foreach ($category_posts as $post) :
    setup_postdata($post);
    ?>
    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    <?php
endforeach;
wp_reset_postdata();
?>

The argument name is numberposts in this helper. Because the result is intended to be short and non-paginated, do not use it as a substitute for a category archive with hundreds of posts. As with a custom WP_Query loop, reset post data after calling setup_postdata().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep the main query intact

Why query_posts() causes problems

query_posts() also uses WP_Query, but it directly alters the main loop. Calling it merely to add a category list can break the page’s original title, pagination, conditional tags, offsets and other template behavior. It can also produce confusing results when another part of the page expects the original query.

For secondary content, create a new WP_Query, call get_posts() for a small list, or use the existing main query. Do not overwrite the main query from inside a template just to change one section.

Change an archive’s main query with pre_get_posts

If the real requirement is to alter the category archive itself—for example, changing how many posts the archive displays—use the pre_get_posts hook and target the main query conditionally. The condition should distinguish the front end and the main query before changing its arguments, so administrative screens and unrelated queries are not affected. This keeps the archive’s normal routing and pagination intact.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make the output usable and maintainable

Use semantic, linkable post markup

Wrap each result in an <article> element, give it a heading, and link the title to the post permalink. If an image is included, use the featured-image block or WordPress’s image functions so the site’s responsive image behavior is preserved. Keep the clickable area large enough on touch screens and ensure focus styles remain visible.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Limit what each card loads

For a grid, a title, thumbnail and short excerpt are usually enough. Loading full post content for every card increases page size and can expose formatting that was designed for the single-post view. Set a deliberate item count and avoid querying fields that the design never prints.

Handle empty and unpublished states

Visitors only see published posts on the public site unless a preview or custom status is intentionally requested. A category with no published matches should have an explicit message in a Query Loop or a conditional branch in PHP. Do not leave an empty heading that suggests content failed to load.

Troubleshoot a category list that is empty or wrong

  • Nothing appears: confirm that the category has published posts and that the selected post type is correct.
  • The PHP filter returns zero posts: check that category_name contains the slug, not the display name. Slugs can differ in capitalization, punctuation and translated text.
  • ID matching is unexpected: decide whether the requirement is one category with cat, any category in a list with category__in, all categories with category__and, or exclusions with category__not_in. Verify the IDs.
  • Only the first items are visible: set a suitable posts-per-page value and add Query Loop pagination or custom pagination for a multi-page result.
  • Content elsewhere on the page is incorrect: check that a custom loop restores post data and that no template code is using query_posts() for the secondary section.
  • The editor shows a blank area for an empty category: add and customize the Query Loop’s No Results section.
  • The layout differs between editor and site: inspect the active theme’s Query Loop, Post Template and pagination styles; those controls can change the final spacing and card arrangement.

A practical decision guide

Choose Query Loop when editors own the page

Select Query Loop if the page is edited in blocks, the category filter is straightforward, and the team needs to change card fields or the number of posts without deploying code. It provides the fastest path to a list or grid with built-in pagination and an empty state.

Choose WP_Query when the template owns the design

Select a secondary WP_Query when you need custom HTML, several independent category sections, complex inclusion rules, a custom post type, or PHP-controlled pagination. Keep the query narrowly scoped and restore post data immediately after its loop.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose get_posts() when five or so links are all you need

Use get_posts() for a compact, non-paginated group such as five recent links in a sidebar or footer. It is simpler than managing a full query loop, but it is not intended to power the canonical archive for a large category.

Choose the archive when category navigation is the product

Use the normal category archive when visitors should browse that topic as a destination with its own URL, heading and pagination. Customize the relevant archive template or the main query rather than inserting a second list into an unrelated page.

Final checklist before publishing

  • The category filter points to the intended term and post type.
  • The number of displayed posts matches the page’s purpose and performance budget.
  • Longer categories have working pagination or a clear link to the archive.
  • Each result has a descriptive, keyboard-accessible title link.
  • An empty category produces a helpful message instead of a blank block.
  • PHP loops restore the surrounding post context.
  • The implementation does not overwrite the main query merely to create a secondary list.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.