Skip to content

Conversation

@basbroek
Copy link
Contributor

@basbroek basbroek commented Jul 23, 2025

PR Description

This PR introduces background support for text marks in Vega-Lite, improving readability and enabling basic annotation use cases.

Motivation

There has been interest in supporting backgrounds for text marks in the past (e.g., #1820, #3418). These discussions suggested that Vega-Lite could provide syntactic sugar to leverage Vega’s existing reactive geometry for this purpose.

Proposal

This PR adds the following properties to the text mark definition:

  • bgType
  • bgColor
  • bgOpacity
  • bgPadding
  • bgCornerRadius

When any of these properties are set, a rect layer is generated behind the text in the compiled Vega spec. The images below show the result for these two specs: example 1, example 2.

examples

Status

Work in Progress (WIP)
Ready for review - feedback requested on the following points:

  • Abstraction Fit: Does this pattern align with Vega-Lite’s design philosophy and abstraction level?
  • Code Placement: Maybe there's a more appropriate place for this logic?
  • Property Naming: Are the proposed names consistent with existing conventions?
  • Schema Restriction: How can I best constrain these properties to only be valid in text marks? I looked for examples, like aspect for image marks and tension for line marks, but it seems these are allowed in other mark definitions as well: "mark": {"type":"bar", "aspect":true, "tension": 1}.

Any suggestions or insights would be greatly appreciated!

@domoritz
Copy link
Member

Thanks. I think the spirit of this pull request is great. I wonder whether it would make more sense to support this in Vega?

@basbroek
Copy link
Contributor Author

The idea to support this in Vega has been discussed before, for instance in this issue and here. In both cases @jheer suggested a solution in VL. Maybe his opinion has changed?

As Vega provides the necessary "assembly language" primitives, I think "syntactic sugar" for generating these designs should occur at the Vega-Lite level. The current Vega setup allows for using the full range of text and rect features (cornerRadius, etc) without changing the surface area of Vega. One might also use a similar approach but with different background marks.

@domoritz
Copy link
Member

Ah, thanks for digging up those comments. Okay, let's see how we can tackle this in Vega-Lite then.

@kjgoodrick
Copy link

I think it would be great to have easy access to this in vega-lite! I have needed this functionality often and it would be great to have a more automatic approach. A couple of thoughts:

  1. In the past when I encountered this problem I used a second text layer with a wider stroke to create the background. In some cases I think this works better than the box as it can cover up less of the background. Do you think this PR could include an option for box or stroke?
  2. Sometimes when I do this the background is not a constant color, so it can be nice to use the luminance to change the color of the text/background as in this example. It would be great if the implementation of this PR allowed users to do this (if it does not already).

Thanks!

@basbroek
Copy link
Contributor Author

@kjgoodrick Thanks for your suggestions!

  1. I also sometimes use this 'halo' effect and I think it would be nice to incorporate it in this feature, for instance by adding a bgShape or bgType property that defaults to rect but also allows text.

  2. The bgColor field can be an expression, so you can make it dependent on other fields. Because the data of the background layer is derived from the text layer, the 'original' data are availabel in datum.datum, like this: "luminance(scale('color', datum.datum.name)) > 0.5 ? 'black' : 'white'".

@kjgoodrick
Copy link

  1. That sounds great to me, I think either name would work with a slight preference for bgType as "text" feels more like a type than a shape.
  2. Great, glad to hear that is possible!

@basbroek
Copy link
Contributor Author

Alright, I’ve done some work on this and I think it’s ready for review:

  • All logic now lives in src/compositemark/textbackground.ts
  • Adding marks with text background happens during normalization
  • Vega specific encoding (reactive geometry, zindex) is added during compiling
  • I have added an example, tests and documentation

Please let me know if I missed something.

@basbroek basbroek marked this pull request as ready for review August 14, 2025 09:29
@basbroek basbroek requested a review from a team as a code owner August 14, 2025 09:29
@kanitw
Copy link
Member

kanitw commented Sep 10, 2025

Property Naming: Are the proposed names consistent with existing conventions?

we have config.background, so I think using the full word "background" would be more consistent than just bg-.

Schema Restriction: How can I best constrain these properties to only be valid in text marks? I looked for examples, like aspect for image marks and tension for line marks, but it seems these are allowed in other mark definitions as well: "mark": {"type":"bar", "aspect":true, "tension": 1}.

Currently we don't have strong types for mark specific properties. I think it's fine to not address this in this PR.

src/mark.ts Outdated
*
* __Default value:__ `2`
*/
bgPadding?: Padding;
Copy link
Member

@kanitw kanitw Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using padding for both rect padding and text strokeWidth is mixing up two different things a bit.

I think it's better to separate background from outline since they can have different sets of properties.

Maybe:

background: Color | ES | TextBackground,
outline: Color | ES | TextOutline

where

interface TextBackground{
   color: ... // required
   opacity?:  ...
   padding?: ...
}

interface TextOutline {
   color: ... // required
   strokeWidth: ... 
   ...
   // no padding, cornerRadius
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this feedback. I have separated the config for background and outline as you suggested, which has the added benefit of allowing a combination of both. I also have rewritten the example, tests and documentation. Please let me know if anything else is necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kanitw If you have some time to spare, can you have a look at these changes and let me know if further work is needed? Thanks in advance.

@basbroek basbroek requested a review from kanitw October 22, 2025 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants