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

Add legend 'auto' x|y and/or 'container' (x|y)ref #1199

Closed
salim-b opened this issue Nov 25, 2016 · 48 comments
Closed

Add legend 'auto' x|y and/or 'container' (x|y)ref #1199

salim-b opened this issue Nov 25, 2016 · 48 comments
Labels
bug something broken feature something new

Comments

@salim-b
Copy link
Contributor

salim-b commented Nov 25, 2016

The problem is that the horizontal legend overlaps the x-axis title. It occurs if the legend is positioned below (rather than to the right of) the plot area using layout = {legend: {"orientation": "h"}};. It aggravates in combination with multiline x-axis titles (using <br> tags).

Currently there's no way to control the spacing between the legend and the plotting area. Everything is auto-scaled, it is useless to set the bottom margin (layout = {margin: {"b": ...}};) in this case because it refers to the space below the legend. The only way to make the whole x-axis title visible is to increase the height of the whole plot until the autoscaling sufficiently spreads the legend and the plotting area apart.

I try to illustrate the problem with the following 3 images which differ only in frame height:

height 700px:
example_height700

height 1000px:
example_height1000

height 1300px:
example_height1300

Here is the above plot hosted on plot.ly.

@n-riesco
Copy link
Contributor

This is happening because layout.margin.b is set to 0 and the default position for horizontal legends is:

x: 0,
xanchor: 'left',
y: 1.1,
yanchor: 'bottom'

@etpinard Would it make sense to make the defaults smarter and check the value of layout.margin.b?

@salim-b
Copy link
Contributor Author

salim-b commented Nov 25, 2016

... and check the value of layout.margin.b?

I don't think layout.margin.b is central to this. If you play around a little with different combinations of layout.margin.b and layout.legend.yanchor, you quickly see that in the plot above you'll get nowhere desirable... actually the default of layout.legend.yanchor, which seems to be top not bottom (at least when I'm plotting in R), leads to the best results.

The problem in my eyes is that – when layout.legend.orientation is horizontal and the rest of the legend positioning parameters left to their default values – the legend overlaps the plotting area in the first place. In the default case the legend should always be placed below the x-axis, then it would be fine.

@etpinard

This comment has been minimized.

@herrgruebner
Copy link

I was having a similar issue with the horizontal legend overlapping x axis values, when the x axis values were long enough, like dates. I'm adding this here because it's the only issue that comes up when you google it, and it seems related. This happens with only setting {legend: 'horizontal'} in the layout and nothing else.

legend override

I tried a couple of different things, like playing with layout.legend.yanchor and the margins, but the legend doesn't appear to be affected by margins, it stays in the same place relative to the dates, and yanchor shifts it a little bit but it remains on top of the x axis ticks.

In the end my solution was to absolutely position the legend using
legend: {
"orientation": "h",
xanchor: "center",
y: 1.2,
x: 0.5
},

This has the side effect of putting the legend on top of the graph, but you can position it below the graph by lowering the Y value. It appears that the default X and Y values according to the docs (1, 1.2) are changed to a different value when the legend is set to horizontal, which makes sense, but should also be reflected in the documentation here:

https://plot.ly/javascript/reference/#layout-legend

I chose to put it above the graph because I know my x axis values are going to change in length and the graph is being iframed into a small spot, so I don't want to waste space. Not super pretty or anything, but a reasonable workaround.

legend override 2

Hopefully the horizontal legends are changed so that it will take into account x axis tick length automatically, or there's another easy way to do it I haven't found.

@ck37

This comment has been minimized.

@jinuem

This comment has been minimized.

@hy9be

This comment has been minimized.

7 similar comments
@suribabu39

This comment has been minimized.

@anafziger

This comment has been minimized.

@kiezuz

This comment has been minimized.

@FrantisekGazo

This comment has been minimized.

@yunxileo

This comment has been minimized.

@allanelder

This comment has been minimized.

@tabuechn

This comment has been minimized.

@ghost

This comment has been minimized.

@salim-b

This comment has been minimized.

@nzjrs

This comment has been minimized.

@IFFranciscoME

This comment has been minimized.

@nzjrs

This comment has been minimized.

@vladimirlukyanov

This comment has been minimized.

1 similar comment
@MichalSzura

This comment has been minimized.

@salim-b
Copy link
Contributor Author

salim-b commented Oct 16, 2017

+1

Although I appreciate the great demand for a fix of this issue, I doubt that all the "+1" comments (and the thereby triggered e-mail notifications) will eventually help to motivate the plotly developers to finally implement a solution for the problem. So just use GitHub reactions to express your support, please 😉

@jiteshkharat53

This comment has been minimized.

@alexcjohnson
Copy link
Collaborator

Digging into this a little in relation to #2243 - the background:

  • Legends are positioned in paper-referenced coordinates - those are the coordinates where the bottom left of the plotting area (excluding the margins in which we draw axis labels etc) is (0,0)
  • The default position is x=0, y=-0.1, xanchor='left', yanchor='top' - so the left edge aligned with the left edge of the plotting area, and the top in the margin, one tenth of the y axis length below the plotting area, on the theory that axis labels typically fit within that gap - but of course that's not always true!
  • So if you know the size of the plot AND the area needed for axis labels and title, you can choose legend.y such that there will be no overlap.
  • But if you need this to work with dynamic plot size or axis label length, the auto-margin mechanism we have (which is used right now to increase the margin in order to keep the legend from extending outside the visible area and will soon be used to ensure long axis labels are always visible, see automatic margins for long labels #2243), CANNOT be used as is to keep the legend from overlapping axis labels.

I see two possible ways to go here. The first is less of an addition to what we currently have, but the second I think would be more powerful and probably easier to implement too:

  1. Have the auto-margin system automatically change legend.y. When legend.y is not explicitly set, it would have to have an 'auto' value or something, then the auto-margin system would have to figure out how to combine space needed for the axis labels with space needed for the legend. But this is still problematic: what if you want it at the top and you have a top x axis whose labels it needs to avoid? Would we need 'auto-top' and 'auto-bottom'? That sounds awkward, and there may be other possibilities I'm not thinking of.
  2. Alternatively, allow the legend to be positioned in other coordinates - I'm thinking of the 'container' coordinates as proposed in Chart Title Alignment #882 for chart titles, in which (0,0) is the absolute bottom left corner including margins. Then we could default a horizontal legend to x=0, xanchor='left', xref='paper' (that wouldn't change) and y=0, yanchor='bottom', yref='container' (that part is new, though the result would be about the same as what we have now. In addition we could add pad attributes as also suggested in Chart Title Alignment #882, which would add a pixel buffer between the legend and the edge of the div, and between the legend and the plot or axis labels) - and at that point, the auto-margin system could simply reserve space for anything container-referenced (including the title 🎉 ) before fitting the other things in.

@yniknafs

This comment has been minimized.

@nicolaskruchten
Copy link
Contributor

nicolaskruchten commented Nov 20, 2019

The new legend position will depend on the tick label dimensions

Is the mechanism here because longer labels means pushing the margins up means in effect moving the (0,0) coordinate that the paper/domain coordinate space works within?

@nicolaskruchten
Copy link
Contributor

I think I'm understanding the problem and suggested solutions better now... the container ref idea sounds like a pretty good one as a low-level control system. We may want to layer on top of that a "placement" enum that would be the 4 corners and 4 faces of the rectangle, which would automatically set anchors and refs to container etc so that orientation="h" with placement="bottom center" would do the right thing and play well with automargins?

@etpinard etpinard self-assigned this Nov 22, 2019
@etpinard
Copy link
Contributor

etpinard commented Jan 6, 2020

Moved to 1.53.0

@etpinard etpinard modified the milestones: v1.52.0, v1.53.0 Jan 6, 2020
@nicolaskruchten nicolaskruchten modified the milestones: v1.53.0, v1.54.0 Jan 30, 2020
@etpinard etpinard removed their assignment Mar 12, 2020
@nicolaskruchten nicolaskruchten modified the milestones: v1.54.0, v1.55.0 Mar 15, 2020
@gonzofish
Copy link

Is there any update on this? I have some legends with a lot of text, the text is dynamic, so I can't do much about hose long the text is. When the chart generates, the legend overlaps the x-axis legend considerably.

Is there anything the community can do to help?

@nicolaskruchten
Copy link
Contributor

If someone wants to take on some implementation work, we'd be happy to iterate on a design and review some PRs, but at the moment this is no longer on our short-term roadmap.

If you work for an organization with a software budget, you could sponsor this feature to bump it up our priority list.

@gonzofish
Copy link

  1. I didn't know sponsoring a feature could be a thing
  2. I'll try to take a look to help out

@nicolaskruchten
Copy link
Contributor

Great! :)

@jackparmer
Copy link
Contributor

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

Sponsorship range: $10k-$15k

What Sponsorship includes:

  • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
  • Tests for this feature
  • Long-term support (continued support of this feature in the latest version of Plotly.js)
  • Documentation at plotly.com/javascript
  • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
  • Possibility of integrating this feature with Dash
  • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
  • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

Please include the link to this issue when contacting us to discuss.

@soadergi
Copy link

soadergi commented Nov 17, 2021

Setting layout.legend.y = "auto" and layout.legend.yanchor = "top" helped me to avoid legend overlapping on x-axis title

@Nicolas-Yazzoom
Copy link

Resizing responsive plots multiple times in quick succession can also cause the legend to overlap with the rest of the plot. After the bug occurs, triggering a resize by in- or decreasing by a few px and then returning to the previous page dimensions renders the plot correctly this time.

https://codepen.io/poomse8/pen/KKxVMjx

@ScottWilliamAnderson
Copy link

these layout settings allowed me to avoid this issue occurring entirely:
'yref': container
'yanchor': bottom
'xanchor': center
'x': 0.5
'orientation': 'h'

@archmoj
Copy link
Contributor

archmoj commented Jun 28, 2023

these layout settings allowed me to avoid this issue occurring entirely: 'yref': container 'yanchor': bottom 'xanchor': center 'x': 0.5 'orientation': 'h'

@alexcjohnson @hannahker
Does that mean we could close this issue?

@salim-b
Copy link
Contributor Author

salim-b commented Jun 28, 2023

Does that mean we could close this issue?

Obviously I can't speak for the people you mentioned, but my original issue has indeed been fixed since I've last checked (2017). Tested with plotly.js v2.11.1 (included in the plotly R package 4.10.2). 🙂

@archmoj archmoj closed this as completed Jun 28, 2023
@chaosink
Copy link

chaosink commented Dec 7, 2023

these layout settings allowed me to avoid this issue occurring entirely: 'yref': container 'yanchor': bottom 'xanchor': center 'x': 0.5 'orientation': 'h'

@alexcjohnson @hannahker Does that mean we could close this issue?

With the settings, I still need to set a proper layout.margin.b manually to avoid overlapping between the X-axis title and the legend.
So I don't think the issue fixed completely...

@SimonCoulombe
Copy link

SimonCoulombe commented Jun 19, 2024

Does that mean we could close this issue?

Obviously I can't speak for the people you mentioned, but my original issue has indeed been fixed since I've last checked (2017). Tested with plotly.js v2.11.1 (included in the plotly R package 4.10.2). 🙂

I still have this issue, what settings worked for you? thanks

@salim-b
Copy link
Contributor Author

salim-b commented Jun 19, 2024

I still have this issue, what settings worked for you?

The code for the plot in the first post auto-scales perfectly with recent versions of plotly.js:

Bildschirmaufzeichnung.vom.19.06.2024.23.03.30.webm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken feature something new
Projects
None yet
Development

No branches or pull requests