---
title: "Rich Text"
description: "This article explains what the rich text field is and how to configure it."
meta_title: "Rich Text"
category: "fields"
audience: developers
lastUpdated: "2026-01-10T02:37:42.000Z"
---

The rich text field allows content writers to write formatted content, including paragraphs, headings, lists, and more.

Prismic provides components for [Next.js](https://prismic.io/docs/nextjs.md), [Nuxt](https://prismic.io/docs/nuxt.md), and [SvelteKit](https://prismic.io/docs/sveltekit.md) to display rich text.

**Next.js example:**

```tsx
import { PrismicRichText } from "@prismicio/react";
import { Heading } from "@/components/Heading";

<PrismicRichText
  field={slice.primary.my_rich_text_field}
  components={{
    heading1: ({ children }) => <Heading as="h1">{children}</Heading>,
    paragraph: ({ children }) => <p className="my-8">{children}</p>,
  }}
/>;
```

**Nuxt example:**

```vue
<script setup lang="ts">
import Heading from "~/components/Heading.vue";
import Paragraph from "~/components/Paragraph.vue";
</script>

<template>
  <PrismicRichText
    :field="slice.primary.my_rich_text_field"
    :components="{
      heading1: Heading,
      paragraph: Paragraph,
    }"
  />
</template>
```

**SvelteKit example:**

```svelte
<script lang="ts">
  import { PrismicRichText } from "@prismicio/svelte";
  import { Heading } from "$lib/components/Heading";
  import { Paragraph } from "$lib/components/Paragraph";
</script>

<PrismicRichText
  field={slice.primary.my_rich_text_field}
  components={{
    heading1: Heading,
    paragraph: Paragraph,
  }}
/>
```

> The [text field](https://prismic.io/docs/fields/text.md) and rich text field look similar. Use the text field for simple text that does not need formatting. Use the rich text field for text that requires formatting.

# Add a rich text field to a content model

1. **Open Slice Machine**

   In your Prismic project, start Slice Machine to begin editing content models.

   ```sh
   npx start-slicemachine --open
   ```

2. **Add a rich text field**

   In Slice Machine, navigate to the slice, page type, or custom type you want to modify. Add a **rich text** field.

   The **label** determines the label shown to content writers in the [Page Builder](https://prismic.io/docs/guides/page-builder.md). Use an easily understood name.

   The **API ID** determines the property name in the Content API. Use a short, snake-cased name.

   The **Allow target blank for links** checkbox determines if a content writer can configure links to open in a new window.

   The **Allow multiple paragraphs** checkbox determines if a content writer can write multiple blocks of content.

3. **(Optional) Allow a subset of formatting options**

   By default, rich text fields support all formatting options. In some cases, you may want to restrict formatting options, such as only allowing H1, H2, and H3 headings.

   Open the field settings and enable or disable formatting options under the **Accept** section.

# Display rich text

Prismic provides rich text components for Next.js, Nuxt, and SvelteKit.

**Next.js example:**

```tsx
import { PrismicRichText, PrismicText } from "@prismicio/react";

// Display as rich text with formatting
<PrismicRichText field={slice.primary.my_rich_text_field} />

// Display as plain text
<PrismicText field={slice.primary.my_rich_text_field} />
```

See the [`<PrismicRichText>` documentation](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#prismicrichtext) and [`<PrismicText>` documentation](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#prismictext) to learn more.

**Nuxt example:**

```vue-html
<!-- Display as rich text with formatting -->
<PrismicRichText :field="slice.primary.my_rich_text_field" />

<!-- Display as plain text -->
<PrismicText :field="slice.primary.my_rich_text_field" />
```

See the [`<PrismicRichText>` documentation](https://prismic.io/docs/technical-reference/prismicio-vue/v6.md#prismicrichtext) and [`<PrismicText>` documentation](https://prismic.io/docs/technical-reference/prismicio-vue/v6.md#prismictext) to learn more.

**SvelteKit example:**

```svelte
<script lang="ts">
  import { PrismicRichText, PrismicText } from "@prismicio/svelte";
</script>

<!-- Display as rich text with formatting -->
<PrismicRichText field={slice.primary.my_rich_text_field} />

<!-- Display as plain text -->
<PrismicText field={slice.primary.my_rich_text_field} />
```

See the [`<PrismicRichText>` documentation](https://prismic.io/docs/technical-reference/prismicio-svelte/v2.md#prismicrichtext) and [`<PrismicText>` documentation](https://prismic.io/docs/technical-reference/prismicio-svelte/v2.md#prismictext) to learn more.

# Style rich text

Rich text can be styled using CSS and a wrapper element.

* **Markup:**

  **Next.js example:**

  ```tsx
  import { PrismicRichText } from "@prismicio/react";

  <div className="rich-text">
    <PrismicRichText field={slice.primary.my_rich_text_field} />
  </div>;
  ```

  **Nuxt example:**

  ```vue-html
  <div class="rich-text">
    <PrismicRichText :field="slice.primary.my_rich_text_field" />
  </div>
  ```

  **SvelteKit example:**

  ```svelte
  <script lang="ts">
    import { PrismicRichText } from "@prismicio/svelte";
  </script>

  <div class="rich-text">
    <PrismicRichText field={slice.primary.my_rich_text_field} />
  </div>
  ```

* **CSS:**

  ```css
  .rich-text h1 {
    font-size: 4rem;
    font-weight: bold;
    margin: 2rem 0;
  }

  .rich-text p {
    margin: 2rem 0;
  }
  ```

> Rich text can also be styled using custom components. [See below](#use-custom-ui-components).

# Use custom UI components

Prismic's rich text component can render custom components for each block type using the `components` prop. This prop allows you to use component libraries like Mantine, MUI, or your own.

**Next.js example:**

```tsx {6-9}
import { PrismicRichText } from "@prismicio/react";
import { Heading } from "@/components/Heading";

<PrismicRichText
  field={slice.primary.my_rich_text_field}
  components={{
    heading1: ({ children }) => <Heading as="h1">{children}</Heading>,
    paragraph: ({ children }) => <p className="my-8">{children}</p>,
  }}
/>;
```

[Learn more about the `components` prop](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#prismicrichtext)

**Nuxt example:**

```vue {8-15}
<script setup lang="ts">
import Heading from "~/components/Heading.vue";
</script>

<template>
  <PrismicRichText
    :field="slice.primary.my_rich_text_field"
    :components="{
      // Full component
      heading1: Heading,
      // Shorthand with attributes
      paragraph: { class: 'my-8' },
      // Shorthand with custom element and attributes
      preformatted: { as: 'div', class: 'code-block' },
    }"
  />
</template>
```

```vue filename=components/Heading.vue
<script setup lang="ts">
defineProps(getRichTextComponentProps("heading1"));
</script>

<template>
  <h1 class="text-xl font-bold"><slot /></h1>
</template>
```

> **Important**
>
> The shorthand definition applies to all block types except `span`. The `as` property, which allows customizing the rendered element, is not available on `image`, `embed`, `hyperlink`, and `label` nodes.

[Learn more about the `components` prop](https://prismic.io/docs/technical-reference/prismicio-vue/v6.md#prismicrichtext)

**SvelteKit example:**

```svelte {8-15}
<script lang="ts">
  import { PrismicRichText } from "@prismicio/svelte";
  import { Heading } from "$lib/components/Heading";
</script>

<PrismicRichText
  field={slice.primary.my_rich_text_field}
  components={{
    // Full component
    heading1: Heading,
    // Shorthand with attributes
    paragraph: { class: "my-8" },
    // Shorthand with custom element and attributes
    preformatted: { as: "div", class: "code-block" },
  }}
/>
```

```svelte filename=src/lib/components/Heading.svelte
<script lang="ts">
  import type { RichTextComponentProps } from "@prismicio/svelte";
  import type { RTHeading1Node } from "@prismicio/client";

  let { children }: RichTextComponentProps<RTHeading1Node> = $props();
</script>

<h1 class="font-bold text-xl">
  {@render children?.()}
</h1>
```

> **Important**
>
> The shorthand definition applies to all block types except `span`. The `as` property, which allows customizing the rendered element, is not available on `image`, `embed`, `hyperlink`, and `label` nodes.

[Learn more about the `components` prop](https://prismic.io/docs/technical-reference/prismicio-svelte/v2.md#prismicrichtext)

## Use custom UI components globally

To set custom components once and use globally, create your own wrapper component containing `<PrismicRichText>` and your custom components. Use your component in place of `@prismicio/react`'s `<PrismicRichText>`.

You can use the following example as a starting point — just customize your default components. It supports the same props as the base `<PrismicRichText>`.

**Next.js example:**

```tsx filename=src/components/PrismicRichText.tsx collapsed
import {
  PrismicRichText as BasePrismicRichText,
  PrismicRichTextProps,
  JSXMapSerializer,
} from "@prismicio/react";

const defaultComponents: JSXMapSerializer = {
  heading1: ({ children }) => (
    <h1 className="text-3xl font-bold">{children}</h1>
  ),
};

export function PrismicRichText({
  components,
  ...props
}: PrismicRichTextProps) {
  return (
    <BasePrismicRichText
      components={{ ...defaultComponents, ...components }}
      {...props}
    />
  );
}
```

**Nuxt example:**

```vue filename=components/MyPrismicRichText.vue collapsed
<script setup lang="ts">
import type {
  PrismicRichTextProps,
  VueRichTextSerializer,
} from "@prismicio/vue";
import Heading from "~/components/Heading.vue";

const props = defineProps<PrismicRichTextProps>();

const defaultComponents: VueRichTextSerializer = {
  heading1: Heading,
};

const mergedComponents = {
  ...defaultComponents,
  ...props.components,
};
</script>

<template>
  <PrismicRichText :field="field" :components="mergedComponents" />
</template>
```

**SvelteKit example:**

```svelte filename=src/lib/components/PrismicRichText.svelte collapsed
<script lang="ts">
  import {
    PrismicRichText as BasePrismicRichText,
    type RichTextComponents,
  } from "@prismicio/svelte";
  import type { RichTextField } from "@prismicio/client";
  import { Heading } from "$lib/components/Heading";

  type Props = {
    field: RichTextField;
    components?: RichTextComponents;
  };

  let { field, components }: Props = $props();

  const defaultComponents: RichTextComponents = {
    heading1: Heading,
  };

  const mergedComponents = {
    ...defaultComponents,
    ...components,
  };
</script>

<BasePrismicRichText {field} components={mergedComponents} />
```

# Use labels for custom formatting

Rich text fields support standard text formatting options, like bold and emphasized text. If the formatting you need is not supported, add custom formatting options using **labels**.

Content writers can select text and apply a label. In your website's code, you can read the label and apply custom formatting by, for example, adding a custom CSS class.

You can register as many labels as needed.

> Unlike other rich text options, labels cannot be configured through [Slice Machine](https://prismic.io/docs/slice-machine.md). Instead, they must be added by editing your content model's JSON file.

1. **Open your content model's JSON file**

   In your Prismic project, open the slice, page type, or custom type JSON file you want to modify. The file location depends on the content type:

   * **Slices**: Typically in `src/slices/<name>/model.json`.
   * **Page types**: `customtypes/<name>/index.json`.
   * **Custom types**: `customtypes/<name>/index.json`.

2. **Add a label**

   Add a `labels` property to the rich text field like the following. The value should be an array of strings, one for each label.

   This example adds a label named **superscript** to a field named `text`.

   ```json {14}
   {
     "id": "text_with_image",
     "type": "SharedSlice",
     "name": "TextWithImage",
     "description": "TextWithImage",
     "variations": [
       {
         // ...
         "primary": {
           "text": {
             "type": "StructuredText",
             "config": {
               "label": "Text",
               "labels": ["superscript"],
               "multi": "paragraph,strong,em"
             }
           }
         }
         // ...
       }
     ]
   }
   ```

3. **Display rich text with custom formatting**

   Use a custom component for `label` blocks and read the block's `node.data.label` property to conditionally style the text.

   This example displays a `<sup>` HTML element when the label is **superscript**.

   **Next.js example:**

   ```tsx {4-8}
   <PrismicRichText
     field={slice.primary.text}
     components={{
       label: ({ node, children }) => {
         if (node.data.label === "superscript") {
           return <sup>{children}</sup>;
         }
       },
     }}
   />
   ```

   **Nuxt example:**

   ```vue {8}
   <script setup lang="ts">
   import Label from "~/components/Label.vue";
   </script>

   <PrismicRichText
     :field="slice.primary.my_rich_text_field"
     :components="{
       label: Label,
     }"
   />
   ```

   ```vue filename=components/Label.vue
   <script setup lang="ts">
   defineProps(getRichTextComponentProps("label"));
   </script>

   <template>
     <sup v-if="node.data.label === 'superscript'"><slot /></sup>
     <span v-else :class="node.data.label"><slot /></span>
   </template>
   ```

   **SvelteKit example:**

   ```svelte {8}
   <script>
     import { Label } from "$lib/components/Label";
   </script>

   <PrismicRichText
     field={slice.primary.my_rich_text_field}
     components={{
       label: Label,
     }}
   />
   ```

   ```svelte filename=src/lib/components/Label.svelte
   <script lang="ts">
     import type { RTLabelNode } from "@prismicio/client";
     import type { Snippet } from "svelte";

     type Props = {
       node: RTLabelNode;
       children: Snippet;
     };

     let { node, children }: Props = $props();
   </script>

   {#if node.data.label === "superscript"}
     <sup>{@render children()}</sup>
   {:else}
     <span class={node.data.label}>{@render children()}</span>
   {/if}
   ```

   [Learn more about using custom UI components](#use-custom-ui-components)

# Convert rich text to HTML or plain text

`@prismicio/client` provides helpers to convert rich text to HTML or plain text.

```ts
import { asHTML, asText } from "@prismicio/client";

const html = asHTML(slice.primary.my_rich_text_field);
const text = asText(slice.primary.my_rich_text_field);
```

[Learn more about `asHTML` and `asText`](https://prismic.io/docs/technical-reference/prismicio-client/v7.md#prismicashtml)

# Check if a rich text field has a value

Use `isFilled.richText()` from [`@prismicio/client`](https://prismic.io/docs/technical-reference/prismicio-client/v7.md) to check if a rich text field has a value.

```ts
import { isFilled } from "@prismicio/client";

if (isFilled.richText(slice.primary.my_rich_text_field)) {
  // Do something if `my_rich_text_field` has a value.
}
```

[Learn more about `isFilled`](https://prismic.io/docs/technical-reference/prismicio-client/v7.md#isfilled)

# API response

Here is what a rich text field looks like from the Content API:

```json
{
  "example_rich_text": [
    {
      "type": "heading1",
      "text": "Build a website that grows",
      "spans": []
    },
    {
      "type": "paragraph",
      "text": "Empower marketers to release on-brand pages fast.",
      "spans": [
        {
          "type": "em",
          "start": 45,
          "end": 48
        }
      ]
    }
  ]
}
```

Prismic returns a JSON representation of the field's formatted content. Prismic's [rich text components](#display-rich-text) are the best way to display the JSON content.
