Documentation
Feedback
Guides
Storefront Development

Storefront Development
Storefront development

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:

_10
data-fs-{component-name}
_10
data-fs-{component-name}-{variant}
_10
data-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 component
  • data-fs-button-variant="primary" - Targets primary variant buttons
  • data-fs-product-card - Targets the ProductCard component
  • data-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.
ComponentData attributeDescription
Buttondata-fs-buttonMain button element
Buttondata-fs-button-variant="primary | secondary | tertiary"Button variant
Buttondata-fs-button-size="small | regular"Button size
Buttondata-fs-button-inverseInverse color scheme
Buttondata-fs-button-loading="true"Loading state
Inputdata-fs-inputMain input element
Badgedata-fs-badgeMain badge element
Badgedata-fs-badge-variant="highlighted | warning"Badge variant
Badgedata-fs-badge-size="big | small"Badge size
Icondata-fs-iconMain icon element

Molecules

For the complete data attributes list, see the component reference for ProductCard, Table, and Modal.
ComponentData attributeDescription
ProductCarddata-fs-product-cardMain card container
ProductCarddata-fs-product-card-variant="default | wide"Card variant
ProductCarddata-fs-product-card-bordered="true"Bordered variant
ProductCarddata-fs-product-card-imageProduct image
ProductCarddata-fs-product-card-contentCard content area
ProductCarddata-fs-product-card-titleProduct title
ProductCarddata-fs-product-card-pricesPrice section
ProductCarddata-fs-product-card-actionsAction buttons area
Tabledata-fs-tableMain table element
Tabledata-fs-table-variant="colored | bordered"Table variant
Tabledata-fs-table-headTable header
Tabledata-fs-table-bodyTable body
Tabledata-fs-table-rowTable row
Tabledata-fs-table-cell="head | data"Table cell type
Modaldata-fs-modalMain modal element
Modaldata-fs-modal-overlayModal overlay
Modaldata-fs-modal-contentModal content area
Modaldata-fs-modal-headerModal header
Modaldata-fs-modal-bodyModal body

Organisms

For the complete data attributes list, see the component reference for Navbar.
ComponentData attributeDescription
Tilesdata-fs-tilesMain tiles container
Tilesdata-fs-tiles-variant="expanded-first | expanded-first-two"Layout variant
Tilesdata-fs-tileIndividual tile element
Tilesdata-fs-content="tiles"Content identifier
Navbardata-fs-navbarMain navbar element
Navbardata-fs-navbar-brandBrand/logo area
Navbardata-fs-navbar-linksNavigation links
Navbardata-fs-navbar-actionsAction 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
_10
document.documentElement.setAttribute('data-theme', 'dark');
_10
_10
// Switch back to default
_10
document.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:
  1. color: transparent hides the original button text.
  2. pointer-events: none prevents interaction during loading.
  3. The ::after pseudo-element creates a spinning circle.
  4. 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
_10
cy.get('[data-fs-button-variant="primary"]').click();
_10
_10
// ❌ Avoid - uses classes that might change
_10
cy.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
_10
document.querySelectorAll('[data-fs-]');
_10
_10
// Find specific component
_10
document.querySelectorAll('[data-fs-button]');
_10
_10
// Find specific variant
_10
document.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
_10
document.querySelector('[data-fs-button-variant="primary"]');
_10
_10
// Count matching elements
_10
document.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
_10
const button = screen.getByTestId('store-button');
_10
const productCard = screen.getByTestId('store-product-card');
_10
_10
// Cypress examples
_10
cy.get('[data-fs-button]').click();
_10
cy.get('[data-fs-product-card]').should('be.visible');
_10
cy.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>

Contributors
2
Photo of the contributor
Photo of the contributor
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
2
Photo of the contributor
Photo of the contributor
Was this helpful?
Suggest edits (GitHub)
On this page