semantic-markup-css
Skill2 starsChanged 40 days agoMITView on GitHub
Guides modern HTML semantics, WAI-ARIA, WCAG contrast, data-* state attributes, and native elements over div-heavy UI; pairs Tailwind with modern CSS where CSS wins. Use before marketing/UI refactors, landing pages, forms, dialogs, nav, or when the user mentions semantics, WAI-ARIA, accessibility, data attributes, native elements, color contrast, or modern CSS.
In this repository49 other files it gives its agents.
- AGENTS.mdAGENTS.md
- adversarial-auditSkill
- agentic-reactorSkill
- agent-orchestratorSkill
- ai-optimizationSkill
- architecture-synthesisSkill
- audit-allow-buildsSkill
- audit-ide-dependenciesSkill
- author-workflow-skillSkill
- bdd-strategizerSkill
- chrome-extension-mv3Skill
- concurrent-cli-agentsSkill
- control-feederSkill
- control-graphSkill
- cursor-transcript-harvestSkill
- cv-promote-guardSkill
- devcontainer-hardenedSkill
- dual-copy-skill-publishSkill
- explore-repo-readonlySkill
- finder-reactorSkill
- fix-dependency-securitySkill
- fusion-sageSkill
- git-worktreesSkill
- grok-host-prepSkill
- gt-flowSkill
- higher-order-decision-architectSkill
- looperSkill
- master-plannerSkill
- mvu-refactor-planSkill
- odysseus-navigatorSkill
- project-editor-profileSkill
- react-client-expertSkill
- semantic-nameSkill
- session-unit-orderSkill
- shell-kernel-ontologySkill
- skill-rename-propagationSkill
- split-to-prsSkill
- src-tree-reorganizeSkill
- stellar-roadmapSkill
- stellar-spacemapSkill
- subagent-delegationSkill
- subagent-explore-reportSkill
- supply-chain-hardenSkill
- tauri-agenticSkill
- tauri-ipc-debugSkill
- tidy-commit-pushSkill
- upgrade-packagesSkill
- verification-cockpitSkill
- x-agent-resourcesSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 52
Do not add redundant roles (role="navigation" on <nav>) or label with ARIA what visible text already provides.
- Distinctive: line 67
Verify both theme variants (e.g.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Semantic markup & modern CSS
Load first on marketing UI, layout refactors, or any task touching TSX + styles. Pair with react-client-expert for client state; this skill owns HTML, ARIA, tokens, and CSS architecture.
Optional project overlay: see examples/overlays/ (e.g. Next.js portfolio marketing CSS).
Decision order (always)
- Native element — can
<button>,<a>,<dialog>,<details>,<address>,<figure>,<ul>/<ol>do the job? - Semantics + one heading level — correct landmark/section/article; single
h1, sectionh2, cardh3 - WAI-ARIA only to fill gaps — prefer native semantics; don't duplicate what HTML already exposes
data-*state in DOM — style with CSS; avoid parallelisOpen && "block"class soup- Token/contrast fix — adjust CSS variables before per-component color hacks
- Tailwind for layout/type — spacing, grid, responsive; CSS for scroll-margin,
:has(),@container,color-mix, reduced motion
Semantic HTML
| Job | Use | Avoid |
| Page regions | One <main>; <header>, <footer>, <nav aria-label="…"> | Nested <main>; <div onClick> navigation |
| Sections | <section id="…" aria-labelledby="…-heading"> + one <h2 id="…-heading"> | <div id="…"> with orphan headings |
| Cards / items | <article>; link via <a> on title or card wrapper | <motion.div> as the interactive root |
| Lists | <ul role="list"> / <ol> | Flex divs of <span> |
| Contact | <address> (reset italic in CSS) | Div stacks |
| Media | <figure> + <figcaption> or sr-only caption | Decorative div-only portrait |
| Overlays | <dialog> + <form method="dialog"> close | Fixed <div> + manual focus trap (unless Radix already standardized) |
| Expand/collapse | <details> / <summary> when no heavy JS state | Custom div accordion |
Buttons vs links: navigation → <a href>; in-page actions → <button type="button">. Never <div role="button">.
WAI-ARIA (minimal)
- Landmarks:
aria-labelon<nav>when multiple (Primary,Footer,Social) - Disclosures:
aria-expanded,aria-controlson menu triggers; panelidmatches - Current page/section:
aria-current="page"or"location"where accurate - Live feedback:
role="status" aria-live="polite"for form/async messages;aria-busy="true"on loading regions - Decorative:
aria-hidden="true"on icons; meaningful controls keep visible text oraria-label - Invalid fields: native
aria-invalid+ visible error text linked viaaria-describedby - Dialogs:
aria-labelledby→ dialog title; prefer native<dialog>focus behavior
Do not add redundant roles (role="navigation" on <nav>) or label with ARIA what visible text already provides.
Color contrast (WCAG 2.2 AA)
Fix at token layer (theme.css / design tokens), not one-off utilities.
| Pair | Target |
| Body text on surface | ≥ 4.5:1 |
| Large text (≥18px / 14px bold) | ≥ 3:1 |
| UI components & focus ring | ≥ 3:1 vs adjacent colors |
| Muted/meta copy | ≥ 4.5:1 if used for essential info; otherwise keep non-essential only |
Verify both theme variants (e.g. light + dim). Document adjusted token values in a short comment.
data-* state conventions
Expose UI state in HTML; style in CSS @layer components:
| Attribute | Values | Use |
data-section | section id slug | Anchor scroll-margin, section-scoped CSS |
data-state | open | closed | Menus, dialogs, panels |
data-status | idle | loading | error | success | Forms, async blocks |
data-card | project, credential, … | Card variants |
data-action | open, … | Card interaction (e.g. whole-card opens cert modal) |
data-grid | featured, catalog | Credentials grid layout |
data-align | center | Subsection heading alignment |
data-cta | icon | Compact icon-only credential CTA |
data-empty | (presence) | Date spacer when no completion date |
data-featured | true | Bento emphasis (boolean presence) |
React: set attributes from reducer/status enum; don't mirror the same state in redundant class toggles.
Example CSS (few lines, high leverage):
@layer components {
[data-section] { scroll-margin-top: var(--header-offset, 5rem); }
[data-state="closed"] { display: none; }
[data-status="loading"] { pointer-events: none; opacity: 0.7; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
}Tailwind vs modern CSS
| Concern | Prefer |
| Fixed header + anchor links | --header-offset + [data-section] { scroll-margin-top } |
| Card hover/focus ring | article:has(a:focus-visible), @media (hover: hover) |
| Themed hover on oklch/hsl tokens | color-mix(in oklch, var(--brand) 90%, black) as --brand-hover |
| Bento / responsive card areas | @container queries on section wrapper |
| Spacing, flex/grid, type scale | Tailwind utilities |
| Focus visible | focus-visible:outline / ring utilities + tokenized --ring |
Goal: many fixes = token tweak + 3–5 lines CSS, not 20 new classes per component.
Workflow (before editing TSX)
- [ ] Read target component + parent layout (landmarks, heading order)
- [ ] Grep for nested <main>, div-onClick, role="button", orphan tokens
- [ ] List states → map to data-* + native elements
- [ ] Contrast-check affected text/surface pairs in all themes
- [ ] Implement: semantics first, then CSS layer, then Tailwind layout
- [ ] Verify: keyboard tab order, Esc on dialog, lint/type-checkAnti-patterns (reject)
// ❌ Div button
<div role="button" tabIndex={0} onClick={…}>
// ✅
<button type="button" onClick={…}>
// ❌ State in classes only
<div className={isOpen ? "block" : "hidden"}>
// ✅
<nav data-state={isOpen ? "open" : "closed"} aria-expanded={isOpen}>
// ❌ Muted token for body copy (contrast fail)
<p className="text-text2">{longParagraph}</p>
// ✅ Body on text1; text2 for meta onlyDone when
- One
<main>; sections usearia-labelledby - Interactive controls are native
<button>/<a>/<dialog> - Stateful UI exposes
data-*(or nativeopenon<details>/<dialog>) - Contrast-sensitive pairs pass AA in all active themes
:has()/ scroll-margin / reduced-motion handled in CSS where applicable- No new div-only patterns where semantic elements suffice
Related
- Client state/fetch: react-client-expert
- Optional overlay: examples/overlays/nextjs-portfolio-marketing-css.md
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

