Files
CWC/docs/superpowers/specs/2026-07-05-blog-post-card-design.md

7.7 KiB
Raw Permalink Blame History

Blog Post Card Styling Design

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Restyle the blog post card to match blog-post-card.png — a vertical card with a featured image on top and a solid blue content area below containing the title, byline, and a "Read more" link in orange.

Architecture: A targeted CSS update to styles/components/post-list.css (the card body, title, byline, and a new .post-list__read-more rule), and a one-line markup addition in index.php to render the "Read more" anchor. No template structure changes. No new Playwright tests beyond a single new assertion in the existing tests/blog-page.spec.js.

Tech Stack: WordPress 6.x, PHP 8.x, Tailwind CSS v4, Playwright, axe-core, PHPCS (WordPress standard).

Global Constraints

  • Tabs for PHP indentation (project standard).
  • The theme's Tailwind build outputs static/dist/theme.css; that file is gitignored but committed with git add -f per project convention.
  • PHPCS uses the WordPress coding standard; composer lint must pass. Pre-existing CRLF errors on untouched files are out of scope.
  • All design colors use the project's existing CSS custom properties from styles/base/colors.css. No hardcoded hex values for theme colors.
  • The card width behavior stays the same: grid-cols-[repeat(auto-fit,minmax(20rem,1fr))]. No layout refactor.
  • The "Read more" link reuses the post's permalink — it's the same destination as the title link.
  • The H1 ("Blog" page title) and search.php are explicitly out of scope for this change. The working tree currently has the H1 removed and search.php untouched; this design does not address either.

Reference Mockup

blog-post-card.png (426×644, vertical 2:3) at the theme root. The mockup shows:

  • Image area (top ~38%): light gray placeholder. Real implementation uses the post's featured image via has_post_thumbnail().
  • Content area (bottom ~62%): solid #90c9e7 background. This color is the hex equivalent of --color-cwc-blue-03 (oklch(80.63% 0.0724 230.4)).
  • Title: multi-line, dark blue text (matches --color-cwc-blue-01).
  • Byline: smaller dark text near the bottom of the content area.
  • "Read more" link: orange (#d24d32, matches --color-secondary / --color-cwc-orange-01) at the bottom-left of the card.

File Structure

File Responsibility Created/Modified
styles/components/post-list.css Add card body, title, byline, and .post-list__read-more styles. Modify
index.php Add a "Read more" link after the byline in .post-list__details. Modify
static/dist/theme.css Rebuilt via npm run build. Modified (committed with git add -f).
tests/blog-page.spec.js Add a single assertion that the "Read more" link exists in the first card. Modify

Design Details

CSS additions to styles/components/post-list.css

The card already has the following structure (from index.php):

<div class="post-list__post flex flex-col border border-secondary rounded-md shadow-lg ...">
    <figure class="post-list__img aspect-video border-b border-secondary rounded-t-md ...">
        <img class="...">
    </figure>
    <div class="post-list__details px-4 py-6 flex flex-col grow">
        <a href="..."><h2 class="post-list__title ...">Title</h2></a>
        <div class="post-list__byline mt-auto">
            <span class="post-list__author">Author</span>
            <span class="post-list__date">Date</span>
        </div>
    </div>
</div>

The styling changes:

  1. .post-list__post — Override the gray border-secondary so the card border disappears (the blue background extends edge-to-edge inside the card). Keep the rounded corners and shadow. The current classes in index.php set border border-secondary; we override via CSS to border-color: var(--color-cwc-blue-03).

  2. .post-list__post and .post-list__img — Set border: 0 (or border-color: transparent) on the figure so the existing border-b border-secondary does not show. The visual change is that the image and the blue content area flow as separate blocks without a divider line between them. The card itself keeps its rounded-md corners; the figure keeps rounded-t-md so the image rounds with the card.

  3. .post-list__title — Set color: var(--color-cwc-blue-01), font-weight: 700 (override the font-normal in the markup). Keep the existing text-25px size and line-clamp-4 truncation. The title is the project's standard H2 typography.

  4. .post-list__byline — Set color: var(--color-cwc-blue-01), font-size: 0.875rem (smaller than the title, but readable on the blue background). Keep mt-auto so the byline sits at the bottom of the available space.

  5. .post-list__read-more (new) — color: var(--color-secondary), font-weight: 600, margin-top: 0.75rem, text-decoration: none. Hover: underline. The text content is "Read more →" (em dash and arrow, no period).

Markup change in index.php

Inside .post-list__details, after the .post-list__byline div, add:

<a class="post-list__read-more" href="<?php the_permalink(); ?>">Read more &rarr;</a>

No other markup changes. The title link, image, byline, and pagination are untouched.

What stays the same

  • Card structure: figure for image, div.post-list__details for content.
  • Grid layout: grid-cols-[repeat(auto-fit,minmax(20rem,1fr))] gap-6.
  • Image aspect ratio: aspect-video (16:9).
  • Image hover effect: hover:prose-img:scale-110 with duration-500 transition.
  • Empty state ("Nothing here yet…").
  • Pagination.
  • Card padding: px-4 py-6 on .post-list__details.
  • The H1 / search.php / sidebar — all untouched.

Test updates

Add a single assertion to the desktop test in tests/blog-page.spec.js:

// First card has a "Read more" link.
await expect(firstCard.locator(".post-list__read-more")).toBeVisible();
await expect(firstCard.locator(".post-list__read-more")).toHaveAttribute(
    "href",
    /\/[a-z0-9-]+\/?$/
);

No new spec file. The existing 4 tests stay as they are.

Out of Scope

  • The H1 page title — the working tree currently has the H1 markup removed. The previous blog plan added it (commit 66073c0) and the design tokens (commit cb0c886); both are present in git history. Whether to re-add the H1 is a separate decision.
  • search.php — still a separate template, still has the old card structure, still has the $featimg case-sensitivity bug. Separate work.
  • static/dist/theme.css pre-existing changes from other work in the working tree (header.php, views/partials/page-hero-services.php, etc.) are unrelated and not touched.
  • Dark mode.
  • Animations on the "Read more" link beyond a basic underline-on-hover.
  • The H2 font family (Quincy vs sans) — the existing card uses the default font family for the title. The mockup's title appears to be a clean sans-serif weight-700. We do not change the font family.

Self-Review Notes

  • Spec coverage: One CSS file, one PHP file, one test file, one dist rebuild. Every spec section is covered.
  • Placeholder scan: No "TBD", "TODO", or vague requirements. The "→" arrow and "Read more" text are spelled out explicitly.
  • Type consistency: Class names follow the existing BEM convention (__read-more).
  • Spec section "Out of Scope" is explicit: H1, search.php, dark mode, font family changes, animations — all out.
  • Design tokens: All colors reference existing CSS custom properties. No new colors introduced.
  • Indentation: Tabs for PHP (project standard).