# A guide to creating custom marks with Plot

**URL:** <https://talk.observablehq.com/t/a-guide-to-creating-custom-marks-with-plot/10340>\
**Category:** Show and tell\
**Created:** [March 31, 2025, 8:02pm UTC](https://talk.observablehq.com/t/a-guide-to-creating-custom-marks-with-plot/10340 "2025-03-31T20:02:47Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jwoLondon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jwolondon/32/259_2.png) [@jwoLondon](https://talk.observablehq.com/u/jwoLondon)\
**Post date:** [March 31, 2025, 8:02pm UTC](https://talk.observablehq.com/t/a-guide-to-creating-custom-marks-with-plot/10340/1 "2025-03-31T20:02:47Z")

</div>

Whenever I wish to add a little more expressiveness when using Plot I find myself having to search this forum and examples to remember what to do.

So I thought I create an explainer with examples for the different ways Plot marks can be customised beyond the standard channel encodings. It started as a simple ‘hello’ page, but grew a little as I explored more. I ended up being pleasantly surprised at how easy it was to customise, which is mostly down to the elegant design of Plot from @mbostock and @Fil

 ![customMontage](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/b/bbfe53ab484e60501b016ecaee76373185548e0b.jpeg)

I hope others find it useful. But also happy to receive comments for improvements / simplifications, especially those with more in-depth knowledge of SVG and the inner workings of Plot.

Here’s the page:

> **[Hello custom marks with Plot](https://observablehq.com/@jwolondon/hello-custom-marks-with-plot)**
>
> Even though Plot provides many types of mark, sometimes you want to exercise more creative control over the appearance of graphical symbols in your visualization work. On this page I explore some options, roughly in order of sophistication, for...

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [April 3, 2025, 4:28pm UTC](https://talk.observablehq.com/t/a-guide-to-creating-custom-marks-with-plot/10340/2 "2025-04-03T16:28:38Z")

</div>

Nice work, Jo! Thanks for writing this up and sharing.

Another technique I use sometimes is a [render function](https://github.com/observablehq/plot/blob/90a56897cabda400e2b7537f8ecbbd2cebd18f7f/src/mark.d.ts#L41-L60); this is essentially shorthand for a custom mark. You can use this when your custom mark doesn’t need any data, but you still want access to the plot’s scales. An example of this is here for the (court) **markings** mark:

> **[Plot: LeBron James’ shots](https://observablehq.com/@observablehq/plot-lebron-james-shots)**
>
> A recreation of Matt Stiles’ and Mitchell Thorson’s basketball shot charts in Observable Plot, demonstrating a custom mark to render the court markings. Based on work by Nicholas Ortenzio. The bin transform is used to produce a heatmap.

You can also use this technique to invert the pattern you demonstrated: instead of embedding a plot into an SVG template literal, you can embed the SVG template literal into the plot. Another example is generating the linearGradient element for these bars:

> **[Plot: Gradient bars](https://observablehq.com/@observablehq/plot-gradient-bars)**
>
> Marks may be a function which returns an SVG element, if you wish to insert arbitrary content. Here we use Hypertext Literal to generate an SVG gradient that can be referenced as a funciri color definition.

The [**render** mark option](https://github.com/observablehq/plot/blob/90a56897cabda400e2b7537f8ecbbd2cebd18f7f/src/mark.d.ts#L138-L139) is also quite useful for, in effect, extending a built-in mark to add some custom rendering. This example could probably simplified, but here’s a “growUp” render transform that applies to the bar mark to add a little (and gratuitous) intro animation:

> **[Plot: Intro animations](https://observablehq.com/@observablehq/plot-intro-animations)**

This reminds me that we still need to document all these things better. Fil has a great start in [#1811](https://github.com/observablehq/plot/pull/1811) but I haven’t had much time to contribute yet.

---

<div class="post-metadata">

**Author:** ![jwoLondon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jwolondon/32/259_2.png) [@jwoLondon](https://talk.observablehq.com/u/jwoLondon)\
**Post date:** [April 4, 2025, 5:31am UTC](https://talk.observablehq.com/t/a-guide-to-creating-custom-marks-with-plot/10340/3 "2025-04-04T05:31:01Z")

</div>

> [@mbostock](#):
>
> You can also use this technique to invert the pattern you demonstrated: instead of embedding a plot into an SVG template literal, you can embed the SVG template literal into the plot.

Thanks Mike. I like this approach particularly, as it would make adapting existing code more straightforward (we just add one extra ‘mark’ to the list). However, if I’ve understood correctly, this limits the scope of the `<defs>` to the marks alone, so wouldn’t work, for example, if you needed to reference them in a color’s `range` specification outside the marks list.
