Claude-skill-registry data-attributes
Using data-* attributes as the HTML/CSS/JS bridge for state, variants, and configuration. Use when managing element state, styling variants, or configuring behavior without JavaScript classes.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/data-attributes" ~/.claude/skills/majiayu000-claude-skill-registry-data-attributes && rm -rf "$T"
skills/data/data-attributes/SKILL.mdData Attributes Skill
This skill covers the use of
data-* attributes as the preferred mechanism for state management, variant styling, and configuration in HTML-first development.
Philosophy
Data attributes replace classes for dynamic concerns. While semantic elements and custom elements handle structure,
data-* attributes handle:
- State (
,data-expanded
,data-loading
)data-valid - Variants (
,data-type
,data-variant
)data-topic - Configuration (
,data-columns
,data-size
)data-animation
This creates a clean HTML/CSS/JS bridge where markup declares intent, CSS responds to it, and JavaScript (when needed) manipulates data attributes rather than class lists.
Why Data Attributes Over Classes?
| Aspect | Classes | Data Attributes |
|---|---|---|
| Semantics | Presentation-focused | Meaning-focused |
| State | , | |
| Variants | , | |
| JS Access | | |
| Validation | Cannot validate values | Can define allowed values |
| Readability | Class soup | Self-documenting |
| CSS Selectors | | |
The Bridge Pattern
HTML: <element data-state="value"> → Declares state/config CSS: [data-state="value"] { } → Styles based on state JS: element.dataset.state = "new" → Updates state (if needed)
This separation means:
- HTML declares what the element is
- CSS defines how states look
- JavaScript only changes data attributes, not classes
Categories of Data Attributes
1. State Attributes
Track the current state of an element:
<!-- Expanded/collapsed --> <nav data-expanded="false">...</nav> <!-- Loading states --> <button data-state="idle">Submit</button> <button data-state="loading">Submitting...</button> <button data-state="success">Sent!</button> <button data-state="error">Failed</button> <!-- Form validation --> <form-field data-valid>...</form-field> <form-field data-invalid>...</form-field> <!-- Visibility --> <modal-dialog data-open>...</modal-dialog>
2. Variant Attributes
Define visual or behavioral variants:
<!-- Type/category --> <status-badge data-type="success">Active</status-badge> <status-badge data-type="warning">Pending</status-badge> <status-badge data-type="error">Failed</status-badge> <!-- Topic/tag styling --> <tag-topic data-topic="css">CSS</tag-topic> <tag-topic data-topic="html">HTML</tag-topic> <tag-topic data-topic="a11y">Accessibility</tag-topic> <!-- Size variants --> <user-avatar data-size="small" src="..." alt="..."/> <user-avatar data-size="medium" src="..." alt="..."/> <user-avatar data-size="large" src="..." alt="..."/>
3. Configuration Attributes
Configure component behavior or layout:
<!-- Grid configuration --> <gallery-grid data-columns="3" data-gap="md">...</gallery-grid> <!-- Animation settings --> <carousel data-autoplay data-interval="5000">...</carousel> <!-- Sort/filter settings --> <data-table data-sortable data-sort-column="date">...</data-table> <!-- Menu orientation --> <nav-menu data-orientation="horizontal">...</nav-menu> <nav-menu data-orientation="vertical">...</nav-menu>
CSS Selectors for Data Attributes
Attribute Presence (Boolean)
/* Element has data-featured (any value or no value) */ article[data-featured] { border-left: 4px solid var(--primary-color); } /* Element has data-required */ form-field[data-required] label::after { content: " *"; color: var(--error-color); }
Exact Value Match
/* Exact match */ nav[data-expanded="true"] { max-height: 500px; } nav[data-expanded="false"] { max-height: 0; overflow: hidden; }
Multiple Values
/* Different states */ button[data-state="loading"] { opacity: 0.6; pointer-events: none; } button[data-state="success"] { background-color: var(--success-color); } button[data-state="error"] { background-color: var(--error-color); }
Partial Match Selectors
/* Contains (anywhere in value) */ [data-tags*="featured"] { } /* Starts with */ [data-category^="blog"] { } /* Ends with */ [data-file$=".pdf"] { } /* Space-separated word */ [data-tags~="important"] { }
Common Patterns
Expandable Navigation
<header> <input type="checkbox" id="nav-toggle" hidden/> <label for="nav-toggle" data-nav-trigger>Menu</label> <nav data-mobile-nav> <ul>...</ul> </nav> </header>
nav[data-mobile-nav] { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } #nav-toggle:checked ~ nav[data-mobile-nav] { max-height: 500px; }
Theme Variants
<article data-theme="light">...</article> <article data-theme="dark">...</article>
article[data-theme="light"] { --bg: white; --text: #1f2937; } article[data-theme="dark"] { --bg: #1f2937; --text: white; }
Loading Button
<button type="submit" data-state="idle"> <span data-label>Submit</span> <span data-loader hidden>Loading...</span> </button>
button[data-state="loading"] { pointer-events: none; opacity: 0.7; & [data-label] { display: none; } & [data-loader] { display: inline; } }
Tag/Topic Styling
<tag-list> <tag-topic data-topic="css">CSS</tag-topic> <tag-topic data-topic="html">HTML</tag-topic> <tag-topic data-topic="js">JavaScript</tag-topic> <tag-topic data-topic="a11y">Accessibility</tag-topic> </tag-list>
tag-topic { padding: 0.25rem 0.75rem; border-radius: 1rem; font-size: 0.875rem; } tag-topic[data-topic="css"] { background: #dbeafe; color: #1e40af; } tag-topic[data-topic="html"] { background: #fee2e2; color: #991b1b; } tag-topic[data-topic="js"] { background: #fef3c7; color: #92400e; } tag-topic[data-topic="a11y"] { background: #d1fae5; color: #065f46; }
Grid Configuration
<gallery-grid data-columns="2">...</gallery-grid> <gallery-grid data-columns="3">...</gallery-grid> <gallery-grid data-columns="4">...</gallery-grid>
gallery-grid { display: grid; gap: var(--spacing-md); } gallery-grid[data-columns="2"] { grid-template-columns: repeat(2, 1fr); } gallery-grid[data-columns="3"] { grid-template-columns: repeat(3, 1fr); } gallery-grid[data-columns="4"] { grid-template-columns: repeat(4, 1fr); }
JavaScript Integration
When JavaScript is needed, use the
dataset API:
Reading Data Attributes
const nav = document.querySelector('nav'); // Read attribute const isExpanded = nav.dataset.expanded === 'true'; // Check presence (boolean attributes) const isFeatured = nav.hasAttribute('data-featured');
Setting Data Attributes
// Set value nav.dataset.expanded = 'true'; // Toggle boolean if (nav.hasAttribute('data-featured')) { nav.removeAttribute('data-featured'); } else { nav.setAttribute('data-featured', ''); } // State machine pattern button.dataset.state = 'loading'; // After async operation button.dataset.state = 'success';
Event Delegation
document.addEventListener('click', (event) => { const trigger = event.target.closest('[data-action]'); if (!trigger) return; const action = trigger.dataset.action; // Handle action });
Validation in elements.json
Define allowed data attributes and their values:
{ "status-badge": { "flow": true, "phrasing": true, "permittedContent": ["@phrasing"], "attributes": { "data-type": { "required": false, "enum": ["success", "warning", "error", "info"] } } }, "gallery-grid": { "flow": true, "permittedContent": ["@flow"], "attributes": { "data-columns": { "required": false, "enum": ["2", "3", "4"] }, "data-gap": { "required": false, "enum": ["sm", "md", "lg"] } } } }
Naming Conventions
State Attributes
| Pattern | Examples |
|---|---|
| , |
| , , |
| Boolean presence | , , |
Variant Attributes
| Pattern | Examples |
|---|---|
| , |
| , |
| , |
Configuration Attributes
| Pattern | Examples |
|---|---|
| , |
| , |
Checklist
When using data attributes:
- Use
for state, not classesdata-* - Use boolean attributes (presence/absence) for true/false states
- Use value attributes for multiple states or variants
- Define allowed values in
where possibleelements.json - Use consistent naming patterns across the project
- Prefer
for multi-state componentsdata-state - Use
API in JavaScript, notdatasetgetAttribute - Document attribute purposes in component skills
Related Skills
- custom-elements - Define and use custom HTML elements
- javascript-author - Write vanilla JavaScript for Web Components with function...
- css-author - Modern CSS organization with native @import, @layer casca...
- progressive-enhancement - HTML-first development with CSS-only interactivity patterns