Getting SVGs from Sanity and rendering them as React components

12 replies
Last updated: May 20, 2022
Hey! Is it possible to get SVGs the way we get images from Sanity natively? If yes, how can I do it?
AI Update

Yes, you can absolutely get SVGs from Sanity natively! SVG files are supported as image assets in Sanity's Content Lake.

How SVG Support Works

According to the official Sanity documentation on assets, Sanity supports SVG files as one of many image formats, including JPG, PNG, WebP, TIFF, GIF, HEIF, and AVIF (8-bit).

Important Behavior to Know

SVGs pass through the image pipeline untouched. This is a key detail - while Sanity's image pipeline can transform formats like JPEG, PNG, WebP, PJPG, TIFF, AVIF, and GIF, SVG and GIF files pass through the pipeline without being processed or transformed. This means:

  • You can upload SVGs just like any other image
  • They'll be stored and served via Sanity's global CDN at cdn.sanity.io
  • Image transformation parameters (like resize, crop, etc.) won't apply to SVGs
  • The SVG will be delivered as-is in its original format

How to Use SVGs

You can work with SVGs in Sanity the same way you work with other images:

  1. Upload - Use the image field type in Studio or upload via the API
  2. Reference - Store references to SVG assets in your documents using the image schema type
  3. Query - Retrieve SVG URLs using GROQ queries, just like other image assets
  4. Display - Use the asset URL directly in your frontend - the SVG will be served from Sanity's CDN

The asset URL structure is the same as other images:

https://cdn.sanity.io/images/<project-id>/<dataset>/<asset-id>-<dimensions>.svg

Since SVGs are vector-based and already scalable, the fact that they pass through untransformed is actually ideal - you get the full quality and scalability benefits of the SVG format while still benefiting from Sanity's global CDN delivery.

two png images and an svg
and I was playing with formatting with next+tailwind+styled but think this may be readable:

import Head from 'next/head';
import Image from 'next/image';
import groq from 'groq';
import sanityClient from '@lib/sanityClient';
import tw from 'tailwind-styled-components';

export default function Home({ docs, imgs }) {
  return (
    <div className="max-w-2xl mx-auto">
      <Head>
        <title>Beep</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <h1>Riff Raff...</h1>
      <form>
        <Input type="text" placeholder="Title" />
        <Button>Submit</Button>
      </form>
      <hr />
      <h2>Images</h2>
      <div>
        {docs.length > 0 &&
          imgs.map(({ _id, url='', originalFilename  }) => <Image
              src={url}
              key={_id}
              alt={originalFilename}
              height={200}
              width={200}
            />
          )}
      </div>
      <h2>Doc Titlees</h2>
      <div>
        {docs.length > 0 &&
          docs.map(({ _id, title = '' }) => <div key={_id}>{title}</div>)}
      </div>
    </div>
  );
}

// ------------------------------------------------------------HOOKS
export async function getStaticProps() {
  const docs = await sanityClient.fetch(groq`
    *[_type == "project"]
  `);
  const imgs = await sanityClient.fetch(groq`
    *[_type == "sanity.imageAsset"]
  `);
  return { props: { docs, imgs } };
}


// ------------------------------------------------------------STYLES
const Input = tw.input`
  input
  input-bordered
  input-primary
  w-full
  max-w-xs
`;
const Button = tw.button`
  btn
  mx-4
`;
I actually want to get the SVG from sanity the way we get images, but not as an image, but as a pure SVG, so I can make it a ReactComponent SVG and then load in the page, as well as not losing the SVG's advantages
ooohhh I see I think - rad question, you will need to stringify or objectify that I think. SVG isn’t in the officially supported image types but it behaves like it is. Lemme see. I’m certain it is possible and have seen a good number of custom use cases like this.
Forgive me, I haven’t tried this before myself. But it could be possible to upload the raw svg as a file asset type when it may get recognized as an image. Otherwise you’d need to turn the blob into a string to render it as an element somewhere else. You could ‘objectify’ the attributes into a document as well. You can put the same react component code in your front end as the studio pretty much, with the formbuilder api to make something neat and interactive too. Or do something simple like add a color input to define the fill color value in your markup.
When SVGs are queried with the img url as an imageAsset, they do appear to return the actual svg markup - so rendering and modifying that appears quite possible and may depend on your app’s code to find and replace values like fill.
short story: even if it’s a
sanity.imageAsset
, what you get in on query is still the raw markup blob.
Interesting, thanks for the help!
user S
Hey! Did you manage to build a working solution?
user R
Since I figured out there weren't really any tradeoffs using the SVGs in img tags (I thought it would pixelate in big screen but actually it doesn't), I decided to take the easy route, since I already had plenty of stuff to get used to with Sanity already 😅
Ok, great!BTW I found this plugin —
https://www.npmjs.com/package/sanity-plugin-inline-svg
That's awesome, I'll make sure to use it next time! Thanks for sharing 😁
That’s really awesome. I’m so sorry, there are so many plugins it’s hard to know what’s out there sometimes. 🥹

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?