2

This is really frustrating.. I am using Highcharts to generate BaRCharts for some of my categories.

On Large screen screens it works really well. But on small screen Category label is overlapping the bar as shown below:

enter image description here

I tried changing widths but overlap issue does not solve.

JSFiddle is here Fiddle

Please let me know help. this BAR and Label is getting generated dynamically by Highcharts API

Gags
  • 3,759
  • 8
  • 49
  • 96

5 Answers5

2

Updated using flex

This might help you out.

With flex you can change the order of elements and by doing so, you can set the "text div" before the "svg", make all position relative and make them flow naturally.

Some css need the "!important" on its value to override the inline styles.

Update 2 Code/demo updated to show how to prefix css properties for Safari

FIDDLE demo

#barcontainer > div > svg,
#barcontainer > div > div,
#barcontainer > div > div > span {
    position: relative !important;
}
#barcontainer > div {
    height: auto !important;
}
#barcontainer > div > svg {
    top: -20px !important;
}
#barcontainer > div {
    -webkit-display: flex;
    display: flex;
    -webkit-flex-flow: column;
    flex-flow: column;
}
#barcontainer > div > svg {
    -webkit-order: 2;
    order: 2;
}
#barcontainer > div > div {
    -webkit-order: 1;
    order: 1;
}

You can also use 1 or more media queries to control at which screen sizes the above should kick in.

@media screen and (max-width: 600px) {
    //flex css 1
}

@media screen and (max-width: 800px) {
    //flex css 2
}

Update 3 using javascript

If you can't/don't want flex here is a simple "swapper" which switch the svg and the text element.

Note: You can use flex and have a fallback for older browsers where a script like this kicks in

FIDDLE demo - JS version

function swapSibling(node1, node2) {
    node1.parentNode.replaceChild(node1, node2);
    node1.parentNode.insertBefore(node2, node1); 
}

window.onload = function() {
    var parent = document.getElementById("barcontainer").children[0];
    var svg = parent.children[0];
    var text = parent.children[1];    
    swapSibling(svg, text);
}

Note: If you need to support IE8 read best way to get child nodes

Update 4 using zoom

If the content just need to get "smaller", one more approach one can take is actually to "zoom" the barcontainer. This keep the existing ratio and layout and makes all content smaller (or bigger), still, when need to "squeeze" to much, text normally gets difficult to read.

Community
  • 1
  • 1
Asons
  • 84,923
  • 12
  • 110
  • 165
  • Nop. I tried this.. this has 2 issues.. single liner labels will look odd and 2nd is that if label is of 3 lines then it ll also overlap – Gags Sep 28 '15 at 13:33
  • I am afraid if Flex is supportd by Safari.. because i tried flex and tested on iPhone 5S and flex was now working at all... – Gags Sep 30 '15 at 01:37
  • @Gags Updated answer again, with prefix for Safari. iPhone's using IOS 6.1 or higher supports the new flex box specs. At this link, http://caniuse.com/#feat=flexbox, you will find from which version other browsers do and as well some good resource links – Asons Sep 30 '15 at 07:12
  • Also i m thinking that will.it be good to use flex.. as it is mostly not supported by browsers.. – Gags Sep 30 '15 at 07:33
  • @Gags Updated my answer with one more approach ... using javascript, which gives you a fallback option for older browsers. – Asons Sep 30 '15 at 10:30
  • i really appreciate your help... there is much gap between label and bar now... i am trying to adjust that.. meantime if you have any idea then that will help.. really thanks :) – Gags Oct 01 '15 at 04:04
  • Check this demo http://jsfiddle.net/dp2gmqf1/11/. Modify the 2 last css rules to see how it works. The added "z-index" in this javascript version is to adjust the svg which has an inner top white space that overlap the text some when we move the svg up, so the z-index puts it "under the text". – Asons Oct 01 '15 at 07:30
  • sry to bother you again but it think this swap can cause issues if we have multiple bars and text and in mycase there are multiple bas – Gags Oct 01 '15 at 09:55
  • The above solve 1 svg/text, for multiple svg/text the script need to be adjusted accordingly, so it iterates through the children and see how many and of which type and then sort them properly. When there are more than 1 bar/text the css has to be updated as well, to match those elements adjustments like margin-top etc. Please provide another fiddle demo that have multiple svg/text and I will have a look. – Asons Oct 01 '15 at 10:03
  • With this new sample it becomes obvious that extending my solution is a very wrong way to go. Making use of another type of Chart library is the way to go if you can't make use of the existing one how Paweł Fus suggested in his answer. The key is to pass a "max size" to the chart instead of "squeeze" what you get into something smaller. – Asons Oct 02 '15 at 12:51
  • i am accepting your answer as you have tried a lot and suggested something at the end – Gags Oct 06 '15 at 05:18
  • I appreciate that, thanks. And one more approach one can take is actually to "zoom" (https://developer.mozilla.org/en/docs/Web/CSS/@viewport/zoom) the "barcontainer". Doing so keep the existing ratio and layout and makes all content smaller (or bigger), still, when need to "squeeze" to much, text normally gets difficult to read. – Asons Oct 06 '15 at 06:00
1

Let me explain a bit the problem: Highcharts lib is using SVG and HTML tags. To use them both at the same time and place, HTML tags need to be rendered on top of the SVG, using absolute positioning. There comes the issue: in general, you can not position SVG and HTML elements like those are two HTML elements (like HTML-div and SVG-rect vs two HTML-divs).

I would suggest to use different approach:

  • use @media-queries
  • when text goes in two lines, change font-size, for example to 0.9rem

Demo: http://jsfiddle.net/dp2gmqf1/5/

Paweł Fus
  • 44,795
  • 3
  • 61
  • 77
  • but what about when text more than 2 lines.. then i can not decrease the font size furthermore... – Gags Sep 29 '15 at 03:40
  • 2
    I think this is general problem: with very limited space, where should be this text placed? Imagine case: 10 lines of text (12px), with container height = 50px. I think that the best would be to use `chart.setSize()` on window resize event. You can get bounding box of the dataLabel: `chart.series[0].points[0].dataLabel.getBBox()`. Now increase height of the chart accordingly. – Paweł Fus Sep 29 '15 at 09:21
0

No, you cannot do this with pure css, because it is the way the "position: absolute" works - it doesn't follow the regular page flow, so there's no way to display the text in a relation to another (normally positioned) element.

You can use javascript with JQuery, but designing a better layout seems to be more natural.

Jquery solution without any changes in html: http://jsfiddle.net/dp2gmqf1/10/:

var height =  $("#barcontainer > div > div > span").height(); // get the height of the text
$("svg").css("margin-top", height + "px"); // set the top-margin of the svg element
prompteus
  • 1,051
  • 11
  • 26
  • but i am not adding position absolute.. It is highcharts... how can i handle in JQuery – Gags Sep 28 '15 at 10:56
  • If the text had a class or an id, you could use code like this: http://jsfiddle.net/dp2gmqf1/3/ , but I'm afraid that I can't help you without class or id. – prompteus Sep 28 '15 at 11:13
  • @makadlcik There are selectors you can use with jQuery, for example `#barcontainer > div > svg`. See my working flex/css version how to get the selectors to make a script version. – Asons Sep 29 '15 at 21:03
  • @LGSon There is no problem with selecting the svg in css, but we need to get the height of the text (because we don't know how many lines it takes), so we can set top margin of the svg with jquery. But we cannot get the height of the element with text, because it has no class or id. – prompteus Sep 30 '15 at 08:02
  • @makadlcik You can get the "text" div like this `#barcontainer > div > div ` or its inner span element like this `#barcontainer > div > div > span` and then calculate the height. – Asons Sep 30 '15 at 09:59
  • @LGSon Well, you are right, this is a working sollution. Although not really pretty. – prompteus Sep 30 '15 at 10:25
  • It works when there is only one element that matches the selector `#barcontainer > div > div `. In this case there is so I updated my answer and added a working jsfiddle. – prompteus Sep 30 '15 at 10:35
0

You may turn your text "Skole-, uddannelses- og..." to flow in one line, if its not an issue for your implementation.

So you can do like this in your html:

<div style="width:270px; white-space: nowrap;">Skole-, uddannelses- og kursusudgifter</div>

Update 1

Try doing this:

.chart-container > div svg { margin-top: 30px; }
Ravi Khandelwal
  • 718
  • 1
  • 5
  • 15
  • yup.. i tried same but then text overflows out of screen and i do not want any cutoffs or scrollbars – Gags Sep 28 '15 at 10:58
0

Your issue is purely due to the placement of the dynamic code, If it is at all possible to move the SVG element inside of the same div that the text is contained in, as well as removing the absolute positioning used on the text, and the height from the main div, it will then work as intended.

The changes can be seen below as follows:

Skole-, uddannelses- og kursusudgifterCreated with Highcharts 4.1.113.5

P.S. As Mentioned before, this relies on whether you can manipulate the ordering of the dynamic data to this extent.

http://jsfiddle.net/dp2gmqf1/4/

Have a nice day, Shogun.

Shogun
  • 1
  • 2
  • He cannot remove absolute position, because it is generated css by highcharts. – prompteus Sep 28 '15 at 11:42
  • @makadlcik Ah I see, if highcharts is generating the string of code with zero chance of manipulation then I fear I'm out of help. – Shogun Sep 28 '15 at 11:48