Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] use CSS variables for plot attributes #4915

Closed
nicholasdgoodman opened this issue Jun 11, 2020 · 6 comments
Closed

[Feature Request] use CSS variables for plot attributes #4915

nicholasdgoodman opened this issue Jun 11, 2020 · 6 comments

Comments

@nicholasdgoodman
Copy link

I want to be able to manage color theming for charts and graphs the same way I would the remainder of the page, via CSS. A full-scale solution seems like it would be a significant effort, since components like the dcc.Graph take various 'layout' declarations e.g. 'plot_bgcolor' which are converted to inline style attributes on the DOM.

Workarounds / Alternatives

The two workarounds that I have been able to use so far are to declare colors transparent, and then via reverse-engineered CSS selectors, I can get the desired behaviors:

dcc.Graph argument

'layout': {
    'title': 'Dash Data Visualization',
    'paper_bgcolor': 'transparent'
    'plot_bgcolor': 'transparent'
}

CSS

body {
    background-color: #000;
    color: #FFF;
}

.dash-graph text {
    fill: #FFF!important;
}

(Note the required !important to override the inline style declaration.)

Feature Request

Modern browsers support CSS variables which can be used both in for declared and inline styles. However, the dcc.Graph library does not accept these values because it unnecessarily attempts to parse the provided color string and convert it to rgba(...) format.

I would like to be able to:

'layout': {
    'title': 'Dash Data Visualization',
    'paper_bgcolor': 'var(--chart-area-color)`,
    'plot_bgcolor': 'var(--main-background-color)'
}

and without any processing / parsing, simply pass the supplied string straight to the rendered HTML inline style:

<svg class="main-svg" ... style="background: var(--main-background-color);">

Doing so means we can manage coloring of charts and graphs from CSS only without having to modify the dash code.

(Similarly, I see no compelling reasons that named colors or colors supplied in #FFF format should be forcibly converted to rgba(...) format either).

Get more by doing less!

@alexcjohnson alexcjohnson transferred this issue from plotly/dash Jun 11, 2020
@alexcjohnson
Copy link
Collaborator

Thanks @nicholasdgoodman - I moved this request to the plotly.js repo, as that's where this color sanitizing happens (as well as everything else internal to the figure prop of dcc.Graph). If you find that this request applies to any other Dash components please open a new issue in the relevant component repo - although my hunch is that in as far as styles like this are used in other components they likely already behave as you would like.

As to plotly.js and its color handling, there are a few reasons for us to sanitize colors here:

  • Portability: able to be rerendered on its own or within a different page. Right now perhaps the most obvious consequence of this is exporting the graph in formats not supported natively by the browser, which we have to do by passing the graph spec to another process to render and then convert.
  • Blended or calculated colors: there are times we need to manually blend two or more colors together, or pick a high-contrast color automatically based on a user-supplied. It's possible there's a way to do this with css colors, ie figure out how the browser would interpret the variables and use that in our calculations, but then we'd also need to know to redo that part of the render if you change those variables...
  • Multiple renderers: some trace types have both SVG and WebGL variants, that look nearly identical but are drawn completely differently behind the scenes. Again, the WebGL version would need to materialize any css variables and respond if they change.

These issues may have solutions (or may not, I don't actually know) but I hope this makes clear that it's not as easy as "stop converting to rgba"

Plotly does have some functionality in Dash Enterprise that serves a similar purpose to what you're describing; it's largely based on layout.template https://plotly.com/python/templates/

@nicholasdgoodman
Copy link
Author

nicholasdgoodman commented Jun 11, 2020

@alexcjohnson

I see due to the 3 mentioned features / capabilities, there are additional complexities I am unfamiliar with as our application uses none of these (exporting, blended colors, or WebGL compoents).

That being said, here are some other related asks that could achieve the same end goal of CSS-driven graph theming.

Alternative 1: Ability to Opt-Out of Inline Style Attributes

When unspecified, colors for the graph, plot area, and graph text are filled in with preset values inline. This means even with clever CSS selectors, it is necessary to force overrides with !important properties. It would be good to have a means to prevent the inline styles from being generated, e.g.:

(Python Syntax)

'layout': {
    'title': 'Dash Data Visualization',
    'paper_bgcolor': None,  # alternative to 'transparent', prevents 
    'plot_bgcolor': None    # inline style color from appearing in DOM
}

The equivalent JS form would be explicitly setting these values to null (or perhaps another falsey value).

Alternative 2: Provide Additional Classes for Easier Selection

(This would be a nice to have regardless) - Even if there is no simple way to remove inline styles outright; elements which do get this treatment should be clearly marked with a CSS class simpler selection and overrides. For example, plot_bgcolor is applied inline to element:

<svg class="main-svg" ... style="background-color: rgba(255,255,255,1.0);"> <!-- want to select this -->
<svg class="main-svg" ...>
<svg class="main-svg" ...>
<svg class="main-svg" ...>

However, there are many such elements in the DOM; providing additional classes such as plotly-plot and plotly-paper would allow for much simpler CSS rules, even if we still have to resort to !important to override the inline styles.

<svg class="main-svg plotly-plot" ... style="...">
<svg class="main-svg" ...>
<svg class="main-svg" ...>
<svg class="main-svg" ...>

Alternative 3: Ability to Explicitly Declare Inline Style or Class

This would be a proper "new feature" which is probably the most expensive, but also the most flexible. Instead of limiting users to specifying component colors, give them the ability to override the rendered HTML directly (this only applies to SVG components):

(Python Syntax)

'layout': {
    'title': 'Dash Data Visualization',
    'paper_style': 'background-color: var(--chart-area-color)',
    'plot_class': 'dash-plot-custom-class'
}

@alexcjohnson
Copy link
Collaborator

Your application likely does use blended or calculated colors even if you didn't ask for them explicitly - they show up a lot in hover labels, among other places.

There was discussion in #2355 about potentially switching to presentation attributes rather than styles, and AFAIK these have lower precedence so may avoid the need for !important. That option is certainly still up for discussion, though I'm a bit worried about that causing plots to pick up unwanted CSS overly-broadly targeted elsewhere on the site.

Thus far we haven't considered classes within the plot to be part of the public API - so in principle they (and the element structure) could change at any time. We could imagine changing that stance, and documenting and committing to these classes. But this still comes with all the pitfalls I mentioned above, as would an additional CSS or custom class API.

@tony
Copy link

tony commented Aug 6, 2023

@nicholasdgoodman Can you rename the title to be about CSS variables? That may make it easier to find.

Correct me if I'm mistaken if that's not the intention - if this isn't about CSS variables I will make a dedicated issue for it

@alexcjohnson alexcjohnson changed the title [Feature Request] Pass color strings directly to the rendered HTML without converting to rgba [Feature Request] use CSS variables for plot attributes Aug 15, 2023
@alexcjohnson
Copy link
Collaborator

@tony it's been long enough that sure, this issue can be about CSS variables even if there might have been other pieces in the past.

I'll just note that due to blending, WebGL, and exporting we probably can't simply use CSS variables directly in the rendered SVG, we'd need to materialize them at the main div level and use that materialized value to render, and if we want to support dynamic styling we'd need to watch for changes in those variables. And for exporting we'd need to also insert those values back into the figure spec.

@gvwilson
Copy link
Contributor

gvwilson commented Jul 5, 2024

Hi - we are trying to tidy up the stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for a while, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. Alternatively, if it's a request for tech support, please post in our community forum. Thank you - @gvwilson

@gvwilson gvwilson closed this as completed Jul 5, 2024
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

No branches or pull requests

4 participants