Overview

This component has no inline attributes. Everything is derived from the URL — the path segment after the store base (or the ?category= query param when running inside the theme editor's preview iframe) is the active category slug. Subcategory nesting is supported via slash-separated slugs (parent/child/grandchild).

Renders one of two views:

  • Grid view — at the root, shows top-level categories as image cards.
  • Subcategory view — after a category slug is selected, shows breadcrumbs + subcategories.

When to use

  • On dedicated category landing pages (/c/ root, /c/{slug} drill-down).
  • Inside collection templates — pair with <mmm-data-source> to drive the product grid.

Quick start

<script src="https://v2-api-production.commmerce.com/api/v1/web-component/commmerce-sdk.js?store=sample-store"></script>

<mmm-category></mmm-category>

<!-- Sibling data-source listens for category:selected and re-queries -->
<mmm-data-source api="category.getCategory" response-key="cat" data-type="category">
  <mmm-loop data="{{window.PRODUCT_RESPONSE_CAT.products}}">
    <mmm-product-card data-product="{{item}}"></mmm-product-card>
  </mmm-loop>
</mmm-data-source>

Attributes

Active-category state is entirely URL-driven (no attribute exposes it). The attributes below are presentation knobs — padding, colours, font sizes, and image sizing — that override the inherited theme settings.

AttributeTypeDefaultDescription
paddingstring1.25remBase padding around the grid wrapper.
padding-mobilestringPadding override at ≤ 430px.
padding-tabletstringPadding override at 431–768px.
padding-desktopstringPadding override at 769–1280px.
padding-xlstringPadding override at ≥ 1281px.
text-colorstringtheme primary textCategory title colour. Also acts as the fallback for heading-color and empty-text-color.
heading-colorstringtext-colorSubcategory-view heading colour.
empty-text-colorstringtext-color"No categories found" message colour.
text-font-sizestringtheme subHeading sizeCategory-title font size.
heading-font-sizestringtheme heading sizeSubcategory-view heading font size.
img-widthstring100%Category-image CSS width.
img-heightstringCategory-image CSS height. When omitted, the image keeps a 1/1 aspect ratio.
img-object-fitstringcoverCSS object-fit for the category image.
img-border-radiusstring0.25remCategory-image border-radius.
img-borderstringnoneCategory-image CSS border shorthand.

Events

EventTargetPayload
category:selectedwindow{ category: string, name: string, fromURL?: boolean }

Fires whenever the active category changes — from URL sync on load, from a category-card click, from a subcategory click, and from breadcrumb resets. fromURL: true distinguishes "loaded from address bar" from "user clicked here".

URL conventions

URL patternViewActive slugNotes
/c/gridnoneTop-level category grid.
/c/shoessubcategoryshoesShows shoes's subcategories.
/c/shoes/sneakerssubcategoryshoes/sneakersDrills two levels deep.
?category=shoessubcategoryshoesUsed by the theme-editor preview iframe.

Live preview

store sample-store tag <mmm-category>

Examples

1. Drop into a category page

<mmm-category></mmm-category>

2. Pair with data-source for SSR product grid

<mmm-category></mmm-category>
<mmm-data-source api="category.getCategory" response-key="cat" data-type="category" payload-page-size="24">
  <mmm-loop data="{{window.PRODUCT_RESPONSE_CAT.products}}">
    <mmm-product-card data-product="{{item}}"></mmm-product-card>
  </mmm-loop>
</mmm-data-source>

3. React to URL-driven loads vs clicks

window.addEventListener('category:selected', (e) => {
  if (e.detail.fromURL) {
    /* Initial load — set up scroll tracking, fire pageview, etc. */
    analytics.page('Category', { slug: e.detail.category });
  } else {
    /* User click — track engagement */
    analytics.track('category_click', { slug: e.detail.category });
  }
});