You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unfortunately, there isn't this option built into plotly.js at the moment. The text labels are created using SVG elements, or in WebGL where text-reflow is done manually and it's not quite as easy just constraining the width.
This likely won't be of high priority for us in the immediate future, but we're always open to pull requests and are happy to help on them!
Ok, understood. Would help with a PR if I had a clue how to do that :)
Pardon my ignorance, but is there no way to introduce a JavaScript function that would be applied to all labels before they're fed to SVG/WebGL, where it becomes complicated?
For example, I've google-found this function (it's not great since there is an issue with long words, but just as an illustration)
function stringDivider(str, width, spaceReplacer) {
if (str.length>width) {
var p=width
for (;p>0 && str[p]!=' ';p--) {
}
if (p>0) {
var left = str.substring(0, p);
var right = str.substring(p+1);
return left + spaceReplacer + stringDivider(right, width, spaceReplacer);
}
}
return str;
}
that I can use internally to shorten the labels
var label = "Very Long Text Label That Doesn't Fit Properly"
x: ['giraffes', 'orangutans', stringDivider( label, 20, "<br>") ],
Also, as a side question — is there a way to read the bar width in plotly so I don't have to adjust the width manually and can make it reflow properly when chart size is adjusted.
Reacted by yunwei, Scott J Simontacchi and Susie Stanley
A workaround is to line break svg elements after rendering. This assumes that there are <br/> tags in the text, and splits text elements into multiple text elements.
Has the plotly library managed to solve this issue now. Looking for some better alternatives.
Reacted by Benjamin W. Portner, sneakypeanut, Nelson Gardner-Challis, ricardo-re-azevedo, paulouliana1, craragon77, Sam Machen, Artem Zhelonkin, Taras Sytnyk, Colleen McKenzie and 2 more
still no updates on this right? cause it would be suuuuper clutch if this there was a way to wrap labels. I'm working with some long, dynamic violin plot labels and it would be so awesome if this feature were addressed
@craragon77 SVG doesn't have line wrap / truncation as native features I think , so the code needs to explicitly break/wrap/recenter or truncate text. Below is code that selects and breaks or truncates text in a Plotly chart after rendering.
The ideal solution would be for someone to package and test this nicely for a pull request to Plotly, but for expedience we just select break the text ourselves:
const_=require('lodash')module.exports={breakStr: function(text,maxLineLength,regexForceBreak,regexSuggestBreak){constresultArr=[];maxLineLength=maxLineLength||12regexForceBreak=regexForceBreak||/<br[/]?>|\n|\&/gregexSuggestBreak=/\s/gfunctionm(str){return!!(str&&str.trim())}varsplitStr=text.split(regexForceBreak);splitStr.forEach(function(str){if(str.length<=maxLineLength){resultArr.push(str);}else{vartempStr=str;while(tempStr){varsuggestedBreakPoints=[]varconvenientBreakPoint=Infinityvarmatch,fragment;while((match=regexSuggestBreak.exec(tempStr))!=null){suggestedBreakPoints.push(match.index+1)if(match.index<=maxLineLength)convenientBreakPoint=match.index;}if(tempStr.trim()&&tempStr.length<=maxLineLength){fragment=tempStrresultArr.push(fragment)tempStr=''}elseif((convenientBreakPoint<=maxLineLength)&&(maxLineLength>maxLineLength-5)){fragment=tempStr.substr(0,convenientBreakPoint)resultArr.push(fragment)tempStr=tempStr.substr(convenientBreakPoint+1);}else{fragment=tempStr.substr(0,maxLineLength)+"–"resultArr.push(fragment)tempStr=tempStr.substr(maxLineLength);}}}});returnresultArr;},/** * @method svgLineBreaks * @returns <function(d)> Returns a function that breaks an SVG text element into multiple lines * @param maxLineLength Maximum number of lines before truncating with ellipses * @param regexForceBreak Regex to suggest places to always, currently •|<br>|<br/>|\n * @param regexSuggestBreak Regex to suggest preferred breaks, currently <wbr> * @param verticalAlign e.g. 'middle' to optionally center mutiple lines at same ypos as original text * @example svg.selectAll('g.x.axis g text').each(svgLineBreaks); */breakElement: function(maxLineLength,regexForceBreak,regexSuggestBreak,verticalAlign){maxLineLength=maxLineLength||12regexForceBreak=regexForceBreak||/<br[/]?>|•|\n/igregexSuggestBreak=regexSuggestBreak||/•|<wbr>/igreturnfunction(d){varel=d3.select(this);varbbox=el.node().getBBox()varheight=bbox.heightheight=height||16.5//hack as Plotly might draw before rendered on screen, so height zero; this is just a guessvarresult={el: this,dy: 0,lines: []}vartext=el.text()vartotal_dy=0;if(text){varlines=this_module.breakStr(text,maxLineLength,regexForceBreak,regexSuggestBreak)result.lines=linesfor(vari=0;i<lines.length;i++){if(i==0){el.text(lines[0])}else{vartspan=el.append('tspan')tspan.text(lines[i]);tspan.attr('x',el.attr('x')||0).attr('dy',height);total_dy+=height}}if(verticalAlign=='middle'){el.attr('y',el.attr('y')-(lines.length-1)*height/2)}}result.dy=total_dyreturnresult}},/** * maxLineLength, regexForceBreak, regexSuggestBreak, adjust * @param d3el * @param selector * @param options.maxLineLength * @param options.regexForceBreak * @param options.regexSuggestBreak * @param options.position "middle" */breakElements: function(d3el,selector,options){varself=this;options=options||{}varbreaker=self.breakElement(options.maxLineLength||12,options.regexForceBreak,options.regexSuggestBreak,options.verticalAlign)varmax_total_dy=0d3.select(d3el).selectAll(selector).each(function(d,i){varresult=breaker.apply(this,arguments)if(i>0&&(result.dy>max_total_dy)){max_total_dy=result.dy}})},truncateElement: function(maxLineLength){returnfunction(d){varel=d3.select(this)vartext=el.text()if(text&&text.length>maxLineLength){text=(text.substr(0,maxLineLength)+"…")}el.text(text)}}}
No one from our team is actively working on this but we would happily work with anyone who wants to help :)
Wow, I came back to plotly after a year and I'm surprised to see this.
It looks SO unprofessional to use any sort of labeling in plotly. It appears to others that there's a bug and I did something wrong, so I don't know why this isn't a bigger issue.
It's enough to have made me use Tableau Public instead - and the entire advantage of plotly is customizability, so this has been a frustrating issue to rediscover several hours into making the plot
Reacted by zdravis, Susie Stanley, Colleen McKenzie, Cliff Pyles and Asif Shaikh
Charting seems so simple at first but the diversity of users, use cases, and edge cases is wild.
And word break / line wrapping specifically is surprisingly nuanced.
Plotly is an open source library, so theoretically we can add features we need such as this.
Something that works for us is posted above, but the gap between 'works for us' and 'works for many' is non trivial.
If any one has the skills and interest to create a good patch and/or get a PR accepted for this issue, we'll contribute $.
Charting seems so simple at first but the diversity of users, use cases, and edge cases is wild. And word break / line wrapping specifically is surprisingly nuanced.
I definitely understand that considering the number of tools I've looked at for what I thought was relatively simple (horizontal timeline with groups and text wrapping that my dad could edit), but of course, these things never are! I can't
This is surprising to me because I don't think it's an edge case at all. It's essential to being able to label data on the graph - it's not presentable if you have overlapping labels/no linebreaks/uneven text sizes (although that's fixed I think), etc.
And labeling data is essential for communication.
It took a very long time and a lot of manual screenshotting for a non-web dev to make this chart look presentable with Plotly in this Dash App!
I would say I spent at least 30% of my time with Plotly trying to get labels to look presentable, and it's why I no longer use the library if I can possibly help it
I no longer work at Plotly or have any affiliation with them, so this is not an "official" response, but was a core maintainer when this issue was originally opened.
The challenge is that there's not actually a reasonable solution to the problem that will be correct in all cases. Text wrapping in the charts is tricky because there are so many variables that are difficult to actually control for - fonts, font sizes, browsers, zoom level, etc. all contribute to the actual width of a given block of text. While yes it is a challenge to format text with long labels, it's par for the course with what plotly attempts to achieve - being an extensible and flexible library which doesn't really get in the way of making nearly any chart or graph visualization. There's alternatives on either side of its niche - D3 if you want to go lower level, and things like Tableau or Highcharts if you want to go higher level, but those come with their own set of compromises you'll have to adapt to.
I don't imagine this issue will ever be resolved, as text wrapping simply isn't something that plotly.js is positioned for to handle automatically, nor should it (IMO) - it would be like asking React to automatically do the layout of your webapp. Frankly, I'm surprised I still get notifications about this issue more than 6 years later and it hasn't been closed yet 😆
All this to say I would love to be proven wrong and see a community contribution which does implement a robust solution. PR's are always welcome :)
Reacted by Bozsoki Levente, Pieter Sheth-Voss and Cliff Pyles
If you are using Python and pandas you can use wrap() to wrap long text labels. Here is some example code:
import pandas as pd
import plotly.express as px
# these sentences are much too long to use them as labels
sentences = [
"I no longer work at Plotly or have any affiliation with them, so this is not an \"official\" response, but was a core maintainer when this issue was originally opened.",
"The challenge is that there's not actually a reasonable solution to the problem that will be correct in all cases.",
"Text wrapping in the charts is tricky because there are so many variables that are difficult to actually control for - fonts, font sizes, browsers, zoom level, etc. all contribute to the actual width of a given block of text.",
"While yes it is a challenge to format text with long labels, it's par for the course with what plotly attempts to achieve - being an extensible and flexible library which doesn't really get in the way of making nearly any chart or graph visualization."
]
df = pd.DataFrame([(text, len(text)) for text in sentences], columns=["text", "length"])
# Here we wrap the text to 20 columns and a maximum of three lines
df["text_wrapped"] = df["text"].str.wrap(width=20, max_lines=3, placeholder = " ... ")
fig = px.bar(df, x="length", y="text_wrapped", orientation="h", hover_data={"text_wrapped":False, "text":True}, text="length")
fig.update_layout(margin_pad=10, template="ggplot2")
fig.update_yaxes(title = "text", categoryorder='total ascending')
fig.show()
The output looks like
The untruncated text can be seen while hovering over the bar chart. It would be nicer to show the untruncated text while hovering over the axis labels. Unfortunately hovers over the axis labels don't seem to be possible in plotly.
Activity
mdtusz commentedon Apr 1, 2016
Unfortunately, there isn't this option built into plotly.js at the moment. The text labels are created using SVG elements, or in WebGL where text-reflow is done manually and it's not quite as easy just constraining the width.
This likely won't be of high priority for us in the immediate future, but we're always open to pull requests and are happy to help on them!
eugenesvk commentedon Apr 1, 2016
Ok, understood. Would help with a PR if I had a clue how to do that :)
Pardon my ignorance, but is there no way to introduce a JavaScript function that would be applied to all labels before they're fed to SVG/WebGL, where it becomes complicated?
For example, I've google-found this function (it's not great since there is an issue with long words, but just as an illustration)
that I can use internally to shorten the labels
Also, as a side question — is there a way to read the bar width in plotly so I don't have to adjust the width manually and can make it reflow properly when chart size is adjusted.
datapanda commentedon Apr 5, 2017
Any update on this?
grahamscott commentedon Jul 7, 2017
@mdtusz I'm happy to try to help with this if you're able to point me in the right direction in the codebase.
etpinard commentedon Jul 7, 2017
#1834 should see some foundation work on this.
protobi-pieter commentedon Jan 28, 2020
A workaround is to line break svg elements after rendering. This assumes that there are
<br/>tags in the text, and splits text elements into multiple text elements.Then it's a matter of selecting svg text elements and calling the above function:
You can get fancier with the selector so line break just axis labels for instance.
It could also be used in conjunction with above method by @eugenesvk to evaluate long strings and insert such line break markers.
punitaojha commentedon Apr 23, 2021
Has the plotly library managed to solve this issue now. Looking for some better alternatives.
paulouliana1 commentedon Sep 28, 2021
I'd also like to know whether Plotly intends to solve this. Thanks!
archmoj commentedon Oct 9, 2021
Wondering if using
overflowCSS could become helpful?See https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
nicolaskruchten commentedon Oct 9, 2021
No one from our team is actively working on this but we would happily work with anyone who wants to help :)
m-podlesny commentedon Oct 11, 2021
Which way to go: #5700 or #2053 ?
craragon77 commentedon Feb 11, 2022
still no updates on this right? cause it would be suuuuper clutch if this there was a way to wrap labels. I'm working with some long, dynamic violin plot labels and it would be so awesome if this feature were addressed
protobi-pieter commentedon Feb 14, 2022
@craragon77 SVG doesn't have line wrap / truncation as native features I think , so the code needs to explicitly break/wrap/recenter or truncate text. Below is code that selects and breaks or truncates text in a Plotly chart after rendering.
The ideal solution would be for someone to package and test this nicely for a pull request to Plotly, but for expedience we just select break the text ourselves:
fedderw commentedon Oct 28, 2022
Wow, I came back to plotly after a year and I'm surprised to see this.
It looks SO unprofessional to use any sort of labeling in plotly. It appears to others that there's a bug and I did something wrong, so I don't know why this isn't a bigger issue.
It's enough to have made me use Tableau Public instead - and the entire advantage of plotly is customizability, so this has been a frustrating issue to rediscover several hours into making the plot
protobi-pieter commentedon Oct 28, 2022
Charting seems so simple at first but the diversity of users, use cases, and edge cases is wild.
And word break / line wrapping specifically is surprisingly nuanced.
Plotly is an open source library, so theoretically we can add features we need such as this.
Something that works for us is posted above, but the gap between 'works for us' and 'works for many' is non trivial.
If any one has the skills and interest to create a good patch and/or get a PR accepted for this issue, we'll contribute $.
fedderw commentedon Oct 28, 2022
I definitely understand that considering the number of tools I've looked at for what I thought was relatively simple (horizontal timeline with groups and text wrapping that my dad could edit), but of course, these things never are! I can't
This is surprising to me because I don't think it's an edge case at all. It's essential to being able to label data on the graph - it's not presentable if you have overlapping labels/no linebreaks/uneven text sizes (although that's fixed I think), etc.
And labeling data is essential for communication.
It took a very long time and a lot of manual screenshotting for a non-web dev to make this chart look presentable with Plotly in this Dash App!
I would say I spent at least 30% of my time with Plotly trying to get labels to look presentable, and it's why I no longer use the library if I can possibly help it
mdtusz commentedon Oct 28, 2022
I no longer work at Plotly or have any affiliation with them, so this is not an "official" response, but was a core maintainer when this issue was originally opened.
The challenge is that there's not actually a reasonable solution to the problem that will be correct in all cases. Text wrapping in the charts is tricky because there are so many variables that are difficult to actually control for - fonts, font sizes, browsers, zoom level, etc. all contribute to the actual width of a given block of text. While yes it is a challenge to format text with long labels, it's par for the course with what plotly attempts to achieve - being an extensible and flexible library which doesn't really get in the way of making nearly any chart or graph visualization. There's alternatives on either side of its niche - D3 if you want to go lower level, and things like Tableau or Highcharts if you want to go higher level, but those come with their own set of compromises you'll have to adapt to.
I don't imagine this issue will ever be resolved, as text wrapping simply isn't something that plotly.js is positioned for to handle automatically, nor should it (IMO) - it would be like asking React to automatically do the layout of your webapp. Frankly, I'm surprised I still get notifications about this issue more than 6 years later and it hasn't been closed yet 😆
All this to say I would love to be proven wrong and see a community contribution which does implement a robust solution. PR's are always welcome :)
kbradwell commentedon Jul 26, 2023
Workaround example for spacing and wrapping titles on subplots:
asmaier commentedon Apr 2, 2024
If you are using Python and pandas you can use wrap() to wrap long text labels. Here is some example code:
The output looks like

The untruncated text can be seen while hovering over the bar chart. It would be nicer to show the untruncated text while hovering over the axis labels. Unfortunately hovers over the axis labels don't seem to be possible in plotly.
archmoj commentedon Jun 5, 2024
It looks like one could make use of
foreignObjecthttps://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject to implement this feature.alexcjohnson commentedon Jun 5, 2024
To my knowledge foreignObject does not work outside browsers - so this would break SVG export
archmoj commentedon Jun 5, 2024
Thanks @alexcjohnson for the note.
I was also thinking about it.
If the
PNGexport works, this may still be a good option. No?archmoj commentedon Jun 5, 2024
@alexcjohnson Update: It looks like using
foreignObjectis not a good option as it could introduce security issues.