Search code examples
jsonchartsvisualizationvega-lite

Vega-Lite: text stroke on the outside


I have a Vega-Lite bar chart with data labels on the bars. The issue is when the colors are dynamic, the text becomes low-contrast and unreadable. I would like to add a white outline to the text. However, if I just set "stroke": "white" to the text mark, the stroke overlaps the font and makes it look glitchy:

enter image description here

I want the stroke to be only on the outside of the text fill. Is that possible?


Solution

  • A better technique is to look at the luminance as described here: https://github.com/Giammaria/Vega-Lite-Techniques?tab=readme-ov-file#luminance-to-determine-font-color

    If you want to use a stroke, then this gets you close.

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "description": "Vega-Lite bar chart from https://observablehq.com/@d3/learn-d3-scales.",
      "width": 400,
      "data": {
        "values": [
          {"name": "🍊", "count": 21},
          {"name": "🍇", "count": 13},
          {"name": "🍏", "count": 8},
          {"name": "🍌", "count": 5},
          {"name": "🍐", "count": 3},
          {"name": "🍋", "count": 2},
          {"name": "🍎", "count": 1},
          {"name": "🍉", "count": 1}
        ]
      },
      "encoding": {
        "y": {"field": "name", "type": "nominal", "sort": "-x", "title": null},
        "x": {"field": "count", "type": "quantitative", "title": null}
      },
      "layer": [
        {
          "mark": "bar",
          "encoding": {
            "color": {
              "field": "count",
              "type": "quantitative",
              "title": "Number of fruit"
            }
          }
        },
        {
          "mark": {
            "type": "text",
            "align": "right",
            "xOffset": -4,
            "aria": false,
            "fill": "transparent",
            "stroke": "white",
            "fontSize": 12,
            "fontWeight": "bold",
            "strokeWidth": 1.5
          },
          "encoding": {"text": {"field": "count", "type": "quantitative"}}
        },
        {
          "mark": {
            "type": "text",
            "align": "right",
            "xOffset": -4,
            "aria": false,
            "fill": "black",
            "fontSize": 12
          },
          "encoding": {"text": {"field": "count", "type": "quantitative"}}
        }
      ]
    }