Skip to main content

Create basic SVG charts

Project description

basic-svg-chart

A simple Python library for creating basic SVG charts, dependency-free: it uses builtin xml.etree.ElementTree.

To see what kind of charts can be created with this library, see examples gallery.

Line chart representing the annual global-average surface air temperature anomalies relative to 1850–1900 from 1940 to 2025 in ERA5 dataset, and a linear regression for the last 30 years

This library can also be used as a REST API (built with FastAPI). A html form to test this API is accessible here.

Why another charting library?

Just because I didn't find a library that totally suits my needs, and after creating a few SVG charts manually with Calc formulas, I decided to lose tens (hundreds?) of hours to develop a new one. Yes, it is about that stupid.

More specifically, I wanted SVG charts with real text (that you can copy), real links (that you can click on) and some CSS interactions on hovering chart (greatly inspired by Robbie Andrew awesome SVG charts), whereas most SVG charting libraries don't handle these elements very well (text being transformed into shapes).

SVG has a lot of advantages over raster images: infinite scalability, small file size (even more when gzipped), support for interactivity and animation, selectable and searchable text, easy to use for lightly modifying an image (like changing a color, moving a shape, changing text...), etc.

CSS is a very powerful language that can be used for for styling SVG, which makes possible large customisation without the need to learn a new API and its hundreds of styling parameters. It also enables to adapt SVG charts rendering depending on device characteristics (like width for targeting small devices for instance) or user preferences (e.g. light or dark color theme) thanks to media queries. See sections Customisation and How-Tos for examples on how to style charts using CSS.

You can find a lot of others SVG chart packages on PyPI which maybe better suit you needs, for example:

When should I use it?

You probably should NOT use this library at least in these cases:

  • If you want a static image (either for using it in a <img> html tag or just to open it in a picture viewer), the css interactions, the links, the copyable text will be useless. This library aims to create web-first charts.
  • For using the charts in a PDF file, a word processor or in a presentation program. They often handle badly css and the image will probably not render as in a web browser.
  • Only line, scatter, vertical bar and box plot types are available for now, so of course if you want a horizontal bar, pie, radar, treemap, sankey... chart, don't use it.
  • Customisation using dedicated parameters is limited, so if you want very fine customisation and don't want to use CSS you should probably prefer one of the above mentioned Python packages or tools like 🐍 matplotlib, 🇷 ggplot2, 📜 Apache ECharts, 🧮 LibreOffice Calc...
  • Lots of data points to draw:
    • For line charts with more than 100,000 points, result might be slow to display and svg file will be large. See example era5_moving_averages.svg: about 120,000 data points, 2MB svg file (600kB gzipped). Or test_large_dataset.py which creates a 600,000 points line chart.
    • For scatter charts, more than 10,000 data points can cause slowing. See example meteo.svg: 8760 circles, 800kB svg file (100kB gzipped).
  • Accessible chart: only a very few of all recommended SVG accessibility guidelines are implemented for now.

🚧 WIP 🚧

[!warning] ⚠️ It's still beta version, API is not stable yet and will probably break in the future!

Installation

With pip:

python3 -m pip install basic-svg-chart

As it does not have any dependency, you can also just download basic_svg_chart.py and import it as a simple python module.

Usage

import basic_svg_chart

# Create a SVG line chart and store it in a string
my_line_chart = basic_svg_chart.chart(
    chart_type = "line", # optional, "line" is the default value
    x = range(3),
    y = [[10, 20, 30], [15, 8, 22], [None, 15, 5]],
    width = 800, height = 500, # optional, default values: width = 1200, height = 800
)

# Add to html file
html_page = f"""<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" ><title>Chart example</title></head><body><h1>Line chart</h1><figure id="chart">
{my_line_chart}
'<figcaption>A <a href="https://developer.mozilla.org/en-US/docs/Web/SVG">SVG</a> chart</figcaption></figure><p>Made with Python.</p></body></html>"""

with open("/tmp/chart.html", "w") as outputfile:
    outputfile.write(html_page)

# Write a scatter chart to a file
basic_svg_chart.scatter_chart(
    x = range(2020, 2026),
    y = (100, 102.6, 103.7, 101.03, 99.9),
    y_ticks_interval = 10,
    title = "Example scatter chart",
    legend_position = None,
    fullscreen = True,
    output = "/tmp/chart.svg")

See real examples and simple tests examples for more.

Reference

This library has one chart() function with 5 aliases line_chart(), scatter_chart(), scatter_line_chart(), bar_chart() and box_plot_chart() with fixed chart type.

basic_svg_chart.chart(x, y, xy=None, chart_type="line", bar_param={'group_padding': 0.8, 'bar_padding': 1, 'group': "x", 'stack': False}, box_plot_param={'calculate_quantiles': False, 'whiskers': ("min", "max"), 'padding': 0.5, 'mean': False, 'outliers': False}, names=None, title=None, desc=None, lang=None, colors=None, width=1200, height=800, fullscreen=False, margin="auto", x_unit=None, y_unit=None, x_ticks=6, x_axis_discrete=True, x_ticks_margin=None, x_ticks_position="middle", y_ticks=6, y_ticks_interval=None, y_min=0, y_max=None, big_mark=None, decimal_mark=None, x_ticks_format="{:n}", y_ticks_format="{:n}", show_values=None, values_position="top", values_position_shift=None, values_format="{y}{y_unit}", show_only_hovered_value=True, tooltip_type=("title", "value"), title_tooltip_format=DEFAULT_TOOLTIP, extra_data=None, circles=4, extra_lines=None, legend_position="right", legend_background=None, css=None, notes=None, font_size=15, background_color="auto", dark_mode="user", pretty=False, output="string")

Create a SVG chart

Parameters:

x : Sequence[int | float | str] : The x values.

y : Sequence[Sequence[int | float | None]] | Sequence[int | float | None] : The y values. If multiple series must be drawn, must be a sequence of sequences. If some series has missing values, they have to be specified with None. If series sequence length < len(x), the last values will be missing.

xy: Sequence[Sequence[Sequence[int | float | str]]], optional : If x and y are not provided, xy must contain the data points expressed as a sequence of series, where each series is a sequence of points where each point is a sequence of 2 elements: x and y as (x, y).

chart_type : str | Sequence[str], optional, default "line" : The type of the chart, can be "line", "scatter", "scatter line", "bar" or "box plot". If a sequence is provided and there are multiple series, each series will have the specified type (based on sequence position, same as y).

bar_param: dict, optional, default {'group_padding': 0.8, 'bar_padding': 1, 'group': "x", 'stack': False} : Specific parameters for bar charts. * bar_param["group_padding"] (default 0.8) is a float between 0 and 1 defining the space used by the group of <rect> elements / the maximum available space between 2 groups of <rect>s. * bar_param["bar_padding"] (default 1) is a float between 0 and 1 defining the space used by each <rect> / the maximum available space between 2 <rect>s. * bar_param["group"] defines how bars are grouped, with 2 possibles values: "x" (the default) for grouping by x values (like line charts): first bar (on the left) is x1 for series1, then x1 for series2... "series" for grouping by series: first bar (on the left) is x1 for series1 then x2 for series1... * bar_param["stack"] (default False) defines if bars must be stacked for each x. When bars are stacked, the first series (as defined in y sequence order) will be the closest to 0, and then stack follow series order.

box_plot_param: dict, optional, default {'calculate_quantiles': False, 'whiskers': ("min", "max"), 'padding': 0.5, 'mean': False, 'outliers': False} : Specific parameters for box plot charts. * box_plot_param["calculate_quantiles"] (default False): if True, y values will be converted to [lower whisker, Q1, Q2, Q3, upper whisker]. Builtin method statistics.quantiles is used to calculate the values. * box_plot_param["whiskers"] (default ["min", "max"]): if box_plot_param["calculate_quantiles"] is True, define the metrics used for whiskers. Can be either "IQR" ([Q1-1.5IQR, Q3-1.5IQR], see https://en.wikipedia.org/wiki/Box_plot#Whiskers) or a couple (lower, upper) where lower and upper can be "min", "max" or a percentile as "Pn". * box_plot_param["padding"] (default 0.5): Define the width of the box as a percentage of the maximum possible width. * box_plot_param["mean"] (default False): if True, the mean will be added (and calculated if box_plot_param["calculate_quantiles"]) and represented as a diamond. * box_plot_param["outliers"] (default False): if True and box_plot_param["calculate_quantiles"] is True, the outliers will be added and represented as circles.

names : Sequence[str] | str, optional : Names of a the series. The position in the sequence must match the position of the series in y sequence. If not provided (or less names than the number of series defined in y), defaults to "Data series n" (with n incremental) or to title if there is just one series.

title : str, optional : The optional title of the chart. If provided, will be printed as a <text> element above the plotting area + a <title> element.

desc : str : The optional description of the chart, used in a <desc> element which is referenced by the <svg> aria-describedby attribute.

lang : str, optional : A BCP 47 language tag used in lang and xml:lang attributes added to the root <svg> element. If "fr" then big_mark parameter defaults to " " and decimal_mark to ",".

colors : Sequence[str], optional : The colors of the series. Can be a color name (e.g. "green"), a hex code (e.g. "#e91585") or a RGB triplet (e.g. "rgb(0, 191, 255)"). If not provided (or less colors than the number of series defined in y), defaults to Okabe-Ito palette if 8 series or less, and Viridis palette if 9 ≤ len(series) ≤ 20. If more than 20 series in y, colors must be provided.

width : int | float, optional, default 1200 : The width of the <svg> element. Used in a viewbox attribute (viewBox="0 0 {width} {height}"). Will also be used in a <svg> width attribute if fullscreen = False.

height : int | float, optional, default 800 : The height of the <svg> element. Used in a viewbox attribute (viewBox="0 0 {width} {height}") Will also be used in a <svg> height attribute if fullscreen = False.

fullscreen : bool, optional, default False : If False (the default), the root <svg> element will have width and height attributes as specified in the eponymous parameters.

margin: str | Sequence[int | float], optional, default "auto" : Define the margins around the chart area. Defaults to "auto" which try to calculate « optimal » margins depending on all elements of the chart (title, legend, units, notes...). Otherwise, must be a sequence of 4 numbers which define [top, right, bottom, left] margins (in this order) in px.

x_unit : str, optional : An optional unit for x values. If specified, will be drawn below the x axis (and centered). Can also be used in x_ticks_format, values_format and title_tooltip_format parameters as "{x_unit}".

y_unit : str, optional : An optional unit for y values. If specified, will be drawn above the y axis. Can also be used in y_ticks_format, values_format and title_tooltip_format parameters as "{y_unit}".

x_ticks : int | Sequence[int | float | str], optional, default 6 : The ticks drawn in the x axis. Can be either an integer representing the number of ticks to show (see x_axis_discrete), or a sequence of values.

x_axis_discrete : bool, optional, default True : If True and x_ticks is an integer, the x ticks values will be pulled from x values, which can lead to an irregular scale. If False and x_ticks is an integer, the x ticks will be equally distributed from min(x) to max(x), even if the ticks are not included in x values, leading to a regular scale.

x_ticks_margin: int | float, optional, default None : The margin between the x ticks and the left and right sides of the chart area. Defaults to None, which means: * Line or scatter charts: 0; * Bar charts: the space between the left side of the first rectangle and the left side of the chart area; * Box plot charts: 1.5 * the space between the left side of the first rectangle and the left side of the chart area.

x_ticks_position: str, optional, default "middle" : The position of the x ticks: either "middle" (the default) for having ticks centered (same as the tick label) or "external" for having ticks around the tick label. All other values will remove the x ticks (but keeping the vertical dotted lines and labels).

y_ticks : int | Sequence[int | float], optional, default 6 : The ticks drawn in the y axis. Can be either an int representing the number of ticks to show (not used if y_ticks_interval provided), or a sequence of values.

y_ticks_interval : int | float, optional : If y_ticks is not a sequence, y_ticks_interval defines the fixed interval between each tick, from y_min to y_max.

y_min : int | float | None, optional, default 0 : The min value drawn on the y ticks. If None (and y_ticks is not a sequence), will be defined as min(y).

y_max : int | float, optional : The max value drawn on the y ticks. If not provided and y_ticks not provided as a sequence, will be defined as max(y), or will be computed using y_ticks_interval if provided.

big_mark : str, optional : Can be used to replace default "_" big mark separator when some numbers are formatted with "{:_}" in x_ticks_format, y_ticks_format, values_format or title_tooltip_format. In such a case, dont use "_" as literal text in these formats as it will also be replaced by big_mark.

decimal_mark : str, optional : Can be used to replace default "." decimal mark when some numbers are formatted with "{:.1f}" in x_ticks_format, y_ticks_format, values_format or title_tooltip_format. In such a case, dont use "." as literal text in these formats as it will also be replaced by decimal_mark.

x_ticks_format : str, optional, default "{:n}" : The string format used to format x ticks values. "{x}" (with formatting options) will be replaced by the tick value and "{x_unit}" by the corresponding parameter.

y_ticks_format : str, optionall, default "{:n}" : The string format used to format y ticks values. "{y}" (with formatting options) will be replaced by the tick value and "{y_unit}" by the corresponding parameter.

show_values : str | Sequence[int | float | str], optional : If provided, the specified values will be drawn on the chart (as <text> elements), next to the corresponding data points. Can be either "all" for displaying all values, "last" for displaying only last values, or a sequence of x values for displaying only the corresponding y values.

values_position : str, optional, default "top" : Where the value will be drawn relatively to the corresponding data point when show_values is provided or tooltip_type contains "value". Can be one of "top", "right", "bottom", "left", "fixed above chart" and "fixed under chart".

values_position_shift : Sequence[int | float], optional : The specific shift in px defined as (x, y) relatively to the data points where to draw values when show_values is provided or tooltip_type contains "value". Defaults to (0, -12) when values_position="top", (0, 20) when "bottom", (12, 0) when "right" and (-12, 0) when "left".

values_format : str | Sequence[str], optional, default "{y}{y_unit}" : The string format used to format values when show_values is provided or tooltip_type contains "value". "{y}" will be replaced by the y value, "{x}" by the x value, "{name}" by the series name, "{extra}" by the corresponding extra_data for the point/series hovered, and "{x_unit}" and "{y_unit}" by the corresponding parameters.

show_only_hovered_value : bool, optional, default True : If True and tooltip_type contains "value" or "vertical line" and (show_values is defined or chart_type contains "scatter"), when hovering a specific value then all other values for the same series will be hidden and other circles will have reduced opacity.

tooltip_type : str | Sequence[str] | None, optional, default "value" : The type of tooltip to display when hovering a data point. Can be a sequence containing "title", "value", "vertical line" or None to display no tooltip. * "value" will use <text> elements hidden by default and shown when hovering. * "title" will use <title> elements inside each <circle> elements representing the data points. These <title> elements are not rendered in mobile browsers. * "vertical line" will show a vertical line and all y values when hovering a x virtual vertical line. It doesn't work well if lots of x values.

title_tooltip_format : str | Sequence[str], optional, default "{name}: x = {x}{x_unit}, y = {y}{y_unit}" : The string format used to format tooltip when tooltip_type contains "title". "{y}" will be replaced by the y value, "{x}" by the x value, "{name}" by the series name, "{extra}" by the corresponding extra_data for the point/series hovered, and "{x_unit}" and "{y_unit}" by the corresponding parameters. If a sequence is provided and there are multiple series, each series will have the specified tooltip format on hover (based on sequence position, same as y).

extra_data : Sequence[Sequence[int | float | str]] | Sequence[int | float | str], optional : Extra data that can be used in title_tooltip_format and values_format. Must be the same type as y: each data point will match the specified extra data based on sequence (of sequence) position.

circles : int | float, optional, default 4 : The <circle> radius in px (as r attribute). Used when chart_type contains "scatter", or show values is provided, or tooltip_type is not None.

extra_lines : Sequence[dict] | dict, optional : Extra horizontal or vertical lines to draw on the chart. Each line is defined by a dictionary containing between 1 and 4 keys (multiple lines can be drawn using a sequence of dictionaries): * 'x' for a vertical line or 'y' for a horizontal line, the value representing where to draw the line in the x or y axis. Must be the same type as x and y, multiple lines are drawn is a sequence if provided. * 'color' (optional, default "black"): the color of the line, as a color name (e.g. "green"), a hex code (e.g. "#e91585") or a RGB triplet (e.g. "rgb(0, 191, 255)"). * 'thickness' (optional, default 2): the stroke-width attribute of the <line> element. * 'position' (optional, default "back"): whether the lines are drawn behind ("back") or in front of ("front") the plots.

legend_position : str | None, optional, default "right" : Where to draw the legend (containing series names). To draw the legend outside the plotting area, use one of "top", "right", "bottom", "left". To draw the legend inside the plotting area, use one of "top left", "top right", "bottom left", "bottom right". None if legend must not be displayed.

legend_background : str, optional : If provided, the background color of the legend (no background by default), as a color name (e.g. "green"), a hex code (e.g. "#e91585") or a RGB triplet (e.g. "rgb(0, 191, 255)").

css : Sequence[str] | str, optional : The optional css declarations to add to the <style> element.

notes : str | Sequence[str], optional : The optional notes to display as a <text> element above the chart. Can contain svg elements (such as <a> for example) and raw text. If a note starts with "<i>", text will be displayed in italic. If it starts with "<b>", text will be displayed in bold. If a sequence is provided, each element will be treated as a new line, using <tspan dy="1.5em">.

font_size : int | float, optional, default 15 : The font size (in px) of the root <svg> element.

background_color : str | None, optional, default "auto" : If not None, draw a <rect> filled with the specified color behind the chart. Can be a color name (e.g. "green"), a hex code (e.g. "#e91585"), or a RGB triplet (e.g. "rgb(0, 191, 255)"). Defaults to "auto", which translates to "black" if dark_mode="force", otherwise "white". If dark_mode="user", the background <rect> will be hidden if the browser is configured in dark color scheme.

dark_mode : str | None, optional, default "user" : If "user", add a few css properties to handle color scheme preference of user on web browser. If "force", display the chart with a black background (instead of white in light mode) and white texts and axis lines (instead of black in light mode). Otherwise, use light mode (white background + black text and axis lines).

pretty : bool, optional, default False : If True, the <svg> output will be prettified using xml.etree.ElementTree.indent() function. If False, the <svg> output will be minified (fits in one line).

output : str, optional, default "string" : If "string", the function will return the <svg> content as a string. If "etree", the function will return the <svg> content as a xml.etree.ElementTree.Element. Otherwise, will be interpreted as the name (absolute or relative path) of the svg file to create containing the chart. In such a case, the function will also return the xml.etree.ElementTree.Element.

Returns:

str or xml.etree.ElementTree.Element : SVG chart, either as a string if output="string" or a xml.etree.ElementTree.Element otherwise. If output is the name (absolute or relative) of a file, the SVG content is written to that file and the function returns the xml.etree.ElementTree.Element.

Customisation

There are several ways to cutomise the charts created with this library.

CSS

You can simply use the css parameter and add unlimited CSS declarations to the SVG chart. CSS is a very powerful language which can do a lot for styling SVG. Your custom css declarations will be added at the end of the <style> element so that they take precedence other the default declarations added by the library, in case you want to override some.

For example, if you want a 20px italic title, Liberation Mono font, green x axis, blinking y unit, no vertical dotted gridlines, and move legend, you can use a css parameter like:

import basic_svg_chart as bsc

bsc.scatter_chart(
    x = range(11),
    y = (range(11), [5] * 8),
    title = "CSS customisation example",
    y_unit = "€uros",
    css = (
        "text.title {font-size: 20px; font-style: italic;}",
        ":root {font-family: 'Liberation Mono';}",
        "#abscissa_lines > line {stroke: green;}",
        "#abscissa_text {fill: green;}",
        "#ordinate > text.unit {animation: blinker 1s linear infinite;}",
        "@keyframes blinker {50% {opacity: 0;}}",
        "#vertical_dotted_lines > line[stroke-dasharray] {display: none;}",
        ".legend {transform: translate(-300px, 500px);}"
    ),
    output = "/tmp/chart.svg"
)

See also Examples, most have a few custom css declarations. The How-Tos section gives also a few simple CSS tricks.

You can find a complete CSS guide on MDN.

Programmatically

By using the output="etree" parameter, the function will return the chart content as a . Then you can modify whatever you want before converting the chart to a string (using ) or writing it to a file (using ).

See also Examples, some are programmatically modified (like carte.py, pop.py, ips.py, secten.py).

Manually

SVG is quite a powerful and easy-to-understand format. So you can also manually modify the svg generated file with any text editor for adding, removing, changing some elements for one-time adjustments. In such a case, you should probably use pretty=True parameter (or prettify the svg content with your text editor).

With a vector graphics editor?

The svg generated file can be graphically modified using a vector graphics editor, like Inkscape.

⚠️ Note that SVG editors don't necessarily handle well CSS, so you can have issues with that. For instance, with default dark_mode parameter, Inkscape seems not to show the chart. You may have to comment (or remove) the line :root {color-scheme: light dark;} in the <style> element before opening the file with Inkscape. And after the file has been modified in Inkscape, it seems some CSS declarations are slightly modified and don't work anymore (like circle replaced by .circle), so you probably should be careful with that too.

Compatibility

Tested on Linux Mint 22, with Python 3.10 to 3.14, and debian 13 + python 3.13. It probably works on other OS too, but it has not been tested.

Note that some examples rely on Linux platform, a few scripts must be changed to work on Windows or MacOS, like specifying encoding="utf-8" when reading csv files or changing the function to open the svg file after creation using subprocess.call(["start", out_file], shell=True) (see at the bottom of run_examples.py).

Chart render is not exactly the same on different web browsers, it has only been tested on Firefox and Chromium.

Old python versions

[!warning] This old python version is not maintened!

This library requires Python ≥ 3.10 to work. If you are using 3.6 ≤ Python < 3.10, you can use the file old/basic_svg_chart.py (version 0.1.0), which is compatible with Python ≥ 3.6 but with a few differences/limitations:

You can see the changes made for version 0.1.0 in this commit.

For Python < 3.6, it won't work at least because of heavy use of f-strings.

How-Tos

Handle y-axis scale with negative values

The are several parameters for configuring y axis: y_ticks (default 6), y_ticks_interval, y_min (default 0) and y_max. An important point is that when your dataset contains positive and negative values, y_min must be specified as it defaults to 0, either by fixing it to None (in which case y_min will be computed as min(y)) or the desired negative value. Example:

import basic_svg_chart

basic_svg_chart.line_chart(
    x = range(10),
    y = ([4, 4, -2, 0, -4, -3, -2, -1, -3, 1], range(10), [5] * 7),
    y_min = -5, # or y_min = None which is equivalent to y_min = 4
    y_ticks_interval = 1,
    output = "/tmp/chart.svg"
)

See examples inflation.py, era5 or roni.

Change margins around the chart (add extra space on the right because legend is truncated for instance)

The parameter margin (which must be a sequence of four numbers defined as [top, right, bottom, left]) can be used to change default margins. If you first want to know what are the default calculated margins of you chart, you have to enable logging first. Example:

import logging
import basic_svg_chart

logging.basicConfig(level = logging.INFO, format = "[%(levelname)s] - %(message)s")

basic_svg_chart.line_chart(
    x = range(10),
    y = range(10),
    names = "TOO LARGE NAME 😭",
    output = "/tmp/chart.svg"
)

# Log will output:
# [INFO] - margin: (27, 190, 34.50, 47)

basic_svg_chart.line_chart(
    x = range(10),
    y = range(10),
    names = "TOO LARGE NAME 😀",
    margin = (27, 230, 34.50, 47), # for adding 40px to the right margin
    output = "/tmp/chart.svg"
)
Remove horizontal and/or vertical dotted tick lines

You can hide the default dotted tick lines with css:

import basic_svg_chart

basic_svg_chart.line_chart(
    x = range(10),
    y = range(10),
    css = (
        "#horizontal_dotted_lines > line[stroke-dasharray] {display: none;}", # hide only horizontal dotted lines
        "#vertical_dotted_lines > line[stroke-dasharray] {display: none;}", # hide only vertical dotted lines
        # "line[stroke-dasharray] {display: none;}", # hide both in a single CSS declaration
    ),
    output = "/tmp/chart.svg"
)
Move some elements (legend, ticks labels, values...)

Use css property transform (or more directly the more recent translate property) to move some elements of the chart. For example, if you want to move y unit to the left, x tick labels to the top and change legend position:

import basic_svg_chart

basic_svg_chart.line_chart(
    x = range(2020, 2025),
    y = ([100, 102, 101.4, 103.8, 104.8], [100, 100.3, 99.7, 99.2, 99.5]),
    names = ("Increasing index", "Decreasing index"),
    y_unit = "2020=100",
    y_ticks = 12,
    legend_position = "top",
    css = (
        "g#ordinate > text.unit {transform: translate(-20px);}", # Move y unit to the left
        "#abscissa_text {transform: translate(0, -4px);}", # Move x tick labels to the top
        "#legend1 {translate: 500px 50px}", # Move series 1 legend (same as `{transform: translate(500px, 50px)`)
        "#legend2 {translate: 700px 110px}", # Move series 2 legend
        ".legend > line {display: none;}", # Optionally, hide legend symbols
    ),
    margin = (30, 20, 30, 50), # reduce top margin because legend has been moved
    output = "/tmp/chart.svg"
)

See also examples: nvidia.py (move y unit to the left and x ticks values to the top), roni.py (move specific values shown on chart), death.py (move mean value for box plot), electricite.py (move x ticks labels to put them between 2 ticks), energy.py (manually move last values text elements to display them in the middle of the corresponding bar), heatmap.py (move legend text elements next to the corresponding series).

Rotate text elements by 90° (y unit, x ticks labels...)

Use css property writing-mode to change text direction. For example, if you want to put y unit on the left of the ordinate axis with text rotated by 90°, and rotate x tick labels in the reverse direction:

import basic_svg_chart
import random

y = [100]
y = [y := y + [y[-1] + random.random() - 0.5] for i in range(99)][-1]

basic_svg_chart.line_chart(
    x = range(1900, 2000),
    x_ticks = 21,
    y = y,
    y_unit = "Index (1900=100)",
    tooltip_type = None,
    css = (
        "g#ordinate > .unit {writing-mode: sideways-lr; transform: translate(-25px, 300px);}",
        "g#abscissa_text > text {writing-mode: vertical-rl;}",
    ),
    margin = (20, 20, 60, 60),
    legend_position = "bottom right",
    output = "/tmp/chart.svg"
)

See example life_satisfaction.py.

Lower opacity of other bars of the same series on hover

Use css property opacity to lower opacity of some specific elements. Example:

import basic_svg_chart

basic_svg_chart.bar_chart(
    x = range(10),
    y = (range(10), [-i for i in range(1, 11)], [4] * 5 + [5] * 2 + [None] + [3]),
    y_ticks = [-10 + 5*i for i in range(5)],
    bar_param = {'group': 'series', 'group_padding': 0.9, 'bar_padding': 0.9},
    css = (
        "g.series:hover > rect {opacity: 0.1;}"
        "g#series_plots > g.series > rect:hover {opacity: 1;}",
    ),
    values_position = "fixed above chart",
    values_format = "{name}: ({x}, {y})",
    legend_position = None,
    fullscreen = True,
    output = "/tmp/chart.svg"
)

See example rain.py.

Change font family

Use css property font-family. Note that text height and width differ depending on font family, so you may have to move some svg elements, change margin or text size to keep the chart readable. Example:

import basic_svg_chart
import random

basic_svg_chart.scatter_chart(
    x = range(10),
    y = [random.random() for i in range(10)],
    y_ticks = [i/10 for i in range(11)],
    title = "Scatter chart with cursive font family",
    css = "svg {font-family: cursive, system-ui;}",
    output = "/tmp/chart.svg"
)

See example pop.py.

Change title (or other text element) font size

Use css property font-size to lower or increse font-size of text elements. Example:

import basic_svg_chart

basic_svg_chart.chart(
    chart_type = "scatter line",
    x = [f"01/{i:02}" for i in range(1, 13)],
    y = [10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10],
    title = "Scatter line chart with a long title too large to fit in the image with default font-size",
    legend_position = None,
    css = "text.title {font-size: 1em;}", # default title font-size = 1.4em
    width = 800, height = 500,
    output = "/tmp/chart.svg"
)

See example era5_annual.py.

Use a dark theme

By default charts are displayed with a dark theme for users requesting a dark color scheme in their browser (and with a light theme for users preferring a light color scheme). To change this behaviour, use parameter dark_mode: "force" will show dark theme charts for all users, None will show light theme charts for all users. To change some styles for dark (or light) theme, use prefers-color-scheme CSS media feature.

For example, changing several colors for dark theme users can be done like that:

import basic_svg_chart

basic_svg_chart.chart(
    x = range(10),
    y = [range(10), [(i + 1)/2 if i % 2 == 0 else -i/3 for i in range(10)]],
    y_ticks = [-5, 0, 5, 10],
    title = "Customizing dark theme",
    notes = "Using <a href='https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme' target='_blank'>prefers-color-scheme</a> CSS media feature.",
    colors = ("orange", "black"),
    css = """
    @media (prefers-color-scheme: dark) {
        .color2 {stroke: DeepSkyBlue;}
        .color2 text {fill: DeepSkyBlue;}
        text.title, text#notes {fill: greenyellow;}
        line[stroke-dasharray] {stroke: red;}
        a {fill: hotpink;}
    }""",
    output = "/tmp/chart.svg"
)

See example energy.py.

Use a specific locale

if you want to use {:n} format with a specific locale, you have to set it first with locale.setlocale(...). Example:

import basic_svg_chart
import locale
print(locale.getlocale())
# locale.setlocale(locale.LC_ALL, "")
locale.setlocale(locale.LC_ALL, "fr_FR.utf8")

basic_svg_chart.line_chart(x = [x/100 for x in range(11)], y = range(0, 10001, 1000), output = "/tmp/chart.svg")

Other limitations

Probably a lot, but here are some:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

basic_svg_chart-0.2.2.tar.gz (89.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

basic_svg_chart-0.2.2-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

File details

Details for the file basic_svg_chart-0.2.2.tar.gz.

File metadata

  • Download URL: basic_svg_chart-0.2.2.tar.gz
  • Upload date:
  • Size: 89.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for basic_svg_chart-0.2.2.tar.gz
Algorithm Hash digest
SHA256 4cf8d38517a488d5053d5098d1c013863929e97953c50d21b4abd673cd3fca10
MD5 1f0ef63b43af3af27a8cbd5137e4d1b6
BLAKE2b-256 5a5c0d50f23e417aa76a2db7fceb62cc354b020abb06267d65d1f4a09f7c73af

See more details on using hashes here.

File details

Details for the file basic_svg_chart-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for basic_svg_chart-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a52f6093ebcc12c1f110aba0a63317a491a2290078ce4df38b08e6b92c807780
MD5 55b530ba1c7a43fc5391269b57ff164b
BLAKE2b-256 9d06cb38239064b80d2d6132bf85a1a3ec4106f4dccafb757198b371b2c43274

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page