Here's a plugin I just wrote for this question that dynamically creates and destroys a mock span
so it doesn't clutter up your html. This helps separate concerns, lets you delegate that functionality, and allows for easy reuse across multiple elements.
Include this JS anywhere:
(function($, window){
$(function() {
let arrowWidth = 30;
$.fn.resizeselect = function(settings) {
return this.each(function() {
$(this).change(function(){
let $this = $(this);
// get font-weight, font-size, and font-family
let style = window.getComputedStyle(this)
let { fontWeight, fontSize, fontFamily } = style
// create test element
let text = $this.find("option:selected").text();
let $test = $("<span>").html(text).css({
"font-size": fontSize,
"font-weight": fontWeight,
"font-family": fontFamily,
"visibility": "hidden" // prevents FOUC
});
// add to body, get width, and get out
$test.appendTo($this.parent());
let width = $test.width();
$test.remove();
// set select width
$this.width(width + arrowWidth);
// run on start
}).change();
});
};
// run by default
$("select.resizeselect").resizeselect();
})
})(jQuery, window);
You can initialize the plugin in one of two ways:
-
HTML - Add the class .resizeselect
to any select element:
<!-- language: lang-html -->
<pre><code><select class="btn btn-select <b>resizeselect</b>">
<option>All</option>
<option>Longer</option>
<option>A very very long string...</option>
</select>
</code></pre>
-
JavaScript - Call .resizeselect()
on any jQuery object:
<!-- language: lang-js -->
<pre><code>$("select").<b>resizeselect</b>()</code></pre>
Demo in jsFiddle and StackSnippets:
<!-- begin snippet: js hide: true console: false babel: false -->
<!-- language: lang-js -->
(function($, window){
$(function() {
let arrowWidth = 30;
$.fn.resizeselect = function(settings) {
return this.each(function() {
$(this).change(function(){
let $this = $(this);
// get font-weight, font-size, and font-family
let style = window.getComputedStyle(this)
let { fontWeight, fontSize, fontFamily } = style
// create test element
let text = $this.find("option:selected").text();
let $test = $("<span>").html(text).css({
"font-size": fontSize,
"font-weight": fontWeight,
"font-family": fontFamily,
"visibility": "hidden" // prevents FOUC
});
// add to body, get width, and get out
$test.appendTo($this.parent());
let width = $test.width();
$test.remove();
// set select width
$this.width(width + arrowWidth);
// run on start
}).change();
});
};
// run by default
$("select.resizeselect").resizeselect();
})
})(jQuery, window);
<!-- language: lang-html -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<select class="resizeselect">
<option>All</option>
<option>Longer</option>
<option>A very very long string...</option>
</select>
<!-- end snippet -->
Updated to include sizing suggestions from Garywoo & Eric Warnke