Slices are reusable page sections that editors arrange in whatever order they like. Because the order is up to the editor, you can’t know which slice will sit above or below another, so it’s natural to build each one as a self-contained block.
But they don’t have to be. A slice can line up with the page’s shared layout, adjust its spacing based on the slice next to it, and even read its neighbors to decide how to render.
This article covers three techniques for slices that respond to their surroundings:
- Set a baseline: Use consistent spacing
- Break the baseline: Collapse spacing automatically
- Adapt to the environment: Read slices as data
These techniques are not specific to a framework or design. We’ll use React and Tailwind CSS so you have code to reference, but you can adapt the examples to your preferences.
A note about the slice simulator
You won’t see most of the techniques we cover when using the slice simulator to develop your slices. The simulator provides one slice at a time, so naturally, your slice can’t react to adjacent slices.
To test your work, create a test page in Prismic using your slices. Then preview that page to see your slices in action.
Set a baseline: Use consistent spacing
Every technique here builds on a shared baseline, so start there. Slices should share a default maximum content width and uniform padding, configurable to the slice’s design.
Using a shared wrapper component is the most maintainable way to share this baseline layout among slices. I like to call it <Bounded>, and it looks like this:
// src/components/Bounded.tsx
import type { JSX, PropsWithChildren } from "react";
import clsx from "clsx";
type BoundedProps = PropsWithChildren<{
as?: keyof JSX.IntrinsicElements;
className?: string;
}>;
/**
* @example
* ```tsx
* <Bounded><Bounded.Content>Lorem ipsum</Bounded.Content></Bounded>
* ```
*/
export function Bounded({
as: Comp = "section",
className,
...restProps
}: BoundedProps) {
return (
<Comp className={clsx("initial:px-6 initial:py-10 initial:md:py-20", className)} {...restProps} />
);
}
type BoundedContentProps = PropsWithChildren<{
className?: string;
}>;
Bounded.Content = function BoundedContent({
className,
...restProps
}: BoundedContentProps) {
return (
<div className={clsx("initial:max-w-6xl initial:mx-auto", className)} {...restProps} />
);
};Note the initial: prefix on class names. The prefix allows for overriding the classes when using the component. Assuming you are using Tailwind CSS, you’ll need to add this line to your CSS file to make it work:
// styles.css
@custom-variant initial (:where(&));Now, all slices can use <Bounded> as their outer-most element.
// src/slices/Hero/index.tsx
<Bounded>
<Bounded.Content>
Your slice content
</Bounded.Content>
</Bounded>If your design calls for different spacing or max-width, use the className prop to apply custom classes.
// src/slices/CallToAction/index.tsx
<Bounded className="py-20 md:py-40">
<Bounded.Content className="max-w-full">
Your slice content
</Bounded.Content>
</Bounded>Break the baseline: Collapse spacing automatically
<Bounded>'s vertical spacing works well when adjacent slices have different backgrounds. A blue slice next to a white slice, for example, looks best with ample spacing on each side of the boundary where they touch.
When adjacent slices share the same background, however, the spacing looks off: with no color change to break it up, the gap where they meet reads as exactly twice the intended amount.
This is easily solved with CSS. We can automatically detect adjacent <Bounded> components with the same background and automatically remove the top padding from the latter slice.
Here’s what the code for that looks like:
// src/components/Bounded.tsx
export function Bounded({
as: Comp = "section",
className,
...restProps
}: BoundedProps) {
return (
<Comp
className={clsx(
"initial:px-6 initial:py-10 initial:md:py-20",
// Collapse top padding when the previous slice shares this background
"[&.bg-white_+_&.bg-white]:pt-0!",
"[&.bg-blue-600_+_&.bg-blue-600]:pt-0!",
"[&.bg-gray-100_+_&.bg-gray-100]:pt-0!",
className,
)}
{...restProps}
/>
);
}Each selector reads as “a slice with this background, immediately followed by another slice with the same background, gets its top padding removed.” Because the rule requires the same background class on both siblings, padding collapses only between matching slices—a white-to-blue boundary keeps its full spacing.
A pure-CSS version is also included above if you aren’t using Tailwind CSS or want to see what’s happening behind the scenes. Just be sure to add a bounded class to <Bounded> if you use the CSS version.
A few things to note:
- The background class must be applied to the
<Bounded>element itself (viaclassName), since the selector matches on the element carrying the class. A background set on a child or via a CSS variable won’t be detected. pt-0!is marked important so it overrides both theinitial:default and any padding a slice passes throughclassName.- You need one selector per background. In the example we list
bg-white,bg-blue-600, andbg-gray-100. Update the list with all the background classes you’ll use.
With these additions to <Bounded>, your slices will space themselves more naturally.
Adapt to the environment: Read slices as data
Your slices may need to adjust their styling depending on their position on a page. For example, you might have a floating navigation bar at the top of your page, necessitating some extra top padding on the page’s first slice.
Prismic’s <SliceZone> component, which is used to render slices as UI components, provides the full list of slices as the slices prop and the slice’s index as the index prop. These props allow you to adjust a slice’s styling based on an adjacent slice or the slice’s position in the slice zone.
Here’s what adding extra top padding looks like if the slice is the first on the page:
// src/slices/Hero/index.tsx
import { SliceComponentProps } from "@prismicio/react";
import clsx from "clsx";
export default function Hero({ index }: SliceComponentProps) {
return (
<Bounded className={clsx(index === 0 && "pt-32")}>
<Bounded.Content>
Your slice content
</Bounded.Content>
</Bounded>
);
}You can do something similar by reading the data in adjacent slices. This example changes a slice’s top padding if the slice follows a Call to Action slice:
// src/slices/Hero/index.tsx
import { SliceComponentProps } from "@prismicio/react";
import clsx from "clsx";
export default function Hero({ slices, index }: SliceComponentProps) {
const prevSlice = slices[index - 1];
const afterCta = prevSlice?.slice_type === "call_to_action";
return (
<Bounded className={clsx(afterCta && "pt-0")}>
<Bounded.Content>
Your slice content
</Bounded.Content>
</Bounded>
);
}Wrap-up
With a shared <Bounded> component and a few CSS techniques, your slices can collapse spacing and adapt to the slices around them. Start from these patterns and adjust them to fit your design.
To learn more about the concepts used in this guide, see the Prismic documentation:
- Slices: What slices are and how to model them.
- SliceZone: The component that renders slices and passes each one its
slicesandindexprops. - Use Next.js with Prismic: How to fetch and display slices in a Next.js project.



