---
title: Migrate Bleed from Polaris React
description: >-
  Learn how to replace Polaris React Bleed layouts with container-owned spacing
  in Polaris web components.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/bleed
  md: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/bleed.md
api_name: app-home
---

# Migrate Bleed from Polaris React

Polaris web components don't provide a negative-margin primitive. Replace the Polaris React `Bleed` component from `@shopify/polaris` by moving spacing responsibility to the containing section, modal, box, stack, or grid.

For full-width content inside a section, set [`padding="none"` on `s-section`](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/section#section-propertydetail-padding), then add padding back only around content that should remain inset. This expresses the intended edges directly instead of making a child escape its parent.

***

## Replace a flushed card section

The following migration replaces a common `Bleed` use: extending media through a card's inline and top padding.

In the destination example, `s-section padding="none"` is the actual replacement for `Bleed`. The image's `inlineSize="fill"`, `aspectRatio="1/1"`, and `objectFit="cover"` describe how that media fills and crops within the new full-width region; they aren't translations of `marginInline` or `marginBlockStart`.

## Migrating a flushed section without Bleed

##### Polaris web components

```tsx
export function FeaturedProduct() {
  return (
    <s-section padding="none">
      <s-image
        src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'%3E%3Crect width='600' height='600' fill='%23f1e7e8'/%3E%3Cpath d='M300 470V180' stroke='%234c7b62' stroke-width='30'/%3E%3Cellipse cx='300' cy='225' rx='105' ry='175' fill='%23518f78'/%3E%3Cpath d='M300 70v310M245 85l40 290M355 85l-40 290' stroke='%232f6654' stroke-width='14'/%3E%3Cpath d='M185 390h230l-35 170H220Z' fill='%23df7f35'/%3E%3Cellipse cx='300' cy='390' rx='115' ry='30' fill='%23f19a50'/%3E%3C/svg%3E"
        alt="Green house plant in a ceramic pot"
        aspectRatio="1/1"
        objectFit="cover"
        inlineSize="fill"
      ></s-image>
      <s-box padding="base">
        <s-stack gap="small">
          <s-heading>Featured product</s-heading>
          <s-text>Highlight seasonal products in your sales channels.</s-text>
        </s-stack>
      </s-box>
    </s-section>
  );
}
```

##### Polaris React

```tsx
import {Bleed, Box, Card, Image, Text} from '@shopify/polaris';

export function FeaturedProduct() {
  return (
    <Card>
      <Bleed marginInline="400" marginBlockStart="400">
        <Image
          source="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'%3E%3Crect width='600' height='600' fill='%23f1e7e8'/%3E%3Cpath d='M300 470V180' stroke='%234c7b62' stroke-width='30'/%3E%3Cellipse cx='300' cy='225' rx='105' ry='175' fill='%23518f78'/%3E%3Cpath d='M300 70v310M245 85l40 290M355 85l-40 290' stroke='%232f6654' stroke-width='14'/%3E%3Cpath d='M185 390h230l-35 170H220Z' fill='%23df7f35'/%3E%3Cellipse cx='300' cy='390' rx='115' ry='30' fill='%23f19a50'/%3E%3C/svg%3E"
          alt="Green house plant in a ceramic pot"
        />
      </Bleed>
      <Box paddingBlockStart="400">
        <Text as="h2" variant="headingSm">
          Featured product
        </Text>
        <Text as="p">
          Highlight seasonal products in your sales channels.
        </Text>
      </Box>
    </Card>
  );
}
```

***

## Choose the composition

Start with the visual boundary the old child was trying to reach.

| Existing `Bleed` use | Polaris web components composition |
| - | - |
| Image, table, list, or divider flush with section edges | Use `s-section padding="none"`. Wrap only the inset siblings in `s-box padding="base"`. |
| Edge-to-edge modal media or table | Use `s-modal padding="none"`. Add `s-box padding="base"` around the modal content that needs inset spacing. |
| Different spacing between ordinary siblings | Use `gap` on `s-stack` or `s-grid`; don't cancel parent padding. |
| Inline alignment or a small visual nudge | Adjust the parent `s-grid`, `s-stack`, or `s-box` alignment and padding. Don't introduce negative CSS margins. |
| Larger checkbox, link, or button hit area | Use the corresponding interactive web component. Don't use visual overflow as the hit target. |

When a section contains multiple full-width and inset regions, alternate direct children and padded boxes:

1. Put full-width media, tables, lists, and dividers directly inside the padding-free section.

2. Wrap headings, paragraphs, form fields, and actions that need inset spacing in `s-box`.

3. Keep DOM order the same as the reading and focus order. Don't reposition content visually across its semantic siblings.

***

## Removed properties

All `Bleed` spacing properties are removed with the component.

### margin​Inline and margin​Block

There are no negative-margin replacements. Remove both properties and choose a container with the required boundary. If all children should be full width, remove padding from the container. If only some should be full width, add padding to the inset children instead.

### margin​Block​Start and margin​Block​End

Don't translate these values to negative block margins. Use parent `gap`, or use `paddingBlockStart` and `paddingBlockEnd` on the neighboring `s-box` when the space belongs to one region.

For a full-width first or last child, use a padding-free section or modal so the child naturally reaches that edge.

### margin​Inline​Start and margin​Inline​End

Don't translate these values to negative inline margins. Use `s-grid` columns and alignment for asymmetric layouts. Use `paddingInlineStart` or `paddingInlineEnd` on an inset region only when the design intentionally needs one-sided padding.

### Responsive spacing objects

Responsive `Bleed` values such as `marginInline={{xs: '200', md: '400'}}` have no direct replacement. Re-evaluate the containing layout at narrow and wide iframe sizes. When the parent padding or grid genuinely needs to change, use the documented [responsive values](https://shopify.dev/docs/api/polaris/using-polaris-web-components#responsive-values) on that parent instead of applying an equal negative value to its child.

### children

Move each child to the new container or padded region. `Bleed` didn't add content semantics, so don't add an extra wrapper unless it owns spacing, structure, or an accessible relationship.

***

## Test the migration

* Compare the intended outer edges at narrow and wide iframe sizes, not the old negative margin values.
* Check that full-width media and tables don't overflow the iframe or create horizontal scrolling.
* Verify inset headings, body content, fields, and actions retain appropriate padding.
* Confirm reading order, focus order, and interactive hit areas match the DOM order.
* Test right-to-left layouts when the old call site used inline-start or inline-end values.
* Remove CSS custom properties and responsive helpers that only calculated the old negative margins.
* Remove the Polaris React `Bleed` import after its final consumer is migrated.

***

## Related guidance

* [Section component](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/section)
* [Box component](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/box)
* [Stack component](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/stack)
* [Grid component](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/grid)
* [Migrate from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react)

***
