Is there an option for super- and subscript in portable text field? Custom decorators can be added as an alternative.

8 replies
Last updated: Feb 24, 2021
Hy everyone, I wanted to ask if there is already an option in the portable text field for super- and subscript. If not, what would be a good alternative? does anyone have any tips?
AI Update

Hey! Portable Text doesn't include superscript and subscript as built-in decorators, but you can absolutely add them as custom decorators. This is a pretty common customization!

Here's how you can add both superscript and subscript to your Portable Text field:

// First, create your component functions
const SubComponent = (props) => <sub>{props.children}</sub>
const SupComponent = (props) => <sup>{props.children}</sup>

// Then define your schema
{
  name: "richText",
  type: "array",
  of: [
    {
      type: "block",
      marks: {
        decorators: [
          // Keep the default decorators you want
          { title: "Strong", value: "strong" },
          { title: "Emphasis", value: "em" },
          // Add your custom ones
          {
            title: "Subscript",
            value: "sub",
            icon: () => <sub>sub</sub>,
            component: SubComponent,
          },
          {
            title: "Superscript",
            value: "sup",
            icon: () => <sup>sup</sup>,
            component: SupComponent,
          },
        ],
      },
    },
  ],
}

The icon property defines what shows up in the toolbar button, and the component property determines how the styled text appears in the editor itself, which helps your content editors see what they're formatting.

Important note: As of Sanity v3.1, the API changed from using blockEditor.icon and blockEditor.render to using icon and component directly on the decorator object. Make sure you're using the current syntax shown above.

On the frontend, you'll need to handle these custom decorators in your serializer. If you're using @portabletext/react, it would look something like:

import { PortableText } from '@portabletext/react'

const components = {
  marks: {
    sub: ({ children }) => <sub>{children}</sub>,
    sup: ({ children }) => <sup>{children}</sup>,
  }
}

<PortableText value={content} components={components} />

This approach works great for any custom text formatting you need beyond the built-in options. You can read more about customizing the Portable Text Editor in the official docs!

Hi User, not out of the box but you could add them as custom decorators instead: https://www.sanity.io/docs/customization#decorators-e6401a8fe843
And then render them as follows: 
https://github.com/sanity-io/block-content-to-react#rendering-custom-marks
Or more specifically:

const sup = props => {
  return (
    <sup>
      {props.children}
    </sup>
  )
}

<BlockContent
  blocks={input}
  serializers={{marks: {sup}}}
/>
thanks for the fast reply, ill have a look and come back to you if i have more questions if thats okey?
That's perfectly ok!
I also had the schema lying around:
{
        name: "richText",
        type: "array",
        of: [
          {
            type: "block",
            marks: {
              decorators: [
                {
                  title: "Sub",
                  value: "sub",
                  blockEditor: {
                    icon: () => <sub>sub</sub>,
                    render: ({ children }) => <sub>{children}</sub>,
                  },
                },
                {
                  title: "Sup",
                  value: "sup",
                  blockEditor: {
                    icon: () => <sup>sup</sup>,
                    render: ({ children }) => <sup>{children}</sup>,
                  },
                },
              ],
            },
          },
        ],
      },

thankyou very much!
followup question: can i somehow hide or remove already existing decorators and/or annotations?
They will disappear when you add custom decorators/annotations 🙂

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?