Custom rich text editor styles not showing on live site
I'm not sure why the UI is not applied in the site! Similarly, I want to control the rendering DOMs too (say, I want to render the hyperlink content within
<a>tag).
cc:
user E user T user M user A
Here is the UI:
Ah, this is a common point of confusion! Customizing styles in the Sanity Studio rich text editor only affects how content looks in the Studio - it doesn't automatically apply those styles to your frontend. You need to handle rendering separately on your website.
The Two-Part Solution
1. Studio Styling (what you've already done) - This is just for the editor experience. When you customize decorators with blockEditor.render, that only affects how content creators see styled text while editing.
2. Frontend Rendering (what you're missing) - You need to configure how Portable Text renders on your actual website using a serializer/component library.
How to Render Custom Styles on Your Frontend
Depending on your framework, you'll use different libraries:
For React/Next.js, use @portabletext/react:
import {PortableText} from '@portabletext/react'
const components = {
marks: {
// Custom decorator
sup: ({children}) => <sup>{children}</sup>,
sub: ({children}) => <sub>{children}</sub>,
// Built-in decorators (if you want custom rendering)
strong: ({children}) => <strong className="font-bold">{children}</strong>,
// Link annotation (for your hyperlink question)
link: ({value, children}) => {
const target = (value?.href || '').startsWith('http') ? '_blank' : undefined
return (
<a href={value?.href} target={target} rel={target === '_blank' ? 'noopener' : undefined}>
{children}
</a>
)
},
},
block: {
h1: ({children}) => <h1 className="text-4xl">{children}</h1>,
// ... other block styles
}
}
// In your component
<PortableText value={content} components={components} />For other frameworks:
- Vue/Nuxt: @portabletext/vue
- Svelte: @portabletext/svelte
- HTML/vanilla JS: @portabletext/to-html
Controlling Link Rendering
For your hyperlink question - yes, you absolutely control the DOM rendering! In the marks.link component above, you define exactly how links render. You can add classes, control target attributes, add analytics tracking, etc.
The key insight: Portable Text is structured data. The Studio shows one representation, but your frontend can render it however you want. The Studio's blockEditor.render and your frontend's serializer components are completely independent.
Show original thread16 replies
Was this answer helpful?
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.