34

Maybe this is an easy question, maybe not. I have a select box where I hardcode with width. Say 120px.

<select style="width: 120px">
  <option>REALLY LONG TEXT, REALLY LONG TEXT, REALLY LONG TEXT</option>
  <option>ABC</option>
</select>

I want to be able to show the second option so that the user can see the full length of the text.

Like everything else. This works fine in Firefox, but doesn't work with Internet Explorer6.

João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
Berlin Brown
  • 11,504
  • 37
  • 135
  • 203

13 Answers13

13

I fixed my problem with the following code:

<div style="width: 180px; overflow: hidden;">
   <select style="width: auto;" name="abc" id="10">
     <option value="-1">AAAAAAAAAAA</option>
     <option value="123">123</option>
   </select>
</div>

Hope it helps!

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
12

If you have the option pre-existing in a fixed-with <select>, and you don't want to change the width programmatically, you could be out of luck unless you get a little creative.

  • You could try and set the title attribute to each option. This is non-standard HTML (if you care for this minor infraction here), but IE (and Firefox as well) will display the entire text in a mouse popup on mouse hover.
  • You could use JavaScript to show the text in some positioned DIV when the user selects something. IMHO this is the not-so-nice way to do it, because it requires JavaScript on to work at all, and it works only after something has been selected - before there is a change in value no events fire for the select box.
  • You don't use a select box at all, but implement its functionality using other markup and CSS. Not my favorite but I wanted to mention it.

If you are adding a long option later through JavaScript, look here: How to update HTML “select” box dynamically in IE

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Tomalak
  • 332,285
  • 67
  • 532
  • 628
6

Very old question but here's the solution. Here you have a working snippet using jquery. It makes use of a temporary auxiliary select into which the selected option from the main select is copied, such that one can assess the true width which the main select should have.

$('select').change(function(){
  var text = $(this).find('option:selected').text()
  var $aux = $('<select/>').append($('<option/>').text(text))
  $(this).after($aux)
  $(this).width($aux.width())
  $aux.remove()
}).change()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select>
  <option>ABC</option>
  <option>REALLY LONG TEXT, REALLY LONG TEXT, REALLY LONG TEXT</option>
</select>
João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
  • 1
    This works well. What do you do if the longest option is not the first one? It still loads at the width of the longest option, then resizes on change. I will play around with it, but maybe you've already thought about this... – Jeff Lindblom Jul 09 '19 at 16:35
  • @JeffLindblom I swapped the elements as you suggested and slightly amended the code. To overcome that problem you just need to `trigger` the event after declaration. You may test now. – João Pimentel Ferreira Jul 10 '19 at 20:20
  • @JoãoPimentelFerreira How would you do the same thing in vanilla Js without jquery ? – AziCode Mar 29 '21 at 14:12
  • 1
    @AziCode There you go: https://stackoverflow.com/a/67240166/4168960 – kilian Apr 24 '21 at 07:04
5

I fixed it in my bootstrap page by setting the min-width and max-width to the same value in the select and then setting the select:focus to auto.

select {
  min-width: 120px;
  max-width: 120px;
}
select:focus {
  width: auto;
}
<select style="width: 120px">
  <option>REALLY LONG TEXT, REALLY LONG TEXT, REALLY LONG TEXT</option>
  <option>ABC</option>
</select>
Ruslan López
  • 4,433
  • 2
  • 26
  • 37
iansoccer9
  • 67
  • 1
  • 1
5

Place it in a div and give it an id

<div id=myForm>

then create a really really simple css to go with it.

#myForm select { 
width:200px; }

#myForm select:focus {
width:auto; }

That's all you need.

tpham211
  • 51
  • 1
  • 1
4

This mimics most of the behavior your looking for:

  <!--

     I found this works fairly well.

  -->

  <!-- On page load, be sure that something else has focus. -->
  <body onload="document.getElementById('name').focus();">
  <input id=name type=text>

  <!-- This div is for demonstration only.  The parent container may be anything -->
  <div style="height:50; width:100px; border:1px solid red;">

  <!-- Note: static width, absolute position but no top or left specified, Z-Index +1 -->
  <select
   style="width:96px; position:absolute; z-index:+1;"
   onactivate="this.style.width='auto';"
   onchange="this.blur();"
   onblur="this.style.width='96px';">
  <!-- "activate" happens before all else and "width='auto'" expands per content -->
  <!-- Both making a selection and moving to another control should return static width -->

  <option>abc</option>
  <option>abcdefghij</option>
  <option>abcdefghijklmnop</option>
  <option>abcdefghijklmnopqrstuvwxyz</option>

  </select>

  </div>

  </body>

  </html>

This will override some of the key-press behavior.

Doug Peil
  • 49
  • 1
  • 2
3

Even though this question is from 2008, there are still cases where you want the select box to match the width of the current selection rather than the longest option. So here's a modern approach to it:

It's more or less the same principle like in this answer just without jQuery.

  1. Get the select element and listen for changes on it.
  2. Create a new select element and option and pass the text of the current selectedIndex to the option.
  3. Add position: fixed and visibility: hidden styles to the new select element. This ensures, that it is not affecting your layout but its bounding box can still be measured.
  4. Append the option to the select.
  5. Append the select to the original select element.
  6. Get the needed dimensions of that new one using getBoundingClientRect().width
  7. Set the width of the original one based on the dimensions of the new one.
  8. Remove the new one.
  9. Dispatch a change event to trigger this logic initially.

const select = document.querySelector('select')

select.addEventListener('change', (event) => {
  let tempSelect = document.createElement('select'),
      tempOption = document.createElement('option');

  tempOption.textContent = event.target.options[event.target.selectedIndex].text;
  tempSelect.style.cssText += `
      visibility: hidden;
      position: fixed;
      `;
  tempSelect.appendChild(tempOption);
  event.target.after(tempSelect);
  
  const tempSelectWidth = tempSelect.getBoundingClientRect().width;
  event.target.style.width = `${tempSelectWidth}px`;
  tempSelect.remove();
});

select.dispatchEvent(new Event('change'));
<select>
  <option>Short option</option>
  <option>Some longer option</option>
  <option>An very long option with a lot of text</option>
</select>
kilian
  • 166
  • 1
  • 9
1

Sample

function PopulateDropdown() {
    $.ajax({
        type: "POST",
        url: "../CommonWebService.asmx/GetData",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (msg) {
            $("select[id^='MyDropDown']").empty();
            $.each(msg.d, function () {
                $("select[id^='MyDropDownSelect']").append($("<option></option>").val(this['IdIndexDataType']).html(this['DataTypeName']));
            }); 
            $("select[id^='MyDropDown']").css("width", "auto");  
        },
        error: function (e1) {
            alert("Error - " + e1.toString());
        }
    });
}

The below code will solve your problem of dropdownlist width by adding this code after insertion of Data to dropdownlist.

$("select[id^='MyDropDown']").css("width", "auto");
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Doni
  • 11
  • 2
1

Okay, this option is pretty hackish but should work.

$(document).ready( function() {
$('#select').change( function() {
    $('#hiddenDiv').html( $('#select').val() );
    $('#select').width( $('#hiddenDiv').width() );
 }
 }

Which would offcourse require a hidden div.

<div id="hiddenDiv" style="visibility:hidden"></div>

ohh and you will need jQuery

Pim Jager
  • 31,965
  • 17
  • 72
  • 98
  • 1
    Why is it that there seems to be no way around jQuery when it comes to JavaScript questions? Adding jQuery to your web site to solve *this* problem is overkill. – Tomalak Nov 16 '08 at 16:26
  • mostly because regular javascript pisses me of so much I always use jQuery (like most people who started with PHP and then also started doing javascript) And writing jQuery is much easier and faster (for me it is). – Pim Jager Nov 16 '08 at 17:46
  • 1
    JavaScript is a beautiful language (unlike PHP, which resides close to the other end of the spectrum), only complex DOM manipulation is annoying. Trivial DOM manipulation is... well, trivial. :-) No need for a full-blown JS framework. – Tomalak Nov 16 '08 at 18:14
  • I agree, the question was about standartized Javascript, not about non-standard jQuery. It does not matter how good or bad they are or how much one likes or dislikes them. Will we soon start seeing "just use C" answers to Cobol questions? – buti-oxa Nov 16 '08 at 19:48
  • First, if the questioner doesn't wan't to use the answer, he simply can decide not to use it. Secondly, this is the only complete answer that actually answers the question. And you can quite simply replace all the jQuery in here with standard Javascript. So if you want to, Do so. – Pim Jager Nov 17 '08 at 16:56
1

A simple solution I used for an existing site in IE (using jQuery, but I can post back with eventListener code if you really don't know JS that well) is the following:

if (jQuery.browser.msie) {
  jQuery('#mySelect').focus(function() {
    jQuery(this).width('auto');
  }).bind('blur change', function() {
    jQuery(this).width('100%');
  });
};

Of course, use a variable (var cWidth = jQuery('#mySelect').width();) to store the previous width, but this is all that was required for ours to work as you'd expect.

Eric
  • 2,037
  • 2
  • 16
  • 14
1

I've created styled select element with auto expand, with just a minimal JS, based on data attribute and hidden CSS pseudo element.

Array.from(document.querySelectorAll('.js-select-auto-expand'), (input) => {
  let parent = input.parentNode;
  
  function updateSize() {
    parent.dataset.selectAutoExpand = input.value
  }
  
  input.addEventListener('input', updateSize);
  
  updateSize();
});
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  padding: 2rem 4rem;
  line-height: 1.5;
  color: gray;
}

.article-test {
  line-height: 2.5;
}

.select-auto-expand {
  position: relative;
  display: inline-block;
  min-width: 2rem;
  width: auto;
  height: 30px;
  line-height: 28px;
  padding: 0 10px;
  vertical-align: baseline;
  border: 1px solid black;
  background-color: transparent;
  color: #fafafa;
  font-size: 1rem;
}
.select-auto-expand .select-auto-expand__select {
  position: absolute;
  top: 0px;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  min-width: 1em;
  height: 100%;
  margin: 0 2px;
  padding: 0 8px;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border-radius: 0;
  border: 0;
  background: transparent;
  font: inherit;
}
.select-auto-expand::after {
  content: attr(data-select-auto-expand);
  display: inline-block;
  width: 100%;
  min-width: 1em;
  white-space: pre-wrap;
  font: inherit;
  line-height: inherit;
  color: inherit;
  background: transparent;
  visibility: hidden;
  opacity: 0;
}
.select-auto-expand:focus-within {
  outline: 3px solid rgba(0, 0, 255, 0.3);
}
.select-auto-expand:focus-within input:focus {
  outline: none;
}
<form action="#" class="article-test">

  <p>
    Adipisci ipsum debitis quaerat commodi tenetur? Amet consectetur adipisicing elit. Lorem ipsum dolor sit, 
    <label class="select-auto-expand" for="pet-select">
      <select name="pets" id="pet-select" class="select-auto-expand__select js-select-auto-expand">
        <option value="select ...">select ...</option>
        <option value="sed qui">sed qui</option>
        <option value="veniam iste quis">veniam iste quis</option>
        <option value="ipsum debitis">ipsum debitis</option>
        <option value="officia excepturi repellendus aperiam">officia excepturi repellendus aperiam</option>
      </select>
    </label>
    veniam iste quis, sed qui non dolores. Porro, soluta. Officia excepturi repellendus aperiam cumque consectetur distinctio, veniam iste quis, sed qui non dolores. Adipisci ipsum debitis quaerat commodi tenetur?
  </p>

</form>

Demo: https://codepen.io/astro87/pen/dyZerdg?editors=0010

Inspired by: https://filamentgroup.github.io/select-css/demo/ https://codepen.io/shshaw/full/bGNJJBE

Bartek
  • 810
  • 7
  • 9
0

I improved the cychan's solution, to be like that:

<html>
<head>

<style>
    .wrapper{
        display: inline;
        float: left; 
        width: 180px; 
        overflow: hidden; 
    }
    .selectArrow{
        display: inline;
        float: left;
        width: 17px;
        height: 20px;
        border:1px solid #7f9db9;
        border-left: none;
        background: url('selectArrow.png') no-repeat 1px 1px;
    }
    .selectArrow-mousedown{background: url('selectArrow-mousedown.png') no-repeat 1px 1px;}
    .selectArrow-mouseover{background: url('selectArrow-mouseover.png') no-repeat 1px 1px;}
</style>
<script language="javascript" src="jquery-1.3.2.min.js"></script>

<script language="javascript">
    $(document).ready(function(){
        $('#w1').wrap("<div class='wrapper'></div>");
        $('.wrapper').after("<div class='selectArrow'/>");
        $('.wrapper').find('select').mousedown(function(){
            $(this).parent().next().addClass('selectArrow-mousedown').removeClass('selectArrow-mouseover');
        }).
        mouseup(function(){
            $(this).parent().next().removeClass('selectArrow-mousedown').addClass('selectArrow-mouseover');
        }).
        hover(function(){
            $(this).parent().next().addClass('selectArrow-mouseover');
        }, function(){
            $(this).parent().next().removeClass('selectArrow-mouseover');
        });

        $('.selectArrow').click(function(){
            $(this).prev().find('select').focus();
        });

        $('.selectArrow').mousedown(function(){
            $(this).addClass('selectArrow-mousedown').removeClass('selectArrow-mouseover');
        }).
        mouseup(function(){
            $(this).removeClass('selectArrow-mousedown').addClass('selectArrow-mouseover');
        }).
        hover(function(){
            $(this).addClass('selectArrow-mouseover');
        }, function(){
            $(this).removeClass('selectArrow-mouseover');
        });
    });

</script>
</head>
<body>
    <select id="w1">
       <option value="0">AnyAnyAnyAnyAnyAnyAny</option>
       <option value="1">AnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAny</option>
    </select>

</body>
</html>

The PNGs used in css classes are uploaded here...

And you still need JQuery.....

Saeed
  • 926
  • 16
  • 28
0

you can try and solve using css only. by adding class to select

select{ width:80px;text-overflow:'...';-ms-text-overflow:ellipsis;position:absolute; z-index:+1;}
select:focus{ width:100%;}

for more reference List Box Style in a particular item (option) HTML

Multi Select List Box

Community
  • 1
  • 1