8

For example, I have something like this:

With the following HTML code, I set the max width of the entire dropdown to be 80%, which I expect to affect each of the options.

I want to have it so that long options wrap around at the max point:

Where the red lines indicate what is considered "one option", and thus when I hover over it, everything in between the red lines should be selected

<select name=countries style="width:100%;max-width:30%;">
    <option value=gs selected="selected">All</option>
    <option value=gs>This is fine</option>
    <option value=gs>This message should wrap because it is very long</option>
    <optgroup label="Title">
        <option value="optcheck">Option groups are long, so they should wrap too</option>
    </optgroup>
</select>

https://jsfiddle.net/pxl70474/x7w85fnm/

double-beep
  • 5,031
  • 17
  • 33
  • 41
K Split X
  • 3,405
  • 7
  • 24
  • 49
  • Not sure if you can modify the styles of the `option` tag as it's presented native to the platform. Have a look here: https://stackoverflow.com/questions/3354979/styling-part-of-the-option-text – Gurtej Singh Nov 19 '18 at 03:38

6 Answers6

3

You could try rewriting it like this. I pulled this out of W3Schools. This simply writes the select menu for a responsive view. You could apply it for your site as it does wrap the text. Or figure out some other way to apply it to your site.

var x, i, j, selElmnt, a, b, c;
/*look for any elements with the class "custom-select":*/
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
  selElmnt = x[i].getElementsByTagName("select")[0];
  /*for each element, create a new DIV that will act as the selected item:*/
  a = document.createElement("DIV");
  a.setAttribute("class", "select-selected");
  a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
  x[i].appendChild(a);
  /*for each element, create a new DIV that will contain the option list:*/
  b = document.createElement("DIV");
  b.setAttribute("class", "select-items select-hide");
  for (j = 0; j < selElmnt.length; j++) {
    /*for each option in the original select element,
    create a new DIV that will act as an option item:*/
    c = document.createElement("DIV");
    c.innerHTML = selElmnt.options[j].innerHTML;
    c.addEventListener("click", function(e) {
        /*when an item is clicked, update the original select box,
        and the selected item:*/
        var y, i, k, s, h;
        s = this.parentNode.parentNode.getElementsByTagName("select")[0];
        h = this.parentNode.previousSibling;
        for (i = 0; i < s.length; i++) {
          if (s.options[i].innerHTML == this.innerHTML) {
            s.selectedIndex = i;
            h.innerHTML = this.innerHTML;
            y = this.parentNode.getElementsByClassName("same-as-selected");
            for (k = 0; k < y.length; k++) {
              y[k].removeAttribute("class");
            }
            this.setAttribute("class", "same-as-selected");
            break;
          }
        }
        h.click();
    });
    b.appendChild(c);
  }
  x[i].appendChild(b);
  a.addEventListener("click", function(e) {
      /*when the select box is clicked, close any other select boxes,
      and open/close the current select box:*/
      e.stopPropagation();
      closeAllSelect(this);
      this.nextSibling.classList.toggle("select-hide");
      this.classList.toggle("select-arrow-active");
    });
}
function closeAllSelect(elmnt) {
  /*a function that will close all select boxes in the document,
  except the current select box:*/
  var x, y, i, arrNo = [];
  x = document.getElementsByClassName("select-items");
  y = document.getElementsByClassName("select-selected");
  for (i = 0; i < y.length; i++) {
    if (elmnt == y[i]) {
      arrNo.push(i)
    } else {
      y[i].classList.remove("select-arrow-active");
    }
  }
  for (i = 0; i < x.length; i++) {
    if (arrNo.indexOf(i)) {
      x[i].classList.add("select-hide");
    }
  }
}
/*if the user clicks anywhere outside the select box,
then close all select boxes:*/
document.addEventListener("click", closeAllSelect);
/*the container must be positioned relative:*/
.custom-select {
  position: relative;
  font-family: Arial;
}
.custom-select select {
  display: none; /*hide original SELECT element:*/
}
.select-selected {
  background-color: DodgerBlue;
}
/*style the arrow inside the select element:*/
.select-selected:after {
  position: absolute;
  content: "";
  top: 14px;
  right: 10px;
  width: 0;
  height: 0;
  border: 6px solid transparent;
  border-color: #fff transparent transparent transparent;
}
/*point the arrow upwards when the select box is open (active):*/
.select-selected.select-arrow-active:after {
  border-color: transparent transparent #fff transparent;
  top: 7px;
}
/*style the items (options), including the selected item:*/
.select-items div,.select-selected {
  color: #ffffff;
  padding: 8px 16px;
  border: 1px solid transparent;
  border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
  cursor: pointer;
  user-select: none;
}
/*style items (options):*/
.select-items {
  position: absolute;
  background-color: DodgerBlue;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 99;
}
/*hide the items when the select box is closed:*/
.select-hide {
  display: none;
}
.select-items div:hover, .same-as-selected {
  background-color: rgba(0, 0, 0, 0.1);
}
<div class="custom-select" style="width:500px;">
  <select>
    <option value="0">HTML5</option>
    <option value="1">Option groups are long, so they should wrap too</option>
    <optgroup label="Title">
      <option value="optcheck">Hypertext Markup Language, a standardized system for tagging text files to achieve font, color, graphic, and hyperlink effects on World Wide Web pages.</option>    
    </optgroup>
  </select>
</div>
Millhorn
  • 2,953
  • 7
  • 39
  • 77
  • While this is not a simple solution, it does exactly what I needed it to do. No bugs or issues at all! It's responsive and has accommodated text options of all lengths. – globalSchmidt Dec 01 '19 at 16:00
  • As a follow on, is there anyway to copy data attributes from the "original" options to the 'select-selected' and hidden 'select-items' divs? Using jquery, I need to access the data attribute when the option is chosen and the divs don't have the data attributes supplied to the original – globalSchmidt Dec 02 '19 at 00:22
  • 1
    Hello, why the Group title does not appear in this custom select? – Lenin Zapata Apr 04 '20 at 16:57
3

If you are using bootstrap you can use the bootstrap selectpicker class with the data-content attribute.

 <select class="selectpicker form-control" data-live-search="true" 
     id="subject_teacher_drop_down">
   <option data-content="English" title="English">English</option>
   <option data-content="Methodology of social..."  title="Methodology of social science 
     with special reference to economics">
     Methodology of social science with special reference to economics
   </option>
 </select>
RoshJ
  • 461
  • 1
  • 6
  • 24
3

To make word wrap, try this css to extend height of container to make enough space to wrap text.

option {
    max-width: 100%;
    overflow: hidden;
    word-wrap: normal !important;
    white-space: normal;
}
Young Kim
  • 45
  • 3
0

This simple change worked for me.

option {
     white-space: break-spaces;
}
0

Expanding on Pulin's answer

To get this to work in Firefox, I needed to target the :before pseudoelement:

option:before {
  white-space: break-spaces;
}

This let my multi-select options take up more than one line of text!

Nate Ferrero
  • 1,408
  • 14
  • 15
0

Having been unable to use other suggestions successfully, I went with the react-select component. Obviously, only useful if you are using React, but it's a very decent/attractive and easy solution if you are.

Coder
  • 2,833
  • 2
  • 22
  • 24