skills/responsive-styling/SKILL.md
Automatically generate mobile-first responsive CSS/SCSS when creating component styles or mentioning responsive design. Implements standard breakpoints (768px, 1024px), ensures WCAG AA color contrast, creates touch-friendly interfaces (44px minimum targets), adds proper focus indicators, supports reduced motion, scales typography responsively, and provides detailed technical specifications with exact values.
npx skillsauth add kanopi/cms-cultivator responsive-stylingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate mobile-first, responsive CSS/SCSS that works across all devices and follows accessibility best practices.
Responsive design is accessibility. Mobile-first is user-first.
This skill automatically activates when:
Before generating responsive styles, determine:
Standard mobile-first breakpoints:
@media (min-width: 768px)@media (min-width: 1024px)When to add breakpoints:
WCAG 2.1 Level AA compliance:
@media (prefers-reduced-motion: reduce)Interactive states (buttons, links):
:hover - Mouse pointer over element:focus - Keyboard navigation focus:focus-visible - Keyboard focus (not mouse click):active - During click/tap:disabled - Inactive statePriority: Focus states more important than hover (accessibility)
Mobile-first sizing:
clamp() for fluid scaling
font-size: clamp(1.5rem, 5vw, 2.5rem);Consistent spacing scale (choose one):
Apply consistently:
User requests responsive styles
↓
Determine component type
↓
Define mobile-first base styles (320px+)
↓
Calculate contrast ratios (WCAG AA)
↓
Add tablet breakpoint (768px+) if layout changes
↓
Add desktop breakpoint (1024px+) if needed
↓
Add all interactive states (focus > hover)
↓
Add reduced motion support
↓
Output mobile-first SCSS with exact values
Always write base styles for mobile, then enhance for larger screens:
// ✅ CORRECT: Mobile-first
.component {
font-size: 1rem; // Base mobile style
padding: 1rem;
@media (min-width: 768px) {
font-size: 1.125rem; // Enhance for tablet
padding: 2rem;
}
@media (min-width: 1024px) {
font-size: 1.25rem; // Enhance for desktop
padding: 3rem;
}
}
// ❌ WRONG: Desktop-first
.component {
font-size: 1.25rem;
@media (max-width: 1024px) {
font-size: 1.125rem;
}
@media (max-width: 768px) {
font-size: 1rem;
}
}
Use consistent breakpoints:
// Mobile: 320px - 767px (base styles, no media query)
// Tablet: 768px - 1023px
$breakpoint-tablet: 768px;
// Desktop: 1024px+
$breakpoint-desktop: 1024px;
// Optional additional breakpoints
$breakpoint-mobile-large: 480px;
$breakpoint-tablet-large: 960px;
$breakpoint-desktop-large: 1280px;
Scale typography appropriately:
.heading-1 {
// Mobile base
font-size: 2rem; // 32px
line-height: 1.2;
font-weight: 700;
margin-bottom: 1rem;
// Tablet
@media (min-width: 768px) {
font-size: 2.5rem; // 40px
margin-bottom: 1.5rem;
}
// Desktop
@media (min-width: 1024px) {
font-size: 3rem; // 48px
margin-bottom: 2rem;
}
}
.body-text {
// Mobile base
font-size: 1rem; // 16px
line-height: 1.6;
// Tablet
@media (min-width: 768px) {
font-size: 1.125rem; // 18px
line-height: 1.7;
}
// Desktop
@media (min-width: 1024px) {
font-size: 1.25rem; // 20px
line-height: 1.8;
}
}
Use fluid spacing that scales:
// Method 1: Stepped spacing
.section {
// Mobile
padding: 2rem 1rem;
margin-bottom: 2rem;
// Tablet
@media (min-width: 768px) {
padding: 3rem 2rem;
margin-bottom: 3rem;
}
// Desktop
@media (min-width: 1024px) {
padding: 4rem 3rem;
margin-bottom: 4rem;
}
}
// Method 2: Fluid spacing with clamp
.section-fluid {
// Scales smoothly between mobile and desktop
padding: clamp(2rem, 5vw, 4rem) clamp(1rem, 3vw, 3rem);
margin-bottom: clamp(2rem, 4vw, 4rem);
}
.card-grid {
display: grid;
gap: 1.5rem;
// Mobile: single column
grid-template-columns: 1fr;
// Tablet: 2 columns
@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
// Desktop: 3 columns
@media (min-width: 1024px) {
grid-template-columns: repeat(3, 1fr);
gap: 3rem;
}
}
.flex-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
// Mobile: stack vertically
flex-direction: column;
// Tablet and up: horizontal
@media (min-width: 768px) {
flex-direction: row;
gap: 2rem;
}
.flex-item {
// Mobile: full width
flex: 1 1 100%;
// Tablet: 2 items per row
@media (min-width: 768px) {
flex: 1 1 calc(50% - 1rem);
}
// Desktop: 3 items per row
@media (min-width: 1024px) {
flex: 1 1 calc(33.333% - 1.333rem);
}
}
}
// Handle WordPress core padding
.wp-block-cover {
// Full viewport width accounting for theme padding
width: calc(100vw - var(--wp--style--root--padding-left) - var(--wp--style--root--padding-right));
max-width: none;
// Center it
margin-left: calc(-1 * var(--wp--style--root--padding-left));
margin-right: calc(-1 * var(--wp--style--root--padding-right));
}
// Pattern wrapper
.wp-block-group.pattern-name {
// Mobile
padding: 2rem 1rem;
// Inner content container
.wp-block-group__inner-container {
max-width: 100%;
margin: 0 auto;
// Tablet
@media (min-width: 768px) {
max-width: 750px;
}
// Desktop
@media (min-width: 1024px) {
max-width: 1200px;
}
}
}
.paragraph--type--name {
// Mobile base
padding: 2rem 1rem;
// Inner container
.paragraph__content {
max-width: 100%;
margin: 0 auto;
@media (min-width: 768px) {
padding: 3rem 2rem;
max-width: 750px;
}
@media (min-width: 1024px) {
padding: 4rem 3rem;
max-width: 1200px;
}
}
}
.field--name-field-items {
display: grid;
gap: 1rem;
// Mobile: stack
grid-template-columns: 1fr;
// Tablet: 2 up
@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
}
// Desktop: 3 up
@media (min-width: 1024px) {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
}
IMPORTANT: WordPress block patterns require TWO separate stylesheets:
Standard styles that apply to published pages. No special wrapper needed.
Styles for the WordPress block editor (admin). Must wrap all selectors with .editor-styles-wrapper.
Example:
Front-end (_hero-cta.scss):
.hero-cta-pattern {
padding: 2rem 1rem;
background: #0073aa;
color: #ffffff;
@media (min-width: 768px) {
padding: 3rem 2rem;
}
}
Editor (_hero-cta-editor.scss):
// Wrap everything with .editor-styles-wrapper
.editor-styles-wrapper {
.hero-cta-pattern {
padding: 2rem 1rem;
background: #0073aa;
color: #ffffff;
@media (min-width: 768px) {
padding: 3rem 2rem;
}
}
}
Why this is necessary:
.editor-styles-wrapper as a scoping mechanismimg {
max-width: 100%;
height: auto;
display: block;
}
.hero-background {
background-size: cover;
background-position: center;
min-height: 300px;
@media (min-width: 768px) {
min-height: 400px;
}
@media (min-width: 1024px) {
min-height: 600px;
}
}
.responsive-image {
// Mobile: portrait crop
aspect-ratio: 4/5;
object-fit: cover;
// Tablet: square
@media (min-width: 768px) {
aspect-ratio: 1/1;
}
// Desktop: landscape
@media (min-width: 1024px) {
aspect-ratio: 16/9;
}
}
button,
a,
input,
select {
// Minimum 44x44px for touch
min-height: 44px;
min-width: 44px;
// Larger on very small screens
@media (max-width: 375px) {
min-height: 48px;
min-width: 48px;
}
}
.touch-menu {
li {
// More spacing on mobile
margin-bottom: 0.5rem;
a {
// Larger tap area
padding: 0.75rem 1rem;
display: block;
}
}
// Less spacing needed on desktop with mouse
@media (min-width: 1024px) {
li {
margin-bottom: 0.25rem;
a {
padding: 0.5rem 1rem;
}
}
}
}
a, button, input, select {
&:focus {
outline: 2px solid currentColor;
outline-offset: 2px;
}
// More prominent on mobile
@media (max-width: 767px) {
&:focus {
outline-width: 3px;
}
}
}
.content {
// Mobile: shorter line length
max-width: 100%;
// Desktop: optimal reading width
@media (min-width: 768px) {
max-width: 65ch; // ~65 characters per line
}
}
// Respect user's motion preferences
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
// Show only on mobile
.mobile-only {
display: block;
@media (min-width: 768px) {
display: none;
}
}
// Hide on mobile
.desktop-only {
display: none;
@media (min-width: 768px) {
display: block;
}
}
// Tablet and up
.tablet-up {
display: none;
@media (min-width: 768px) {
display: block;
}
}
.main-nav {
// Mobile: hamburger menu
@media (max-width: 767px) {
.menu-toggle {
display: block;
}
.menu-items {
display: none;
&.is-open {
display: block;
position: fixed;
top: 60px;
left: 0;
right: 0;
background: white;
padding: 1rem;
}
}
}
// Desktop: horizontal menu
@media (min-width: 768px) {
.menu-toggle {
display: none;
}
.menu-items {
display: flex;
gap: 2rem;
}
}
}
// Define fluid typography
:root {
// Scales from 16px to 20px
--font-size-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
// Scales from 32px to 48px
--font-size-h1: clamp(2rem, 1.5rem + 2vw, 3rem);
// Scales from 24px to 32px
--font-size-h2: clamp(1.5rem, 1.25rem + 1vw, 2rem);
// Scales from 20px to 24px
--font-size-h3: clamp(1.25rem, 1.125rem + 0.5vw, 1.5rem);
}
body {
font-size: var(--font-size-base);
}
h1 {
font-size: var(--font-size-h1);
}
h2 {
font-size: var(--font-size-h2);
}
h3 {
font-size: var(--font-size-h3);
}
When generating responsive styles, ensure:
When generating responsive styles, provide:
/* Component Name */
/* Mobile base styles (320px - 767px) */
.component {
/* All base styles here */
}
/* Tablet (768px - 1023px) */
@media (min-width: 768px) {
.component {
/* Tablet enhancements */
}
}
/* Desktop (1024px+) */
@media (min-width: 1024px) {
.component {
/* Desktop enhancements */
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
/* Reduced motion styles */
}
❌ Desktop-first (using max-width) ❌ Magic numbers (random breakpoints) ❌ Forgetting touch targets ❌ Fixed pixel widths that don't scale ❌ Tiny text on mobile (<16px) ❌ Horizontal scrolling ❌ Ignoring landscape mobile ❌ Breaking at intermediate sizes
✅ Mobile-first (using min-width) ✅ Consistent breakpoints ✅ 44px minimum touch targets ✅ Flexible widths with max-width ✅ 16px minimum text ✅ Contained content ✅ Test at 320px, 768px, 1024px ✅ Test at all widths
tools
Strategist-focused site audit for discovery and pre-discovery. Given a site URL and optional qualitative research data, navigates the site via CoWork, audits against all 21 UX Laws from lawsofux.com, reviews content hierarchy, synthesises qualitative data, runs Lighthouse, and produces two deliverables — a Project Knowledge Summary (Markdown for Claude Desktop Projects) and a polished, iterable HTML Artifact for client sharing. Use when a strategist, UX lead, or PM asks for a discovery audit, UX laws audit, content hierarchy review, pre-discovery site review, "audit this site for strategy", "strategist audit", "UX audit", or pastes a site URL with discovery context. Not for developer audits — use accessibility-audit, performance-audit, or live-site-audit for those.
development
Provide story point estimation guidance with hour calculations for software development tasks. Uses Fibonacci sequence (1, 2, 3, 5, 8, 13, 21, 34+) and converts story points to hours. Includes platform-specific adjustments and velocity calculations.
tools
Perform a full QA review of a Teamwork task by reading the task and all its comments for context, extracting the multi-dev URL, generating dynamic validation steps tailored to the task type, and using CoWork browser automation to execute those steps on the multi-dev environment. Produces a structured validation report with pass/fail per step, screenshots, internal notes, and a client-facing summary — all shown in chat. Use this skill whenever the user asks to QA, test, validate, or review a Teamwork task or multi-dev environment — even if they just say "can you QA this?" or paste a Teamwork link. Also triggers for phrases like "run QA on", "check the multi-dev", "validate this task", "test the dev link", or "review the ticket". Works across Drupal/CMS updates, WordPress/plugin updates, bug fixes, new feature development, and general web development tasks.
tools
Generate a client-facing project heartbeat / status update message for a Kanopi project, ready to be posted as a Teamwork message. Use this skill whenever the user asks to write, draft, generate, or send a project update, heartbeat, status update, or progress report to a client. Also triggers when the user says things like "time for a project update", "draft the heartbeat", "write up the update for [project]", or "it's been two weeks, let's send an update". Always use this skill — even if the user doesn't say "heartbeat" — whenever the intent is to summarise recent project activity for a client audience.