Trouble applying custom styles in rich text editor to live site

16 replies
Last updated: Oct 16, 2021
I've modified the styles available in rich text editor and I can see that the custom styles are applied in rich text editor. But in live site, it isn't working!
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:
AI Update

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:

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.

Styles applied in the Studio have no effect on the frontend. You need to reapply the styles on the frontend.
If you’re also using React on the frontend, you could have a monorepo with the Studio and the frontend and share stylesheets. But you said in another thread that you’re using Tailwind on the frontend, so this is not an option.
If I can apply the styles from stylesheet, I'm more than happy with it.
are you using Tailwind on the front-end?
yeah, tailwind as well as some global styles in usual stylesheet.Here is how I try to render the UI part (code sample attached). But when I look into the actual site, I could see the contents being rendered without
div, a
tags as well as no classnames are being passed to frontend!
You are mixing backend and frontend styling, as Jérôme said, the style you apply in the studio has nothing to do with your website. You’ll have to use the PortableText package to apply and customize your frontend.
Thanks
user T
. I have already rendered some custom marks and blocks using portable text.
I've tried the same for styles too, but it is not working! Am I missing something here?

Here is the sample object (rich text object) that I get in front-end. My problem is that how can I recognize the value in
style node
and render the UI?
Here is the object sample:
You can access the style with
node.style
like this:

const serializers = {
  types: {
		block: ({ node, children }) => {
			switch (node.style) {
		    case 'h1':
	        return <h1>{children}</h1>
        case 'h2':
	        return <h2>{children}</h2>
        case 'h3':
	        return <h3>{children}</h3>
        case 'h4':
	        return <h4>{children}</h4>
        case 'h5':
	        return <h5>{children}</h5>
        case 'h6':
	        return <h6>{children}</h6>
				case 'blockquote':
	        return <blockquote>{children}</blockquote>
        default:
          return <p>{children}</p>
	    }
		}
	}
}
Awesome
user T
. Exactly what I was looking for!!!
I want to style the list items in Sanity. I tried capturing it in the same
types
block but it is not working!
user T
Can you please help me on this?
user T
Can you please help me on this?
Hey
user H
, list items are under the type
lists
not
block
thanks! figured it out 🙂
You can do something like this
 list: ({ children, type }) =>
    type === 'bullet' ? (
      <ul className="something">{children}</ul>
    ) : (
      <ol className="something-else">{children}</ol>
    )

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?