Styling a native Sanity component for a single implementation

14 replies
Last updated: Apr 2, 2020
Is there any way to style a native Sanity component for a single implementation?
I have one array field that could use larger grid columns, a darker background and some other niceties, but I don't want to override settings for the entire studio nor recreate the
entire array component. Plus, it'd be awesome if I could increase the max-width of the editor container for this specific document type. Any tips?🤔
AI Update

Yes! You can absolutely style native Sanity components for single implementations without recreating the entire component or affecting your whole Studio. Here's how:

Using renderDefault to Wrap Components

The key is using the Form Components API with the renderDefault function. This lets you wrap the default component with your own styling while keeping all its functionality.

For your specific use case with an array field, you can do this in your schema:

import {defineField} from 'sanity'
import {Stack} from '@sanity/ui'

defineField({
  name: 'myArray',
  type: 'array',
  of: [{type: 'image'}],
  components: {
    input: (props) => (
      <div style={{
        background: '#1a1a1a', // darker background
        padding: '20px',
        borderRadius: '8px'
      }}>
        {props.renderDefault({
          ...props,
          // You can pass custom props here
        })}
      </div>
    )
  },
  options: {
    layout: 'grid' // This gives you grid layout for arrays
  }
})

Styling Specific Document Types

For increasing the editor container width for a specific document type, you can use the components.field option:

import {defineType} from 'sanity'

defineType({
  name: 'myDocumentType',
  type: 'document',
  components: {
    field: (props) => (
      <div style={{maxWidth: '1200px', margin: '0 auto'}}>
        {props.renderDefault(props)}
      </div>
    )
  },
  fields: [
    // your fields
  ]
})

Using Sanity UI for Better Styling

Instead of inline styles, you can use Sanity UI components for more consistent theming:

import {Card} from '@sanity/ui'

components: {
  input: (props) => (
    <Card padding={4} tone="primary" radius={2}>
      {props.renderDefault(props)}
    </Card>
  )
}

Array Grid Options

For your array field specifically, Sanity has built-in grid support:

{
  name: 'gallery',
  type: 'array',
  of: [{type: 'image'}],
  options: {
    layout: 'grid' // or 'list'
  }
}

The beauty of renderDefault is that you keep all the native functionality (drag-and-drop, validation, etc.) while just adding your custom wrapper styling. This works at multiple levels:

  • components.input - Style just the input widget
  • components.field - Style the entire field (including title/description)
  • components.item - Style individual array items

You can apply these at the field level (single implementation) or globally in your sanity.config.js if needed later.

perhaps creating a custom preview would help? I played with that a little last night for a similar thing .. changing an
array
so that it used
display:grid
and all the grid settings to go with it.
Thanks for the answer, Bryce!
I've tried adding a
preview
object to the array, but that didn't help. The items themselves have custom previews, but as they can't change the container's styles...
Mind sharing a snippet of how you did it?
🙂
mmm, so you're looking to style the outside container?
and yes, let me find the snippet i used last night
yup, to make the cards larger
ok, so a little background on this. I've created a
gallery
component that goes inline with Portable text. From there I created a custom
GalleryPreview
object to displaying the gallery in the block editor.
here's the GalleryPreview object code ... for the very short term, i've simply added the CSS styles inline, but will eventually move this out to a CSS file probably

import React from 'react'
import client from 'part:@sanity/base/client'
import urlBuilder from '@sanity/image-url'

const urlFor = source => urlBuilder(client).image(source)

const galleryPreview = ({ value = {} }) => {
  let wrapperStyles = {
    display: 'grid',
    gridTemplateColumns:'repeat(3, 1fr)'
  }
  let figureStyles = {
    margin: '1rem'
  }
  let figureImgStyles = {
    maxWidth: '100%'
  }

  return (
    <div style={wrapperStyles}>
      {value &&
        value.images.map(image => (
          <figure key={image._key} style={figureStyles}>
            <img src={urlFor(image).url()} style={figureImgStyles}/>
          </figure>
        ))
      }
    </div>
  )
}

export default galleryPreview
here's what the output looks like
i would think this same thing would work for your needs? maybe not for increasing the overall editor width, but i think everything else
Gotcha! This is great for portable text, indeed, and the inline styles are no problem if this is as far as styling goes, thanks for the snippet and effort 💜
My use case, however, is inside of the regular form editor, not Portable Text, and this makes things harder: the idea is using a regular
type: 'array'
field with
options: { layout: 'grid' }
in order to maintain all of the vanilla fields and the drag and drop sorting functionality. Recreating this in a custom
inputComponent
would be a nightmare, especially as it was a simple matter of styling the component's CSS.
I managed to make it work with some CSS magic:


// In my `deskStructure.js`
// for the specific schema type I'm working with (edition)
S.view.form().id('EDITION_FORM')
And in CSS:

div[aria-labelledby*='EDITION_FORM'] div[class^='Editor_root'] {
  /* 200px larger than the default container */
  max-width: calc(840px + 2rem);
}

div[aria-labelledby*='EDITION_FORM'] ul[class^='GridList_root'] {
  /* default size is minmax(7rem, 1fr) */
  grid-template-columns: repeat(auto-fill, minmax(180px, 200px));
  /* Add a gray color to differentiate cards from BG */
  background: #f2f2f2;
}
This way, I select the form wrapper for this specific schema type based on the
aria-labelledby
attribute and am able to manipulate the editor root (increasing its width) and the grid container. Quite brittle, but much better than doing everything by hand 🎉🎉
Here's the result: a gray background for the grid container, larger cards and more room in the editor to drag this around 😍
ahh, that makes complete sense ... and glad you've got it looking the way you want
curious, was your question more about if there is a better and/or sanity specific way? or was your question before your did the CSS magic?
I was wondering if there was a Sanity-native approach that didn't involve overwriting styles for the whole studio. While we were chatting I figured out that Sanity uses
S.form().id()
in the HTML, and then I did the whole CSS thingy.
Would still love a native approach, though! hahaha
native is always preferred!

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?