Using data attributes with FastStore UI
Learn how to use data attributes to customize and style FastStore UI components.
Data attributes in the FastStore UI allow you to target and customize component styles with CSS. All FastStore UI components use a consistent
data-fs- prefix for their data attributes, making it easy to identify and style components.What are data attributes?
Data attributes are HTML attributes that start with
data- and allow you to store custom data on HTML elements. FastStore UI uses these attributes to:- Target components for styling - Apply custom CSS to specific components
- Handle component variants - Style different states and variations
- Enable theme customization - Override default component styles
- Support responsive design - Apply different styles based on component properties
FastStore UI data attribute convention
All FastStore UI components follow a consistent naming pattern:
_10data-fs-{component-name}_10data-fs-{component-name}-{variant}_10data-fs-{component-name}-{property}
Naming convention examples
The following data attributes illustrate how the
data-fs- naming pattern maps to components and their variants:data-fs-button- Targets the Button componentdata-fs-button-variant="primary"- Targets primary variant buttonsdata-fs-product-card- Targets the ProductCard componentdata-fs-product-card-image- Targets the image within a ProductCard
How to use data attributes
Basic component targeting
To style a specific component, use its main data attribute:
_11// Target all Button components_11[data-fs-button] {_11 border-radius: var(--fs-border-radius);_11 font-weight: var(--fs-text-weight-bold);_11}_11_11// Target all Input components_11[data-fs-input] {_11 border: var(--fs-border-width) solid var(--fs-border-color);_11 padding: var(--fs-spacing-2);_11}
Component variants
Many components support variants that you can target with specific data attributes:
_18// Target primary buttons_18[data-fs-button-variant="primary"] {_18 background-color: var(--fs-color-primary-bkg);_18 color: var(--fs-color-primary-text);_18}_18_18// Target secondary buttons_18[data-fs-button-variant="secondary"] {_18 background-color: var(--fs-color-secondary-bkg);_18 border: var(--fs-border-width) solid var(--fs-color-secondary-bkg-active);_18 color: var(--fs-color-secondary-text);_18}_18_18// Target small buttons_18[data-fs-button-size="small"] {_18 padding: var(--fs-spacing-1) var(--fs-spacing-3);_18 font-size: var(--fs-text-size-1);_18}
Component states
Target different states of components:
_11// Target loading buttons_11[data-fs-button-loading="true"] {_11 opacity: var(--fs-opacity-disabled);_11 cursor: not-allowed;_11}_11_11// Target disabled inputs_11[data-fs-input]:disabled {_11 background-color: var(--fs-color-disabled-bkg);_11 color: var(--fs-color-disabled-text);_11}
Nested elements
To better understand how to target nested elements, this example shows the typical structure of a ProductCard component:
_19<ProductCard>_19 <ProductCardImage>_19 <img_19 data-fs-image_19 src={product.image[1].url}_19 alt={product.image[1].alternateName}_19 />_19 </ProductCardImage>_19 <ProductCardContent_19 title={product.isVariantOf.name}_19 price={{_19 value: product.offers.offers[0].price,_19 listPrice: product.offers.offers[0].listPrice,_19 formatter: useFormattedPrice,_19 }}_19 ratingValue={3.5}_19 onButtonClick={() => {}}_19 />_19</ProductCard>
Understanding this structure helps you target specific parts of the component with data attributes:
_17// Target the image within ProductCard_17[data-fs-product-card-image] {_17 border-radius: var(--fs-border-radius);_17 object-fit: cover;_17}_17_17// Target the content area of ProductCard_17[data-fs-product-card-content] {_17 padding: var(--fs-spacing-3);_17}_17_17// Target the title within ProductCard_17[data-fs-product-card-title] {_17 font-size: var(--fs-text-size-3);_17 font-weight: var(--fs-text-weight-bold);_17 margin-bottom: var(--fs-spacing-1);_17}
Common data attributes by component type
The following tables list commonly used data attributes grouped by component type.
Atoms
For the complete data attributes list, see the component reference for Button, Input, Badge, and Icon.
| Component | Data attribute | Description |
|---|---|---|
| Button | data-fs-button | Main button element |
| Button | data-fs-button-variant="primary | secondary | tertiary" | Button variant |
| Button | data-fs-button-size="small | regular" | Button size |
| Button | data-fs-button-inverse | Inverse color scheme |
| Button | data-fs-button-loading="true" | Loading state |
| Input | data-fs-input | Main input element |
| Badge | data-fs-badge | Main badge element |
| Badge | data-fs-badge-variant="highlighted | warning" | Badge variant |
| Badge | data-fs-badge-size="big | small" | Badge size |
| Icon | data-fs-icon | Main icon element |
Molecules
For the complete data attributes list, see the component reference for ProductCard, Table, and Modal.
| Component | Data attribute | Description |
|---|---|---|
| ProductCard | data-fs-product-card | Main card container |
| ProductCard | data-fs-product-card-variant="default | wide" | Card variant |
| ProductCard | data-fs-product-card-bordered="true" | Bordered variant |
| ProductCard | data-fs-product-card-image | Product image |
| ProductCard | data-fs-product-card-content | Card content area |
| ProductCard | data-fs-product-card-title | Product title |
| ProductCard | data-fs-product-card-prices | Price section |
| ProductCard | data-fs-product-card-actions | Action buttons area |
| Table | data-fs-table | Main table element |
| Table | data-fs-table-variant="colored | bordered" | Table variant |
| Table | data-fs-table-head | Table header |
| Table | data-fs-table-body | Table body |
| Table | data-fs-table-row | Table row |
| Table | data-fs-table-cell="head | data" | Table cell type |
| Modal | data-fs-modal | Main modal element |
| Modal | data-fs-modal-overlay | Modal overlay |
| Modal | data-fs-modal-content | Modal content area |
| Modal | data-fs-modal-header | Modal header |
| Modal | data-fs-modal-body | Modal body |
Organisms
For the complete data attributes list, see the component reference for Navbar.
| Component | Data attribute | Description |
|---|---|---|
| Tiles | data-fs-tiles | Main tiles container |
| Tiles | data-fs-tiles-variant="expanded-first | expanded-first-two" | Layout variant |
| Tiles | data-fs-tile | Individual tile element |
| Tiles | data-fs-content="tiles" | Content identifier |
| Navbar | data-fs-navbar | Main navbar element |
| Navbar | data-fs-navbar-brand | Brand/logo area |
| Navbar | data-fs-navbar-links | Navigation links |
| Navbar | data-fs-navbar-actions | Action buttons area |
Advanced usage patterns
Combining multiple attributes
You can combine multiple data attributes for more specific targeting:
_11// Target only primary small buttons_11[data-fs-button-variant="primary"][data-fs-button-size="small"] {_11 background-color: var(--fs-color-primary-bkg-active);_11 padding: var(--fs-spacing-1) var(--fs-spacing-2);_11}_11_11// Target product cards with bordered variant_11[data-fs-product-card][data-fs-product-card-bordered="true"] {_11 border: var(--fs-border-width) solid var(--fs-border-color-light);_11 box-shadow: var(--fs-shadow-default);_11}
Responsive design
Use data attributes with media queries for responsive styling:
_14// Mobile-first approach_14[data-fs-product-card] {_14 width: 100%;_14 margin-bottom: var(--fs-spacing-3);_14 _14 @media (min-width: 768px) {_14 width: calc(50% - var(--fs-spacing-2));_14 display: inline-block;_14 }_14 _14 @media (min-width: 1024px) {_14 width: calc(33.333% - var(--fs-spacing-3));_14 }_14}
Theme customization
The recommended way to customize themes in FastStore is by overriding design tokens. FastStore provides both global tokens and component-specific tokens that you should use instead of hardcoded values.
Using component tokens
Override component-specific tokens for consistent theming:
_15// Customize ProductCard appearance using tokens_15[data-fs-product-card] {_15 --fs-product-card-border-color: transparent;_15 --fs-product-card-border-color-hover: var(--fs-border-color-light);_15 _15 &[data-fs-product-card-bordered='true'] {_15 --fs-product-card-border-color: var(--fs-border-color-light);_15 }_15}_15_15// Customize Button appearance using tokens_15[data-fs-button] {_15 --fs-button-border-radius: var(--fs-border-radius-medium);_15 --fs-button-padding: var(--fs-spacing-2) var(--fs-spacing-4);_15}
Creating theme variations
Theme variations work by adding a
data-theme attribute to a root element — typically \<html> or a top-level wrapper. Because CSS custom properties cascade, any FastStore UI component nested inside that element automatically inherits the overridden tokens, with no class changes needed on individual components.To apply a theme, set the
data-theme attribute on the root element:
_10<!-- Apply dark theme globally -->_10<html data-theme="dark">
Alternatively, you can toggle it programmatically in a React component:
_10// Switch to dark theme_10document.documentElement.setAttribute('data-theme', 'dark');_10_10// Switch back to default_10document.documentElement.removeAttribute('data-theme');
Then, in your stylesheet, define component token overrides scoped to that
data-theme value. Every FastStore UI component inside the root element will use the overridden tokens automatically:
_23// Dark theme using design tokens_23[data-theme="dark"] {_23 [data-fs-button-variant="primary"] {_23 --fs-button-primary-bkg-color: var(--fs-color-primary-bkg-dark);_23 --fs-button-primary-text-color: var(--fs-color-primary-text-dark);_23 }_23 _23 [data-fs-input] {_23 --fs-input-bkg-color: var(--fs-color-body-bkg-dark);_23 --fs-input-text-color: var(--fs-color-text-dark);_23 --fs-input-border-color: var(--fs-border-color-dark);_23 }_23}_23_23// High contrast theme using design tokens_23[data-theme="high-contrast"] {_23 [data-fs-button-variant="primary"] {_23 --fs-button-primary-bkg-color: var(--fs-color-black);_23 --fs-button-primary-text-color: var(--fs-color-white);_23 --fs-button-border-width: var(--fs-border-width-thick);_23 --fs-button-border-color: var(--fs-color-white);_23 }_23}
Always use design tokens instead of hardcoded values. This ensures consistency across your theme and makes it easier to maintain and update your styles. Learn more about available tokens in the Design tokens documentation.
Component state management
Data attributes can be used to manage and style different component states. Here's an example of creating a loading indicator for buttons using data attributes and CSS:
_25// Style a button in loading state_25[data-fs-button][data-fs-button-loading="true"] {_25 position: relative;_25 color: transparent; // Hide button text during loading_25 pointer-events: none; // Prevent clicks during loading_25 _25 // Create a spinning loader indicator_25 &::after {_25 content: '';_25 position: absolute;_25 top: 50%;_25 left: 50%;_25 width: var(--fs-spacing-3);_25 height: var(--fs-spacing-3);_25 margin: calc(var(--fs-spacing-3) / -2) 0 0 calc(var(--fs-spacing-3) / -2);_25 border: var(--fs-border-width) solid currentColor;_25 border-radius: var(--fs-border-radius-pill);_25 border-top-color: transparent;_25 animation: spin 1s linear infinite;_25 }_25}_25_25@keyframes spin {_25 to { transform: rotate(360deg); }_25}
How it works:
color: transparenthides the original button text.pointer-events: noneprevents interaction during loading.- The
::afterpseudo-element creates a spinning circle. - The animation rotates the circle continuously.
Usage in component:
_10<Button data-fs-button-loading="true">_10 Loading..._10</Button>
Best practices for styling with data attributes
Follow these guidelines to write maintainable, consistent, and accessible styles when working with FastStore UI data attributes.
Use design tokens
Override component styles using design tokens (CSS custom properties) rather than hardcoded values. This keeps styles consistent across the design system and makes future updates easier.
_11// ✅ Good - uses design tokens_11[data-fs-button] {_11 --fs-button-primary-bkg-color: var(--fs-color-accent);_11 --fs-button-border-radius: var(--fs-border-radius-medium);_11}_11_11// ❌ Avoid - hardcoded values_11[data-fs-button] {_11 background-color: #ff6b6b;_11 border-radius: 8px;_11}
Use semantic data attributes
Always use the built-in
data-fs- attributes provided by FastStore UI rather than creating your own. Avoid modifying or replacing the existing attributes.
_10// ✅ Good_10<button data-fs-button data-fs-button-variant="primary">Click me</button>_10_10// ❌ Avoid_10<button data-custom-button data-custom-variant="primary">Click me</button>
Maintain naming consistency
Follow the established
data-fs- naming pattern when extending components. Mixing conventions makes selectors harder to maintain.
_10// ✅ Good - follows FastStore pattern_10<div data-fs-custom-component data-fs-custom-component-variant="special">_10_10// ❌ Avoid - inconsistent naming_10<div data-fs-custom-component data-custom-variant="special">
Use boolean attributes correctly
For boolean data attributes, always use string values (
"true" / "false"). Omitting the value or passing a JavaScript boolean can lead to unexpected selector behavior.
_10// ✅ Good_10<button data-fs-button-disabled="true">Disabled Button</button>_10<button data-fs-button-loading="false">Normal Button</button>_10_10// ❌ Avoid_10<button data-fs-button-disabled>Disabled Button</button>_10<button data-fs-button-loading={false}>Normal Button</button>
Combine attributes for precise targeting
Use multiple data attributes together to target only the exact component state you need, avoiding unintended side effects on other variants.
_10// Target only primary small buttons_10[data-fs-button-variant="primary"][data-fs-button-size="small"] {_10 --fs-button-padding: var(--fs-spacing-1) var(--fs-spacing-2);_10}_10_10// Target bordered ProductCards on hover only_10[data-fs-product-card][data-fs-product-card-bordered="true"]:hover {_10 --fs-product-card-shadow: var(--fs-shadow-hover);_10}
Test with data attributes
Use data attributes as test selectors instead of class names, which may change between releases.
_10// ✅ Good - uses data attributes_10cy.get('[data-fs-button-variant="primary"]').click();_10_10// ❌ Avoid - uses classes that might change_10cy.get('.btn-primary').click();
Things to avoid
- Don't use generic selectors - Overly broad selectors may affect unintended components.
- Don't ignore component variants - Account for all component states when writing styles.
- Don't break accessibility - Make your custom styles maintain each component's accessibility.
- Don't forget to document your customizations - Keep track of the token overrides and custom data attributes you introduce.
Debugging data attributes
Inspect elements
Use browser developer tools to inspect data attributes:
_10// Find all elements with FastStore UI data attributes_10document.querySelectorAll('[data-fs-]');_10_10// Find specific component_10document.querySelectorAll('[data-fs-button]');_10_10// Find specific variant_10document.querySelectorAll('[data-fs-button-variant="primary"]');
CSS debugging
Add temporary styles to visualize data attributes:
_10// Highlight all FastStore UI components_10[data-fs-] {_10 outline: var(--fs-border-width) solid var(--fs-color-danger-bkg) !important;_10}_10_10// Highlight specific components_10[data-fs-button] {_10 outline: var(--fs-border-width) solid var(--fs-color-info-bkg) !important;_10}
Console testing
Test data attribute selectors in the browser console:
_10// Test if selector works_10document.querySelector('[data-fs-button-variant="primary"]');_10_10// Count matching elements_10document.querySelectorAll('[data-fs-product-card]').length;
Customization examples
The following examples show how to override component tokens to customize the appearance of FastStore UI components while keeping styles consistent with the design system.
Custom button styling
_12// Custom primary button with design tokens_12[data-fs-button-variant="primary"] {_12 --fs-button-primary-bkg-color: var(--fs-color-primary-bkg);_12 --fs-button-primary-bkg-color-hover: var(--fs-color-primary-bkg-hover);_12 --fs-button-shadow: var(--fs-shadow-hover);_12 --fs-button-transition-timing: var(--fs-transition-timing);_12 --fs-button-transition-property: var(--fs-transition-property);_12 _12 &:hover {_12 transform: translateY(calc(-1 * var(--fs-spacing-1)));_12 }_12}
Custom ProductCard layout
_26// Custom ProductCard with design tokens_26[data-fs-product-card] {_26 --fs-product-card-padding: var(--fs-spacing-3);_26 --fs-product-card-border-radius: var(--fs-border-radius-medium);_26 --fs-product-card-bkg-color: var(--fs-color-neutral-bkg);_26 --fs-product-card-shadow: var(--fs-shadow-default);_26 --fs-product-card-shadow-hover: var(--fs-shadow-hover);_26 _26 transition: box-shadow var(--fs-transition-timing);_26 _26 &:hover {_26 --fs-product-card-shadow: var(--fs-shadow-hover);_26 }_26 _26 [data-fs-product-card-image] {_26 --fs-product-card-img-radius: var(--fs-border-radius);_26 --fs-product-card-img-aspect-ratio: 1;_26 }_26 _26 [data-fs-product-card-title] {_26 --fs-product-card-title-size: var(--fs-text-size-3);_26 --fs-product-card-title-weight: var(--fs-text-weight-bold);_26 --fs-product-card-title-color: var(--fs-color-text);_26 --fs-product-card-title-margin-bottom: var(--fs-spacing-1);_26 }_26}
Responsive table styling
_23// Responsive table with horizontal scroll on mobile_23[data-fs-table] {_23 width: 100%;_23 border-collapse: collapse;_23 _23 @media (max-width: 768px) {_23 display: block;_23 overflow-x: auto;_23 white-space: nowrap;_23 }_23}_23_23[data-fs-table-cell="head"] {_23 background-color: var(--fs-color-neutral-bkg);_23 font-weight: var(--fs-text-weight-bold);_23 padding: var(--fs-spacing-2);_23 text-align: left;_23}_23_23[data-fs-table-cell="data"] {_23 padding: var(--fs-spacing-2);_23 border-bottom: var(--fs-border-width) solid var(--fs-border-color-light);_23}
Testing with data attributes
Test selectors
Use data attributes for reliable test selectors:
_10// Jest/Testing Library examples_10const button = screen.getByTestId('store-button');_10const productCard = screen.getByTestId('store-product-card');_10_10// Cypress examples_10cy.get('[data-fs-button]').click();_10cy.get('[data-fs-product-card]').should('be.visible');_10cy.get('[data-fs-button-variant="primary"]').should('have.class', 'active');
Test ID pattern
FastStore UI components also include
data-testid attributes:
_10<button_10 data-fs-button_10 data-testid="store-button"_10 data-fs-button-variant="primary"_10>_10 Click me_10</button>