> ## Documentation Index
> Fetch the complete documentation index at: https://discountkit.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Styling & Data Attributes

> The data-* attributes, CSS styling tokens, CSS parts, and light-DOM classes for <dkl-volume-picker-radio-groups>

This is the shared reference for `<dkl-volume-picker-radio-groups>` — the `data-*` attributes
that drive its behaviour, the `--dkl-*` tokens that style it, and the CSS parts and light-DOM
classes you can target. The [app block](/components/volume-picker/app-block) settings map onto
these; on a [web component](/components/volume-picker/web-component) you set them directly.

<Note>
  **Using this reference with the app block**

  When you place the [**DK: Volume Groups** app block](/components/volume-picker/app-block), it
  renders its own `<dkl-volume-picker-radio-groups>` and writes these values for you — so what
  applies depends on the kind of override:

  **Data attributes - No:**
  The block sets every `data-*` itself, from its App block settings and the resolved discount. Adding `data-*` to your own markup has no effect on a block instance; they're the configuration surface for the [web component](/components/volume-picker/web-component) only. To change block behaviour, use its [settings](/components/volume-picker/app-block).

  **CSS styling tokens — Yes:**
  They're CSS custom properties that inherit through the shadow boundary, so they style a block exactly like a web component. The block's colour / radius / spacing pickers just write the matching setting-backed tokens into a scoped `<style>` rule for you. Any token **not** exposed as a setting (e.g. `--dkl-vp-legend-spacing`, `--dkl-vp-list-gap`) you can still set yourself from your own CSS — `:root`, the embed's **Custom CSS** field, or a rule targeting the block.

  **CSS parts and classes — Yes:**
  The shadow DOM and light-DOM markup are identical, so `::part()` and the `.dkl-volume-picker__*` classes work the same on a block or a web component.
</Note>

<Tip>
  **Token precedence.** A token the block writes from a chosen setting is scoped to the block's id (`#dkl-vp-   {block.id}`), which is more specific than a `:root` rule — so to override *that* token, either change the editor
  setting or match the specificity (target the block element). Tokens the block leaves unset fall back to your CSS or
  the built-in default as normal.
</Tip>

## Data attributes

Set as `data-*` on the host. On a web component the carrier supplies the data attributes; the
behaviour toggles default off.

<ParamField body="data-discount-id" type="metaobject handle" default="carrier (first eligible)">
  Which discount's carrier to clone. The `discount-` prefix is optional; an attribute-less
  tag uses the default (first eligible).
</ParamField>

<ParamField body="data-style" type="&#x22;cards&#x22; | &#x22;mini-buttons&#x22;" default="cards">
  Presentation: stacked cards, or a compact button grid (the per-tier price line is hidden).
</ParamField>

<ParamField body="data-money-format" type="string" default="carrier (shop.money_format)">
  Money format for JS-reformatted prices.
</ParamField>

<ParamField body="data-widget-id" type="string" default="null">
  Instance id; disambiguates multiple widgets.
</ParamField>

<ParamField body="data-update-price-on-change" type="&#x22;true&#x22; | &#x22;false&#x22;" default="false">
  Whether selecting a tier updates the displayed price — the theme's native price element and
  the [`<dkl-price>`](/components/price/overview) component (via the tier-change event's
  `updatesPrice` flag). When `false`, the event still fires for custom integrations, but no
  price display reflects the tier.
</ParamField>

<ParamField body="data-price-target" type="CSS selector | &#x22;none&#x22;" default="auto-detect">
  Override or disable the price element target. Use `"none"` when pairing with
  [`<dkl-price>`](/components/price/overview).
</ParamField>

<ParamField body="data-sync-with-quantity" type="&#x22;true&#x22; | &#x22;false&#x22;" default="false">
  Sync the theme's quantity selector to the selected tier's quantity.
</ParamField>

<ParamField body="data-quantity-target" type="CSS selector | &#x22;none&#x22;" default="auto-detect">
  Override or disable the quantity input target.
</ParamField>

<ParamField body="data-quantity-event" type="event name" default="(none)">
  An extra theme event to also drive quantity sync, on top of `quantity-selector:update`.
  The component reads the quantity from the event's `detail.quantity`, or re-reads the form
  input if absent.
</ParamField>

<ParamField body="data-exclude-sale-prices" type="&#x22;true&#x22; | &#x22;false&#x22;" default="carrier (the discount's excludeSale)">
  Disable tiers when the variant is already on sale.
</ParamField>

<ParamField body="data-price-unavailable-label" type="string" default="No discount available">
  Label shown when a tier is unavailable.
</ParamField>

<Info>
  **Sold-out variants disable the tiers** (on initial render and on variant change),
  independently of `data-exclude-sale-prices` — a selectable tier on a variant the form
  won't add would be a dead end.
</Info>

<Accordion title="Per-tier attributes (data-dkl-*)" icon="layer-group">
  Server-rendered onto each `input.dkl-volume-picker__radio`; the component reads them. You
  don't set these by hand — they're listed for reference.

  <ParamField body="data-dkl-tier-index" type="int">
    The tier's position in the group.
  </ParamField>

  <ParamField body="data-dkl-discount-type" type="&#x22;percentage&#x22; | &#x22;fixedAmount&#x22;">
    How the tier's discount is expressed.
  </ParamField>

  <ParamField body="data-dkl-discount-amount" type="number">
    The fixed discount amount (when `fixedAmount`).
  </ParamField>

  <ParamField body="data-dkl-discount-percent" type="number">
    The discount percent (when `percentage`).
  </ParamField>

  <ParamField body="data-dkl-unit-price-cents" type="int (cents)">
    The pre-computed discounted unit price.
  </ParamField>
</Accordion>

## CSS styling tokens

<Tabs>
  <Tab title="Layout: Cards">
    <Frame caption="CSS styling tokens for the DKL Volume Picker component - layout: cards">
      <img src="https://mintcdn.com/discountkit/qPmR0fAEpbjKUETr/images/components/dkl-volume-css-tokens.jpg?fit=max&auto=format&n=qPmR0fAEpbjKUETr&q=85&s=52493e9d18ff127b9a98eb2fe5ae55a1" alt="Image highlighting the CSS styling tokens for the DKL Volume Picker component" width="1600" height="1032" data-path="images/components/dkl-volume-css-tokens.jpg" />
    </Frame>
  </Tab>

  <Tab title="Layout: Mini-buttons">
    <Frame caption="CSS styling tokens for the DKL Volume Picker component - layout: mini-buttons">
      <img src="https://mintcdn.com/discountkit/qPmR0fAEpbjKUETr/images/components/dkl-volume-mini-css-tokens.jpg?fit=max&auto=format&n=qPmR0fAEpbjKUETr&q=85&s=86e536edc0d8eccf9d3c5c3188779528" alt="Image highlighting the CSS styling tokens for the DKL Volume Picker component" width="1600" height="1032" data-path="images/components/dkl-volume-mini-css-tokens.jpg" />
    </Frame>
  </Tab>
</Tabs>

Two layers: a shadow `<style>` for the title/list structure, and the light-DOM card chrome
in the stylesheet. The card chrome mostly consumes the
[global brand tokens](/components/overview#global-brand-tokens) so cards match the theme.

### Structure

<ParamField body="--dkl-vp-legend-spacing" default="0.75rem">
  Space below the title row.
</ParamField>

<ParamField body="--dkl-vp-title-font-weight" default="600">
  Group title font weight.
</ParamField>

<ParamField body="--dkl-vp-title-font-size" default="0.95rem">
  Group title font size.
</ParamField>

<ParamField body="--dkl-vp-title-color" default="inherit">
  Group title color.
</ParamField>

<ParamField body="--dkl-vp-list-gap" default="0.5rem">
  Gap between options.
</ParamField>

<ParamField body="--dkl-vp-count" default="tier count (max 3)">
  Mini-buttons grid columns.
</ParamField>

<ParamField body="--dkl-vp-mini-padding" default="0.375rem 1rem">
  Mini-buttons option padding.
</ParamField>

<ParamField body="--dkl-vp-selected-border-color" default="#000000">
  Border and ring of the **selected** tier.
</ParamField>

<ParamField body="--dkl-color-border" default="rgba(0,0,0,.12)">
  Resting card border.
</ParamField>

<ParamField body="--dkl-radius" default="8px">
  Card corners.
</ParamField>

<ParamField body="--dkl-color-background" default="#fff">
  Card background.
</ParamField>

<ParamField body="--dkl-color-background-soft" default="rgba(0,0,0,.04)">
  Hover background.
</ParamField>

<ParamField body="--dkl-color-accent" default="#217a4a">
  Focus-visible outline.
</ParamField>

## CSS parts and classes

The title/list scaffold is in shadow DOM (parts); the radio cards are slotted light DOM
(classes).

### Parts

<Tabs>
  <Tab title="Layout: Cards">
    <Frame caption="CSS parts for the DKL Volume Picker component - layout: cards">
      <img src="https://mintcdn.com/discountkit/qPmR0fAEpbjKUETr/images/components/dkl-volume-css-parts.jpg?fit=max&auto=format&n=qPmR0fAEpbjKUETr&q=85&s=577e2a32de7cce9d63778c27d23e2d64" alt="Image highlighting the CSS parts for the DKL Volume Picker component" width="1600" height="886" data-path="images/components/dkl-volume-css-parts.jpg" />
    </Frame>
  </Tab>

  <Tab title="Layout: Mini-buttons">
    <Frame caption="CSS parts for the DKL Volume Picker component - layout: mini-buttons">
      <img src="https://mintcdn.com/discountkit/qPmR0fAEpbjKUETr/images/components/dkl-volume-mini-css-parts.jpg?fit=max&auto=format&n=qPmR0fAEpbjKUETr&q=85&s=63816a7a7acfbddadced8e25c19af415" alt="Image highlighting the CSS parts for the DKL Volume Picker component - layout: mini-buttons" width="1600" height="886" data-path="images/components/dkl-volume-mini-css-parts.jpg" />
    </Frame>
  </Tab>
</Tabs>

<ParamField body="root" type="CSSPart">
  The `<fieldset>` wrapper.
</ParamField>

<ParamField body="legend-wrapper" type="CSSPart">
  The title row.
</ParamField>

<ParamField body="title" type="CSSPart">
  The `<legend>` group title.
</ParamField>

<ParamField body="list" type="CSSPart">
  The radiogroup holding the options.
</ParamField>

### Light-DOM classes

<ParamField body=".dkl-volume-picker__option" type="class">
  One tier card (selected: `:has(.dkl-volume-picker__radio:checked)`).
</ParamField>

<ParamField body=".dkl-volume-picker__radio" type="class">
  The radio input.
</ParamField>

<ParamField body=".dkl-volume-picker__content" type="class">
  Card inner row.
</ParamField>

<ParamField body=".dkl-volume-picker__header" type="class">
  Title + discount stack.
</ParamField>

<ParamField body=".dkl-volume-picker__title" type="class">
  Tier heading (e.g. "Buy 3+").
</ParamField>

<ParamField body=".dkl-volume-picker__discount" type="class">
  The "X% off each" line.
</ParamField>

<ParamField body=".dkl-volume-picker__price" type="class">
  Per-tier price.
</ParamField>

<ParamField body=".dkl-volume-picker__price-unit" type="class">
  The unit suffix (e.g. "/ea").
</ParamField>

<ParamField body=".dkl-volume-picker__price-unavailable" type="class">
  "No discount" placeholder.
</ParamField>

## Examples

```css Recolour the selected card border theme={null}
:root {
  --dkl-vp-selected-border-color: #2563eb;
}
```

```css Tighter list, bolder titles theme={null}
:root {
  --dkl-vp-list-gap: 0.25rem;
  --dkl-vp-title-font-weight: 700;
}
```

```html Compact button layout theme={null}
<dkl-volume-picker-radio-groups
  data-style="mini-buttons"
  style="--dkl-vp-mini-padding: 0.25rem 0.75rem;"
></dkl-volume-picker-radio-groups>
```

## Next steps

<CardGroup cols={2}>
  <Card title="App block" icon="puzzle-piece" href="/components/volume-picker/app-block">
    Configure these via theme-editor settings.
  </Card>

  <Card title="Web Components" icon="code" href="/components/volume-picker/web-component">
    Set these directly on the tag.
  </Card>
</CardGroup>
