Why are Bootstrap tabs displaying tab-pane divs with incorrect widths when using highcharts?

前端 未结 6 1153
长发绾君心
长发绾君心 2020-11-22 14:30

So I\'m creating a page with tabbed content using Twitter\'s Bootstrap, yet the content of my starting active div is always different than that of my other tabs. For example

相关标签:
6条回答
  • 2020-11-22 14:36

    The in-line style "width" is different for the charts. I'm not sure when and how are those calculated, but you can override those in css for example.

    0 讨论(0)
  • 2020-11-22 14:37

    Based on the Pawel's answer I render the chart at beginning and then resize the chart.

    The code used (with bootstrap 3.0.3 and HighCharts 3.0.7)

    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        $('#container').highcharts().setSize($('#container').width(),$('#container').height());
    })
    

    Source: http://getbootstrap.com/javascript/#tabs-usage

    0 讨论(0)
  • 2020-11-22 14:38

    I found an easier solution in another post. Basically, the problem comes because Highcharts cannot render on a div with 'display: none' set. The solution is just write a fix in your CSS stylesheet.

    .tab-content > .tab-pane,
    .pill-content > .pill-pane {
        display: inline;
        visibility: hidden;
        position: absolute;
        width: 930px;
    }
    
    .tab-content > .active,
    .pill-content > .active {
        display: inline;
        visibility: visible;
        position: absolute;
        width: 930px;
    }
    

    This is going to make the tabs to work with visibility attribute instead of display. Charts will render well.

    0 讨论(0)
  • 2020-11-22 14:39

    The Cause

    This is not a Highcharts issue, at least not by itself, the problem is caused by the fact that Bootstrap uses display: none to hide inactive tabs:

    .tab-content > .tab-pane, .pill-content > .pill-pane {
        display: none;      /* this is the problem */
    }
    

    This causes Highcharts not able to get the expected width to initialize the chart, thus defaults to 600px. This would happen to other tools using the same approach to hide content.

    A Pure CSS Solution

    Instead of working around the issue with an extra redraw or delayed initialization, we can achieve the hidden effect using height: 0; overflow-y: hidden, this way the hidden tab panes are still in place and having valid width:

    /* bootstrap hack: fix content width inside hidden tabs */
    .tab-content > .tab-pane:not(.active),
    .pill-content > .pill-pane:not(.active) {
        display: block;
        height: 0;
        overflow-y: hidden;
    } 
    /* bootstrap hack end */
    

    Update: We now target inactive tabs directly, via :not(.active), to avoid possible side effect if any.

    This solution is seamless, so you no longer have to worry whether the chart is inside a tab-pane or not. And it's efficient as it fixes the width issue in the first place, thus there's no need to workaround the width issue afterward via resize/redraw/reflow using javascript.

    Note about cascading order

    This patch needs to be loaded after bootstrap css, because of CSS cascading order rules, in short, the latter rule wins.

    Demo

    Before vs After

    Tip: switch to the Profile tab to see the difference.

    0 讨论(0)
  • 2020-11-22 14:40

    The problem is that Highcharts can not calculate width of the container which has CSS: display:none, so applied is default width (600px). In fact, browser is not able to calculate width for such elements.

    For example when you will use separator to resize Result window, chart will resize and will work. So you have three options:

    • render chart after first click on that tab
    • render chart at the beginning, but after each click and window resize use chart.setSize(w,h) with new width and height
    • render chart at the beginning, but after tab click call chart.reflow()
    0 讨论(0)
  • 2020-11-22 14:52

    Based on Paweł's answer I've made a working example:

    http://codepen.io/colinsteinmann/pen/BlGfE

    Basically the .reflow() function is called on each chart when a tab is clicked. That way the chart gets redrawn based on the new dimensions which are applied to the container when it becomes visible.

    This is the most important snippet of code:

    // fix dimensions of chart that was in a hidden element
    jQuery(document).on( 'shown.bs.tab', 'a[data-toggle="tab"]', function (e) { // on tab selection event
        jQuery( ".contains-chart" ).each(function() { // target each element with the .contains-chart class
            var chart = jQuery(this).highcharts(); // target the chart itself
            chart.reflow() // reflow that chart
        });
    })
    
    0 讨论(0)
提交回复
热议问题