NS Design System
v3.0.0 · 257 tokens

112Tag pages

Two surfaces answering different questions: the top of ONE tag's page, and the page that lists every tag. A tag page arrived at from search is otherwise a list of posts with no statement of what connects them — which is why the description is not decoration here, it is the only thing that says what the tag means.

Use it for

  • A tag or category archive — the header, then a Blog index with the featured card dropped
  • An all-tags page
  • --compact when the tag header sits above a rail-and-grid listing rather than alone

Not for

  • A tag cloud. Encoding count as type size makes the biggest tag the most legible and buries the specific one somebody is hunting for. A sorted grid of equal cards is duller and works
  • A tag page with no description. If you cannot write one sentence about what the tag collects, the tag is not a tag — it is a typo with twelve posts in it

One tag

Header, then the listing. The count sets an expectation before the reader starts scrolling: 12 posts and 300 posts are different promises about how long they are about to be here.

apex 42 posts

Everything about Salesforce’s own language: triggers, governor limits, testing, and the patterns that survive a real org.

markup
<div style="max-inline-size:52rem;inline-size:100%">
  <header class="ns-taghead">
    <h1 class="ns-taghead__title">apex <span class="ns-taghead__count">42 posts</span></h1>
    <p class="ns-taghead__desc">Everything about Salesforce&rsquo;s own language: triggers, governor limits, testing, and the patterns that survive a real org.</p>
    <div class="ns-taghead__actions">
      <a class="ns-btn ns-btn--outline ns-btn--sm" href="#0"><i class="ph ph-rss-simple" aria-hidden="true"></i> Subscribe</a>
      <a class="ns-btn ns-btn--quiet ns-btn--sm" href="#0">All tags</a>
    </div>
  </header>
  <nav class="ns-tagrow" aria-label="Related tags" style="margin-block-start:var(--space-5)">
    <a class="ns-tag" href="#0">triggers</a>
    <a class="ns-tag" href="#0">soql</a>
    <a class="ns-tag" href="#0">testing</a>
    <a class="ns-tag" href="#0">governor-limits</a>
  </nav>
</div>

Compact

For a tag header that sits above the rail-and-grid listing, where the page already has a lot to say.

flow 18 posts

Declarative automation, and where it stops being the right tool.

markup
<header class="ns-taghead ns-taghead--compact" style="max-inline-size:52rem;inline-size:100%">
  <h1 class="ns-taghead__title">flow <span class="ns-taghead__count">18 posts</span></h1>
  <p class="ns-taghead__desc">Declarative automation, and where it stops being the right tool.</p>
</header>

Every tag

Sorted, equal weight, count on the right. The description is what makes this page navigable rather than a wall of nouns.

markup
<div class="ns-tagindex">
  <a class="ns-tagcard" href="#0">
    <span class="ns-tagcard__name">apex <span class="ns-tagcard__count">42</span></span>
    <span class="ns-tagcard__desc">Triggers, governor limits, testing, and the patterns that survive a real org.</span>
  </a>
  <a class="ns-tagcard" href="#0">
    <span class="ns-tagcard__name">flow <span class="ns-tagcard__count">18</span></span>
    <span class="ns-tagcard__desc">Declarative automation, and where it stops being the right tool.</span>
  </a>
  <a class="ns-tagcard" href="#0">
    <span class="ns-tagcard__name">architecture <span class="ns-tagcard__count">11</span></span>
    <span class="ns-tagcard__desc">Data models, sharing, and decisions that are expensive to reverse.</span>
  </a>
  <a class="ns-tagcard" href="#0">
    <span class="ns-tagcard__name">careers <span class="ns-tagcard__count">7</span></span>
    <span class="ns-tagcard__desc">Certifications, interviews, and what actually gets people hired.</span>
  </a>
</div>

Both, full page

The tag page is the blog index with its header swapped and the featured card dropped — worth checking side by side rather than taking on trust. Resize either one: the rail drops below the grid at 64rem, and the tag cards reflow from four columns to one.

markup
<p style="display:flex;flex-wrap:wrap;gap:var(--space-3)">
  <a class="ns-btn ns-btn--outline ns-btn--sm" href="./demo-tag-page.html" target="_blank" rel="noopener">Open the tag page <i class="ph ph-arrow-up-right" aria-hidden="true"></i></a>
  <a class="ns-btn ns-btn--outline ns-btn--sm" href="./demo-tag-index.html" target="_blank" rel="noopener">Open the all-tags page <i class="ph ph-arrow-up-right" aria-hidden="true"></i></a>
  <a class="ns-btn ns-btn--quiet ns-btn--sm" href="./demo-blog-listing.html" target="_blank" rel="noopener">Compare with the index <i class="ph ph-arrow-up-right" aria-hidden="true"></i></a>
</p>

Accessibility contract

  • The # is generated in CSS, never typed: a hash in the DOM is read aloud as “number sign” before every tag name on the page
  • The count is real text beside the title, so “12 posts” is announced rather than inferred from the length of a list
  • The tag row is a <nav> with an accessible name — it is navigation, not a set of decorative chips