---
title: Migrate StyleHelper to container queries
description: >-
  Learn how to replace the StyleHelper utility with container queries in
  checkout and customer account UI extensions.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/checkout/migrate-to-web-components/style-helper
  md: >-
    https://shopify.dev/docs/apps/build/checkout/migrate-to-web-components/style-helper.md
---

# Migrate StyleHelper to container queries

The `Style` helper was a React utility for authoring conditional styles based on viewport size, hover, and focus states. In Polaris web components, responsive values use native container queries instead. Wrap your content in [`<s-query-container>`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/layout-and-structure/query-container) and use `@container` syntax directly in property values.

***

## How container queries work

Container queries respond to the width of a parent container rather than the viewport. This makes components more reusable across different layout contexts (main content, sidebar, modals).

To use responsive values:

1. Wrap content in `<s-query-container>`
2. Use `@container (inline-size > Npx) valueWhenTrue, valueWhenFalse` syntax in any property that supports responsive values
3. The first value applies when the condition is true (container is wider than the threshold)
4. The second value (after the comma) applies when the condition is false (container is narrower)

***

## Migrating viewport breakpoints

The previous `Style` helper used named viewport breakpoints (`extraSmall`, `small`, `medium`, `large`). Container queries don't have named breakpoints — you specify pixel values based on the parent container's width instead. Since container queries respond to the container, not the viewport, there's no direct mapping. Choose breakpoint values based on where your extension renders (for example, a block is narrower than the full viewport).

***

## Responsive layout

## Migrating responsive grid columns

##### Latest (Preact)

```tsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-query-container>
      <s-grid
        gridTemplateColumns="@container (inline-size > 600px) '30% 70%', 1fr"
        gap="base"
      >
        <s-text>Sidebar</s-text>
        <s-text>Main content</s-text>
      </s-grid>
    </s-query-container>
  );
}
```

##### Pre-Polaris (2025-07)

```tsx
import {
  reactExtension,
  Grid,
  Text,
  Style,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <Grid
      columns={Style.default('fill')
        .when({viewportInlineSize: {min: 'small'}}, ['30%', '70%'])}
      spacing="base"
    >
      <Text>Sidebar</Text>
      <Text>Main content</Text>
    </Grid>
  );
}
```

***

## Responsive spacing

## Migrating responsive padding

##### Latest (Preact)

```tsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-query-container>
      <s-box
        padding="@container (inline-size > 450px) none, large-100"
        background="subdued"
      >
        <s-text>Content with responsive padding</s-text>
      </s-box>
    </s-query-container>
  );
}
```

##### Pre-Polaris (2025-07)

```tsx
import {
  reactExtension,
  View,
  Text,
  Style,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <View
      padding={Style.default('base')
        .when({viewportInlineSize: {min: 'small'}}, 'large')}
      background="subdued"
    >
      <Text>Content with responsive padding</Text>
    </View>
  );
}
```

***

## Conditionally hiding content

## Migrating conditional display

##### Latest (Preact)

```tsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-query-container>
      <s-box display="@container (inline-size > 450px) none, auto">
        <s-text>Only visible on small containers</s-text>
      </s-box>
    </s-query-container>
  );
}
```

##### Pre-Polaris (2025-07)

```tsx
import {
  reactExtension,
  View,
  Text,
  Style,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <View
      display={Style.default('auto')
        .when({viewportInlineSize: {min: 'small'}}, 'none')}
    >
      <Text>Only visible on small viewports</Text>
    </View>
  );
}
```

***

## Advanced patterns

### Named containers

Use `containerName` to target a specific ancestor container when nesting multiple query containers.

```tsx
<s-query-container containerName="outer">
  <s-section>
    <s-query-container>
      <s-box padding="@container outer (inline-size > 450px) large-100, none">
        References the "outer" container specifically
      </s-box>
    </s-query-container>
  </s-section>
</s-query-container>
```

### Range conditions

Query a range of container sizes using compound conditions.

```tsx
<s-query-container>
  <s-box
    padding="@container (300px < inline-size < 500px) large-100, none"
    border="base"
    background="subdued"
  >
    <s-text>Padding only applies when container is between 300px and 500px</s-text>
  </s-box>
</s-query-container>
```

### Nested conditions

Stack multiple breakpoints in a single value using comma-separated conditions. Conditions cascade mobile-first — later matching conditions override earlier ones, and the final unconditioned value is the base default applied when no condition matches.

```tsx
<s-query-container>
  <s-box padding="@container (inline-size > 300px) base, (inline-size > 350px) large-200, (inline-size > 400px) large-400, none">
    <s-text>Padding scales with the container size, starting from none below 300px.</s-text>
  </s-box>
</s-query-container>
```

In the example above, a container narrower than 300px gets `padding="none"` (the base default). Between 300px and 350px only the first condition matches → `base`. Between 350px and 400px both early conditions match and the later one wins → `large-200`. Above 400px all three match and the last one wins → `large-400`. List conditions from smallest to largest threshold so the cascade resolves the way you expect.

### Escaped characters

Values with reserved characters like `()` or `,` should be wrapped in quotes.

```tsx
<s-query-container>
  <s-grid
    gridTemplateColumns="@container (inline-size > 450px) 'repeat(4, 1fr)', 'repeat(2, 1fr)'"
    gap="base"
    border="base"
  >
    <s-box background="subdued" padding="base"><s-text>1</s-text></s-box>
    <s-box background="subdued" padding="base"><s-text>2</s-text></s-box>
    <s-box background="subdued" padding="base"><s-text>3</s-text></s-box>
    <s-box background="subdued" padding="base"><s-text>4</s-text></s-box>
  </s-grid>
</s-query-container>
```

***

## Removed patterns

### hover and focus conditions

The `Style` helper's `hover` and `focus` conditions don't have a replacement in Polaris web components.

***
