55

The issue:

Some of the items in the select require more than the specified width of 145px in order to display fully.

Firefox behavior: clicking on the select reveals the dropdown elements list adjusted to the width of the longest element.

IE6 & IE7 behavior: clicking on the select reveals the dropdown elements list restricted to 145px width making it impossible to read the longer elements.

The current UI requires us to fit this dropdown in 145px and have it host items with longer descriptions.

Any advise on resolving the issue with IE?

The top element should remain 145px wide even when the list is expanded.

Thank you!

The css:

select.center_pull {
    background:#eeeeee none repeat scroll 0 0;
    border:1px solid #7E7E7E;
    color:#333333;
    font-size:12px;
    margin-bottom:4px;
    margin-right:4px;
    margin-top:4px;
    width:145px;
}

Here's the select input code (there's no definition for the backend_dropbox style at this time)

<select id="select_1" class="center_pull backend_dropbox" name="select_1">
<option value="-1" selected="selected">Browse options</option>
<option value="-1">------------------------------------</option>
<option value="224">Option 1</option>
<option value="234">Longer title for option 2</option>
<option value="242">Very long and extensively descriptive title for option 3</option>
</select>

Full html page in case you want to quickly test in a browser:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>dropdown test</title>

<style type="text/css">
<!--
select.center_pull {
    background:#eeeeee none repeat scroll 0 0;
    border:1px solid #7E7E7E;
    color:#333333;
    font-size:12px;
    margin-bottom:4px;
    margin-right:4px;
    margin-top:4px;
    width:145px;
}
-->
</style>
</head>

<body>
<p>Select width test</p>
<form id="form1" name="form1" method="post" action="">
<select id="select_1" class="center_pull backend_dropbox" name="select_1">
<option value="-1" selected="selected">Browse options</option>
<option value="-1">------------------------------------</option>
<option value="224">Option 1</option>
<option value="234">Longer title for option 2</option>
<option value="242">Very long and extensively descriptive title for option 3</option>
</select>
</form>
</body>
</html>
Mat
  • 202,337
  • 40
  • 393
  • 406
aaandre
  • 2,502
  • 5
  • 33
  • 46
  • 1
    This has been answered previously on Stack Overflow: http://stackoverflow.com/questions/73960/dropdownlist-width-in-ie – Ron DeVera Mar 25 '09 at 18:11
  • Thank you for pointing that out. That solution requires the inclusion of massive javascript libraries, something I am trying to avoid. – aaandre Mar 25 '09 at 23:12
  • See if this is what you may want...http://dropdownwidthproblem.blogspot.com –  Jul 22 '11 at 23:20

23 Answers23

29

For IE 8 there is a simple pure css-based solution:

select:focus {
    width: auto;
    position: relative;
}

(You need to set the position property, if the selectbox is child of a container with fixed width.)

Unfortunately IE 7 and less do not support the :focus selector.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
rusty
  • 332
  • 3
  • 2
  • 2
    +1 for pointing out `:focus` and `width:auto`, however I think in many cases (including mine) people will want to use `position:absolute`, and probably not just on focus. If you don't use `position:absolute` the extra width might cause the dropdown to drop down a line if it was floating to the right of something (or inline-block). – Muhd Feb 08 '13 at 23:03
10

I did Google about this issue but didn't find any best solution ,So Created a solution that works fine in all browsers.

just call badFixSelectBoxDataWidthIE() function on page load.

function badFixSelectBoxDataWidthIE(){
    if ($.browser.msie){
      $('select').each(function(){
    if($(this).attr('multiple')== false){
      $(this)
          .mousedown(function(){
               if($(this).css("width") != "auto") {
                   var width = $(this).width();
                   $(this).data("origWidth", $(this).css("width"))
                          .css("width", "auto");
                   /* if the width is now less than before then undo */
                   if($(this).width() < width) {
        $(this).unbind('mousedown');
                       $(this).css("width", $(this).data("origWidth"));
                   }
               }
           })
           /* Handle blur if the user does not change the value */
           .blur(function(){
               $(this).css("width", $(this).data("origWidth"));

           })
           /* Handle change of the user does change the value */
           .change(function(){
               $(this).css("width", $(this).data("origWidth"));

           });
        }
      });
    }
    }
Falcon
  • 3,150
  • 2
  • 24
  • 35
Anoop Sharma
  • 193
  • 1
  • 11
  • 2
    this is good but it expands the actual select control, which will push anything to the right over – DaveDev Mar 09 '11 at 16:20
  • 1
    Just like DaveDev mentioned this might be an issue if you have a specific design but otherwise it is helpful and easy to implement, thanks for the code! – Mauro Morales Apr 04 '11 at 17:38
  • It expands the actual select control only when i click on them. I fill these select controls using ajax. I am currently calling it in $(document).ready() function! Am i doing something wrong? – zer0c00l Sep 20 '11 at 07:36
  • Hi zer0c00l, yes You have missed one part to binding events. You should have to call this function on ajax success as well after inserting elements to DOM element. – Anoop Sharma Jan 31 '13 at 06:51
  • yes you missed one small binding issue. You should call same function in Ajax success also after inserting things to DOM element. More clarification can be found http://blog.anoopkumarsharma.com/select-dropdown-with-fixed-width-cutting-off-content-in-ie/ – Anoop Sharma Jan 31 '13 at 06:57
  • @user558204 Whenever linking to your own site, you *must* disclose that it is yours. I know it's yours because you only just posted this code on your blog, and now are suddenly promoting it here. – Andrew Barber Jan 31 '13 at 07:27
  • Please do not use signatures/taglines in your posts. Your user box counts as your signature, and you can use your profile to post any information about yourself you like. [FAQ on signatures/taglines](http://stackoverflow.com/faq#signatures) – Andrew Barber Feb 12 '13 at 09:13
  • @Andrew Thanks. will make sure in future. – Anoop Sharma Feb 12 '13 at 13:44
7

For a simple Javascript-free solution, adding a title-attribute to your <option>s holding the text might be enough, depending on your requirements.

<option value="242" title="Very long and extensively descriptive text">
  Very long and extensively descriptive text
</option>

This will show the cut-off text in a tool-tip fashion on hovering the <option>, regardless of the width of the <select>.

Works for IE7+.

islander
  • 71
  • 1
  • 1
7

Here is a little script that should help you out:

http://www.icant.co.uk/forreview/tamingselect/

Zac
  • 12,637
  • 21
  • 74
  • 122
  • 3
    Thank you. I am wondering if anyone is aware of a javascript-free solution? – aaandre Mar 25 '09 at 21:45
  • i found this solution much better (you do not need to change your code): http://css-tricks.com/select-cuts-off-options-in-ie-fix/ – tuffo19 Jun 12 '13 at 12:25
3

Not javascript free i'm afraid, but I managed to make it quite small using jQuery

$('#del_select').mouseenter(function () {

    $(this).css("width","auto");

});

$('#del_select').mouseout(function () {

    $(this).css("width","170px");

}); 
stukerr
  • 716
  • 3
  • 10
  • 18
  • I liked your KISS approach but attempting to select would trigger mouseout. Try this: $.fn.ie_select_expando=function(){if(!$.browser.msie)return;var s = $(this);s.data('o',false);s.mouseenter(function(){if ( !s.data('owidth') ) s.data('owidth', s.css('width'));s.css("width","auto");}).mouseout(function(){if ( !s.data('o') ) s.css("width", s.data('owidth'));}).blur(function(){if ( s.data('o') ) {s.css("width", s.data('owidth'));s.data('o',false);}}).click(function() {if ( s.data('o') ) {s.css("width", s.data('owidth'));s.data('o',false);} else {s.css("width","auto");s.data('o',true);}});} – ynkr Dec 09 '10 at 11:33
3

Simply you can use this plugin for jquery ;)

http://plugins.jquery.com/project/skinner

$(function(){
          $('.select1').skinner({'width':'200px'});
});
anbi
  • 31
  • 1
2

Small, but hopefully useful update to the code from MainMa & user558204 (thanks guys), which removes the unnecessary each loop, stores a copy of $(this) in a variable in each event handler as it's used more than once, also combined the blur & change events as they had the same action.

Yes, it's still not perfect as it resizes the select element, rather than just the drop-down options. But hey, it got me out of a pickle, I (very, very unfortunately) still have to support an IE6-dominant user base across the business.

// IE test from from: https://gist.github.com/527683
var ie = (function () {
  var undef, v = 3, div = document.createElement('div'), all = div.getElementsByTagName('i');
  while (
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
    all[0]
  );
  return v > 4 ? v : undef;
} ());


function badFixSelectBoxDataWidthIE() {
  if (ie < 9) {
    $('select').not('[multiple]')
      .mousedown(function() {
        var t = $(this);
        if (t.css("width") != "auto") {
          var width = t.width();
          t.data("ow", t.css("width")).css("width", "auto");

          // If the width is now less than before then undo
          if (t.width() < width) {
            t.unbind('mousedown');
            t.css("width", t.data("ow"));
          }
        }
      })

      //blur or change if the user does change the value
      .bind('blur change', function() {
        var t = $(this);
        t.css("width", t.data("ow"));
      });
  }
}
TechSpud
  • 3,418
  • 1
  • 27
  • 35
1

A full fledged jQuery plugin is available, check out the demo page: http://powerkiki.github.com/ie_expand_select_width/

disclaimer: I coded that thing, patches welcome

PowerKiKi
  • 4,539
  • 4
  • 39
  • 47
  • Has this been tested on IE7? That's where I'm having the problem - at my client they seem to have only people who've never upgraded their browser, so they're using IE7 or they always upgrade, so they're on IE9 (or Firefox). The people who always upgrade aren't having the problem. – Paul Tomblin Sep 07 '12 at 15:49
  • As stated on the homepage, it is IE8 only. Never tested in IE7. And sorry for late reply :-/ – PowerKiKi Feb 12 '13 at 14:48
1

Why would anyone want a mouse over event on a drop down list? Here's a way of manipulating IE8 for the way a drop down list should work:

First, let's make sure we are only passing our function in IE8:

    var isIE8 = $.browser.version.substring(0, 2) === "8.";
    if (isIE8) {
       //fix me code
    }

Then, to allow the select to expand outside of the content area, let's wrap our drop down lists in div's with the correct structure, if not already, and then call the helper function:

        var isIE8 = $.browser.version.substring(0, 2) === "8.";
    if (isIE8) {
        $('select').wrap('<div class="wrapper" style="position:relative; display: inline-block; float: left;"></div>').css('position', 'absolute');

        //helper function for fix
        ddlFix();
    }

Now onto the events. Since IE8 throws an event after focusing in for whatever reason, IE will close the widget after rendering when trying to expand. The work around will be to bind to 'focusin' and 'focusout' a class that will auto expand based on the longest option text. Then, to ensure a constant min-width that doesn't shrink past the default value, we can obtain the current select list width, and set it to the drop down list min-width property on the 'onchange' binding:

    function ddlFix() {
    var minWidth;

    $('select')

    .each(function () {
        minWidth = $(this).width();
        $(this).css('min-width', minWidth);
    })
    .bind('focusin', function () {
        $(this).addClass('expand');
    })
    .change(function () {
        $(this).css('width', minWidth);
    })
    .bind('focusout', function () {
        $(this).removeClass('expand');
    });
}

Lastly, make sure to add this class in the style sheet:

 select:focus, select.expand {
    width: auto;
}
Ben Sewards
  • 2,571
  • 2
  • 25
  • 43
1

I found a pretty straightforward fix for this. In the <select> html element add these properties:

onmouseover="autoWidth(this)" 
onblur="resetWidth(this)" 

So whenever user clicks on that the width will automatically expand, and user moves out of the select box, the width will be reset to original.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
TheOnlyOne
  • 19
  • 1
1

A different approach:

  1. instead of a select make it an edit box, disabled so noone can enter anything manually or change contents after selection
  2. another hidden edit to contain an id of a selected option (explained below)
  3. make a button [..] and script it to show that div below
  4. make a hidden div with absolute position under or near the edit box
  5. make that div to contain a select with style size="6" (to show 6 options and a scrollbar rather than a drop-down list) and a button "select" and maybe "cancel"
  6. Do not style width so the whole thing will assume width of the widest option or the button plus maybe some padding of your choice
  7. script the "select" button to copy id of the selected option to the hidden edit box and it's value to the visible one, also to hide the div again.

4 simple javascript commands total.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
Kitet
  • 11
  • 1
1

similar solution can be found here using jquery to set the auto width when focus (or mouseenter) and set the orignal width back when blur (or mouseleave) http://css-tricks.com/select-cuts-off-options-in-ie-fix/.

schrodinger's code
  • 2,624
  • 1
  • 25
  • 19
1
for (i=1;i<=5;i++){
   idname = "Usert" + i;
   document.getElementById(idname).style.width = "100%";

}

I used this way to showed the drop down list when the width is not showed correctly.

It work for IE6, Firefox and Chrome.

keong
  • 11
  • 1
0

Its tested in all version of IE, Chrome, FF & Safari

// JavaScript code

    <script type="text/javascript">
    <!-- begin hiding
    function expandSELECT(sel) {
      sel.style.width = '';
    }
    function contractSELECT(sel) {
      sel.style.width = '100px';
    }
    // end hiding -->
    </script>

// Html code

    <select name="sideeffect" id="sideeffect"  style="width:100px;" onfocus="expandSELECT(this);" onblur="contractSELECT(this);" >
      <option value="0" selected="selected" readonly="readonly">Select</option>
    <option value="1" >Apple</option>
    <option value="2" >Orange + Banana + Grapes</option>
Arif
  • 1,222
  • 6
  • 29
  • 60
0

I've got yet another contribution to this. I wrote this a while back that you may find helpful: http://dpatrickcaldwell.blogspot.com/2011/06/giantdropdown-jquery-plugin-for-styling.html

It's a jquery plugin to make a styleable unordered list backed by the hidden select element.

The source is on github: https://github.com/tncbbthositg/GiantDropdown

You'd be able to handle behaviors and styles on the UL that you can't with the SELECT. Everything else should be the same because the select list is still there, it's just hidden but the UL will use it as a backing data store (if you will).

D. Patrick
  • 2,894
  • 26
  • 37
0

Here is a solution that actually works.

It sets the width in IE and doesn't mess up your page layout and doesn't close the dropdown when you mouse over the select options like some of the other solutions on this page.

You will need however to change the margin-right value and width values to match what you have for your select fields.

Also you can replace the $('select') with $('#Your_Select_ID_HERE') to only effect a specific select field. As well you will need to call the function fixIESelect() on the body onload or via jQuery using DOM ready as I did in my code below:

//////////////////////////
// FIX IE SELECT INPUT //
/////////////////////////
window.fixIESelect_clickset = false;
function fixIESelect()
{
 if ($.browser.msie)
 {
  $('select').mouseenter(function ()
  {
   $(this).css("width","auto");
   $(this).css("margin-right","-100");
  });
  $('select').bind('click focus',function ()
  {
   window.fixIESelect_clickset = true;
  });
  $('select').mouseout(function ()
  {
   if(window.fixIESelect_clickset != true)
   {
    $(this).css("width","93px");
    window.fixIESelect_clickset = false;
   }
  });
  $('select').bind('blur change',function ()
  {
   $(this).css("width","93px");
  });
 }
}
/////////////
// ONLOAD //
////////////
$(document).ready(function()
{
 fixIESelect();
});
Littm
  • 4,923
  • 4
  • 30
  • 38
Gallagher
  • 31
  • 5
0

I wanted this to work with selects that I added dynamically to the page, so after a lot of experimentation, I ended up giving all the selects that I wanted to do this with the class "fixedwidth", and then added the following CSS:

table#System_table select.fixedwidth { width: 10em; }
table#System_table select.fixedwidth.clicked { width: auto; }

and this code

<!--[if lt IE 9]>
    <script type="text/javascript">
        jQuery(document).ready(function() {
            jQuery(document).on(
              {
                'mouseenter': function(event) {
                    jQuery(this).addClass('clicked');
                    },
                'focusout change blur': function() {
                    jQuery(this).removeClass('clicked');
                    }
              }, 'select.fixedwidth');
        });
    </script>
<![endif]-->

A couple of things to note:

  • In spite of the fact that my selects are all in a table, I had to do "on" to the jQuery(document).on instead of to jQuery('table#System_table').on
  • In spite of the fact that the jQuery documentation says to use "mouseleave" instead of "blur", I found that in IE7 when I moved the mouse down the drop down list, it would get a mouseleave event but not a blur.
Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
0

For my layout, I didn't want a hack (no width increasing, no on click with auto and then coming to original). It broke my existing layout. I just wanted it to work normally like other browsers.

I found this to be exactly like that :-

http://www.jquerybyexample.net/2012/05/fix-for-ie-select-dropdown-with-fixed.html

Steve
  • 2,546
  • 8
  • 49
  • 94
0

A workaround if you don't care about the strange view after an option is selected (i.e. Select to jump to a new page):

<!-- Limit width of the wrapping div instead of the select and use 'overflow: hidden' to hide the right part of it. -->
<div style='width: 145px; overflow: hidden; border-right: 1px solid #aaa;'>
  <select onchange='jump();'>
    <!-- '&#9660;(▼)' produces a fake dropdown indicator -->
    <option value=''>Jump to ... &#9660;</option>
    <option value='1'>http://stackoverflow.com/questions/682764/select-dropdown-with-fixed-width-cutting-off-content-in-ie</option>
    ...
  </select>
</div>
Mergen Wu
  • 1
  • 1
0

Not javascript free, I am afraid too and my solution do require a js library, however, you can only use those files which you need rather than using them all, maybe best suited for those who are already using YUI for their projects or deciding which one to use. Have a look at: http://ciitronian.com/blog/programming/yui-button-mimicking-native-select-dropdown-avoid-width-problem/

My blog post also discusses other solutions as well, one is referenced back to here on stackoverflow, why I went back to create my own SELECT element is because of simple reason, I don't like mouseover expand events. Maybe if that helps anyone else too!

Hammad Tariq
  • 1,523
  • 3
  • 14
  • 29
0

A pure css solution : http://bavotasan.com/2011/style-select-box-using-only-css/

.styled-select select {
   background: transparent;
   width: 268px;
   padding: 5px;
   font-size: 16px;
   line-height: 1;
   border: 0;
   border-radius: 0;
   height: 34px;
   -webkit-appearance: none;
   }

.styled-select {
   width: 240px;
   height: 34px;
   overflow: hidden;
   background: url(http://cdn.bavotasan.com/wp-content/uploads/2011/05/down_arrow_select.jpg) no-repeat right #ddd;
   border: 1px solid #ccc;
   }
<div class="styled-select">
   <select>
      <option>Here is the first option</option>
      <option>The second option</option>
   </select>
</div>
Teenage
  • 210
  • 2
  • 6
0

The jquery BalusC's solution improved by me. Used also: Brad Robertson's comment here.

Just put this in a .js, use the wide class for your desired combos and don't forge to give it an Id. Call the function in the onload (or documentReady or whatever).
As simple ass that :)
It will use the width that you defined for the combo as minimun length.

function fixIeCombos() {
    if ($.browser.msie && $.browser.version < 9) {
    var style = $('<style>select.expand { width: auto; }</style>');
    $('html > head').append(style);

    var defaultWidth = "200";

    // get predefined combo's widths.
    var widths = new Array();
    $('select.wide').each(function() {
        var width = $(this).width();
        if (!width) {
        width = defaultWidth;
        }
        widths[$(this).attr('id')] = width;
    });

    $('select.wide')
    .bind('focus mouseover', function() {
        // We're going to do the expansion only if the resultant size is bigger
        // than the original size of the combo.
        // In order to find out the resultant size, we first clon the combo as
        // a hidden element, add to the dom, and then test the width.
        var originalWidth = widths[$(this).attr('id')];

        var $selectClone = $(this).clone();
        $selectClone.addClass('expand').hide();
        $(this).after( $selectClone );
        var expandedWidth = $selectClone.width()
        $selectClone.remove();
        if (expandedWidth > originalWidth) {
        $(this).addClass('expand').removeClass('clicked');
        }
    })
    .bind('click', function() {
        $(this).toggleClass('clicked'); 
    })
    .bind('mouseout', function() {
        if (!$(this).hasClass('clicked')) {
        $(this).removeClass('expand');
        }
    })
    .bind('blur', function() {
        $(this).removeClass('expand clicked');
    })
    }
}
Community
  • 1
  • 1
-1

Best solution: css + javascript

http://css-tricks.com/select-cuts-off-options-in-ie-fix/

var el;

$("select")
  .each(function() {
    el = $(this);
    el.data("origWidth", el.outerWidth()) // IE 8 can haz padding
  })
  .mouseenter(function(){
    $(this).css("width", "auto");
  })
  .bind("blur change", function(){
    el = $(this);
    el.css("width", el.data("origWidth"));
  });
tuffo19
  • 310
  • 3
  • 8