'Width of Chosen dropdowns near zero when starting in collapsed Bootstrap accordion

When a Chosen dropdown is inside a Bootstrap 3 accordion that's initially hidden, then the width of the dropdown is near zero. After expanding it looks like this:

width zero of select

Whereas I expect it to look like this:

width normal for select

The problem occurs when the panel-collapse collapse div does not have an in class,effectively indicating it's initially collapsed. Here's the code to reproduce this issue:

$(document).ready(function() {
    $('select').chosen();
});
.panel-heading { cursor: pointer; }
body { padding: 10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.jquery.min.js"></script>

<div class="panel-group" id="accordion">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
          Expand me to show the issue!
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse">
      <div class="panel-body form-inline">
        <p>This select has a near-width zero:</p>
        <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
    <div class="panel panel-default">
    <div class="panel-heading" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
      <h4 class="panel-title">
          Already expanded / how it <em>should</em> be
      </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse in">
      <div class="panel-body form-inline">
        <p>This panel is initially visible and <em>does</em> have correct width for the select box:</p>
          <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
</div>

What can I do to prevent this from happening? Calling chosen as .chosen({width: '90%'});, i.e. with a hard-coded width works, but is not satisfactory (I want to style in my stylesheet or using Bootstrap). The only resolution left seems to be to hook into the expanding event and force a chosen update, but that also feels like a workaround.

Preferably I'd have a line of CSS to fix this, or know whether this might even be a bug in the (combination of) tool(s)?



Solution 1:[1]

Reason:

Chosen calculates and assigns the width when the DOM is ready, before that the initial width for the emulated drop-down is zero.

Solution:

Add the following to your CSS so the dropdown has an initial width:

.chosen-container.chosen-container-single {
    width: 300px !important; /* or any value that fits your needs */
}

The !important part is because chosen adds an inline style of width: 0; to the element itself and you need to override the specificity with !important.

Solution 2:[2]

From jquery-chosen official documentation:

The width of the Chosen select box. By default, Chosen attempts to match the width of the select box you are replacing. If your select is hidden when Chosen is instantiated, you must specify a width or the select will show up with a width of 0.

So you need to specify width attribute

$(document).ready(function() {
    $('select').chosen( { width: '100%' } );
});
.panel-heading { cursor: pointer; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.jquery.min.js"></script>

<div class="panel-group" id="accordion">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
          Expand me to show the issue!
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse">
      <div class="panel-body form-inline">
        <p>This select has a near-width zero:</p>
        <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
    <div class="panel panel-default">
    <div class="panel-heading" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
      <h4 class="panel-title">
          Already expanded / how it <em>should</em> be
      </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse in">
      <div class="panel-body form-inline">
        <p>This panel is initially visible and <em>does</em> have correct width for the select box:</p>
          <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
</div>

EDIT:

Also as a hack you can check visible selectbox width and apply it to all others:

$(document).ready(function() {
    $('select').chosen( { width: $( '.panel-collapse.collapse.in select' ).eq( 0 ).width() + 'px' } );
});

Solution 3:[3]

It works if you do

$('.my-element').chosen({width:"auto"});

Solution 4:[4]

To avoid an inline width style being applied by chosen, pass an empty string as the width parameter when initializing your select.

$('#your-select-element').chosen({ width: '' });

Behind the scenes, chosen just calls jQuery .width() to set the width on the element using the value you supply.

By passing an empty string, the chosen-container element won't have any width style applied to it at all. Then you don't need to mess with !important or other things that could conflict with your stylesheet.

Solution 5:[5]

This way you'll give each select its initial size:

$('select').each(function(){

    $(this).chosen({ width: $(this).eq( 0 ).width() + 'px' });

})

Solution 6:[6]

If the select is inside a hidden form, width is still 0. Here is my fix for it:

  $(document).ready(function() {
    refreshSelects();
  });

  /**
   * Re-draws selects to fix width of 'chosen' wrapper.
   */
  refreshSelects = function() {
    $('select').each(function(){
      // Re-calculate width of every select wrapper. Hidden selects width is
      // calculated as 0 by 'chosen' plugin.
      $(this).siblings('.chosen-container').css('width', realWidth($(this)));
    });

    /**
     * Calculates real width of an element.
     *
     * @param {object} $element
     *   jQuery object.
     *
     * @returns {string}
     *   Element width string.
     */
    function realWidth($element){
      var $clone = $element.clone();
      $clone.css("visibility","hidden");
      $('body').append($clone);
      var width = $clone.outerWidth();
      $clone.remove();
      return width;
    }
  }

Solution 7:[7]

You can call the select on show of the accordian that will set the exact height.

$(document).ready(function() {
    $("#accordion").on("show",function(){
        $('select').chosen();
    })        
});
.panel-heading { cursor: pointer; }
body { padding: 10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/chosen/1.1.0/chosen.jquery.min.js"></script>

<div class="panel-group" id="accordion">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
          Expand me to show the issue!
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse">
      <div class="panel-body form-inline">
        <p>This select has a near-width zero:</p>
        <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
    <div class="panel panel-default">
    <div class="panel-heading" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
      <h4 class="panel-title">
          Already expanded / how it <em>should</em> be
      </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse in">
      <div class="panel-body form-inline">
        <p>This panel is initially visible and <em>does</em> have correct width for the select box:</p>
          <select class="form-control">
            <option>Short</option>
            <option>Longer option</option>
            <option>The longest option of them all</option>
        </select>
      </div>
    </div>
  </div>
</div>

Solution 8:[8]

Just Modify

$("#my_element").chosen({width:"auto"});

Instead of

$("#my_element").chosen();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 jramm
Solution 5 vincenzo
Solution 6
Solution 7
Solution 8 Abhishek Yadav