Verschachteln von Optgruppen in einer Dropdown-Liste / Auswahl

78

Ich habe ein c # DropDownList-Steuerelement für Kunden erstellt, mit dem der Inhalt als Optgroups dargestellt werden kann (nicht von Grund auf neu, ich habe im Internet gefundenen Code bearbeitet, obwohl ich genau verstehe, was es tut), und es funktioniert einwandfrei.

Jetzt bin ich jedoch auf eine Situation gestoßen, in der ich zwei Einrückungsstufen in meinem Dropdown-Menü haben muss, d. H.

<select>
  <optgroup label="Level One">
    <option> A.1 </option>
    <optgroup label="Level Two">
      <option> A.B.1 </option>
    </optgroup>
    <option> A.2 </option>
  </optgroup>
</select>

In dem obigen Beispiel-Snippet wird es jedoch so gerendert, als ob Level Twoes die gleiche Einrückung wie hätte Level One.

Gibt es eine Möglichkeit, das von mir gesuchte Verhalten verschachtelter Optgruppen zu erzeugen?

Ed James
quelle
Dieses Problem wurde als Vorschlag zur HTMLWG hinzugefügt: github.com/whatwg/html/issues/5789
oriadam

Antworten:

67

Die HTML-Spezifikation hier ist wirklich kaputt. Es sollte verschachtelte Optgruppen zulassen und Benutzeragenten empfehlen, sie als verschachtelte Menüs zu rendern. Stattdessen ist nur eine Optgruppenebene zulässig . Zu diesem Thema müssen sie jedoch Folgendes sagen:

Hinweis. Implementierer werden darauf hingewiesen, dass zukünftige HTML-Versionen den Gruppierungsmechanismus möglicherweise erweitern, um verschachtelte Gruppen zuzulassen (dh OPTGROUP-Elemente können verschachtelt sein). Auf diese Weise können Autoren eine reichhaltigere Auswahlhierarchie darstellen.

Und Benutzeragenten könnten Untermenüs verwenden, um Optgoups zu rendern, anstatt wie bisher Titel vor dem ersten Optionselement in einer Optgruppe anzuzeigen.

Raphael Schweikert
quelle
Das stimmt, Sie können keinen verschachtelten Baum mit mehreren Ebenen mit Optionsgruppen erstellen, auch nicht mit HTML 5, auch die Notiz ist falsch.
inf3rno
Weiß jemand, ob er dies in HTML5 besuchen möchte? Scheint ein massives Versehen zu sein.
Sweepster
18
Gemäß der HTML5 spec ( dev.w3.org/html5/markup/optgroup.html#optgroup ) dem einzigen erlaubten Elternteil optgroupist select, die vorschlagen , dass kein wird diese in HTML5 nicht unterstützt.
Dan Atkinson
2
Weiß jemand, ob verschachtelte Optgruppen auf der Roadmap stehen?
Snæbjørn
51

Dies ist in Ordnung, aber wenn Sie eine Option hinzufügen, die nicht in optgroup enthalten ist, wird sie fehlerhaft.

<select>
  <optgroup label="Level One">
    <option> A.1 </option>
    <optgroup label="&nbsp;&nbsp;&nbsp;&nbsp;Level Two">
      <option>&nbsp;&nbsp;&nbsp;&nbsp; A.B.1 </option>
    </optgroup>
    <option> A.2 </option>
  </optgroup>
  <option> A </option>
</select>

Wäre viel besser, wenn Sie CSS verwenden und optgroup sofort schließen würden:

<select>
  <optgroup label="Level One"></optgroup>
  <option style="padding-left:15px"> A.1 </option>
  <optgroup label="Level Two" style="padding-left:15px"></optgroup>
  <option style="padding-left:30px"> A.B.1 </option>
  <option style="padding-left:15px"> A.2 </option>
  <option> A </option>
</select>

Adam
quelle
1
Perfekt, viel einfacher, da Sie style="padding-left:'. (15 * $level). 'px"in einer Schleife über einen Baum von Gegenständen arbeiten können.
Xeoncross
3
Leider funktioniert dies nicht in Safari, da paddingin <option>nicht gerendert wird
Markus
4
CSS zur Rettung: Sie können die linke Auffüllung entfernen und stattdessen einen Texteinzug verwenden, indem Sie der Breite Ihres Auswahlfelds den gleichen Betrag hinzufügen (Quelle: stackoverflow.com/questions/2966855/… )
Potherca
Das ist kein Buggy, es ist so definiert. Option A ist nicht Teil einer Gruppe.
Suncat2000
44

Ok, wenn jemand dies jemals liest: Die beste Option ist, vier &nbsp;s bei jeder zusätzlichen Einrückungsstufe hinzuzufügen , wie es scheint!

damit:

<select>
 <optgroup label="Level One">
  <option> A.1 </option>
  <optgroup label="&nbsp;&nbsp;&nbsp;&nbsp;Level Two">
   <option>&nbsp;&nbsp;&nbsp;&nbsp; A.B.1 </option>
  </optgroup>
  <option> A.2 </option>
 </optgroup>
</select>

Ed James
quelle
115
Auf diese Weise können Sie die Benutzerfreundlichkeit Ihrer Auswahl buchstäblich beeinträchtigen, indem Sie Benutzern nicht erlauben, den ersten Buchstaben eines Elements zu drücken, um schnell zu diesem Buchstaben zu blättern.
Geoffrey Bachelet
41
Paradoxerweise, Geoffrey, verbessert es gleichzeitig die Benutzerfreundlichkeit, indem es eine visuelle Hierarchie bereitstellt. Lustige alte Welt.
Jake Rayson
1
Ein weiterer Grund, warum dies nicht ideal ist, ist eine ausgewählte Option mit vielen Einrückungen, die ungewöhnlich aussieht, wenn die Auswahl aufgrund der gesamten Polsterung nicht aktiv ist
Ryan
12
Überprüfen Sie das DOM ... die optgroupssind nicht wirklich verschachtelt. Zumindest in Firefox. Es schließt die erste Optgruppe, wenn es die zweite sieht.
Mpen
1
@DarkSide Dies ist ein sehr sehr altes Frage / Antwort-Paar, daher war ich froh, dass ich den Vorteil des Zweifels geben konnte, aber ich habe es gerade in Chrome 38.0.2125.104 versucht und nein, es funktioniert wie erwartet.
Ed James
16

<style>
  .NestedSelect{display: inline-block; height: 100px; border: 1px Black solid; overflow-y: scroll;}
  .NestedSelect label{display: block; cursor: pointer;}
  .NestedSelect label:hover{background-color: #0092ff; color: White;}
  .NestedSelect input[type="radio"]{display: none;}
  .NestedSelect input[type="radio"] + span{display: block; padding-left: 0px; padding-right: 5px;}
  .NestedSelect input[type="radio"]:checked + span{background-color: Black; color: White;}
  .NestedSelect div{margin-left: 15px; border-left: 1px Black solid;}
  .NestedSelect label > span:before{content: '- ';}
</style>

<div class="NestedSelect">
  <label><input type="radio" name="MySelectInputName"><span>Fruit</span></label>
  <div>
    <label><input type="radio" name="MySelectInputName"><span>Apple</span></label>
    <label><input type="radio" name="MySelectInputName"><span>Banana</span></label>
    <label><input type="radio" name="MySelectInputName"><span>Orange</span></label>
  </div>

  <label><input type="radio" name="MySelectInputName"><span>Drink</span></label>
  <div>
    <label><input type="radio" name="MySelectInputName"><span>Water</span></label>

    <label><input type="radio" name="MySelectInputName"><span>Soft</span></label>
    <div>
      <label><input type="radio" name="MySelectInputName"><span>Cola</span></label>
      <label><input type="radio" name="MySelectInputName"><span>Soda</span></label>
      <label><input type="radio" name="MySelectInputName"><span>Lemonade</span></label>
    </div>

    <label><input type="radio" name="MySelectInputName"><span>Hard</span></label>
    <div>
      <label><input type="radio" name="MySelectInputName"><span>Bear</span></label>
      <label><input type="radio" name="MySelectInputName"><span>Whisky</span></label>
      <label><input type="radio" name="MySelectInputName"><span>Vodka</span></label>
      <label><input type="radio" name="MySelectInputName"><span>Gin</span></label>
    </div>
  </div>
</div>

Gebrochener Pfeil
quelle
Dies funktioniert automatisch für die UNLIMITED-Verschachtelungsebene, ohne dass ein CSS / Style-Attribut hinzugefügt / geändert werden muss.
Gebrochener Pfeil
Super Kumpel! Sieht großartig aus! : D
Donny van V
Tolle Antwort. SK joy vai
Rasel
6

Ich mag die Lösung von Broken Arrow oben in diesem Beitrag sehr. Ich habe es gerade ein wenig verbessert / geändert, damit das, was als Etiketten bezeichnet wurde, umgeschaltet werden kann und nicht als Optionen betrachtet wird. Ich habe ein kleines Stück jQuery verwendet, aber dies könnte ohne jQuery geschehen.

Ich habe Zwischenbeschriftungen (keine Blattbeschriftungen) durch Links ersetzt, die beim Klicken eine Funktion aufrufen. Diese Funktion ist dafür verantwortlich, den nächsten Teil des angeklickten Links umzuschalten, damit die Optionen erweitert / reduziert werden. Dies vermeidet die Möglichkeit, ein Zwischenelement in der Hierarchie auszuwählen, was normalerweise erwünscht ist. Es sollte einfach sein, eine Variante zu erstellen, mit der Zwischenelemente ausgewählt werden können.

Dies ist das modifizierte HTML:

<div class="NestedSelect">
    <a onclick="toggleDiv(this)">Fruit</a>
    <div>
        <label>
            <input type="radio" name="MySelectInputName"><span>Apple</span></label>
        <label>
            <input type="radio" name="MySelectInputName"><span>Banana</span></label>
        <label>
            <input type="radio" name="MySelectInputName"><span>Orange</span></label>
    </div>

    <a onclick="toggleDiv(this)">Drink</a>
    <div>
        <label>
            <input type="radio" name="MySelectInputName"><span>Water</span></label>

        <a onclick="toggleDiv(this)">Soft</a>
        <div>
            <label>
                <input type="radio" name="MySelectInputName"><span>Cola</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Soda</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Lemonade</span></label>
        </div>

        <a onclick="toggleDiv(this)">Hard</a>
        <div>
            <label>
                <input type="radio" name="MySelectInputName"><span>Bear</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Whisky</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Vodka</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Gin</span></label>
        </div>
    </div>
</div>

Eine kleine Javascript / jQuery-Funktion:

function toggleDiv(element) {
    $(element).next('div').toggle('medium');
}

Und die CSS:

.NestedSelect {
    display: inline-block;
    height: 100%;
    border: 1px Black solid;
    overflow-y: scroll;
}

.NestedSelect a:hover, .NestedSelect span:hover  {
    background-color: #0092ff;
    color: White;
    cursor: pointer;
}

.NestedSelect input[type="radio"] {
    display: none;
}

.NestedSelect input[type="radio"] + span {
    display: block;
    padding-left: 0px;
    padding-right: 5px;
}

.NestedSelect input[type="radio"]:checked + span {
    background-color: Black;
    color: White;
}

.NestedSelect div {
    display: none;
    margin-left: 15px;
    border-left: 1px black
    solid;
}

.NestedSelect label > span:before, .NestedSelect a:before{
    content: '- ';
}

.NestedSelect a {
    display: block;
}

Beispiel in JSFiddle ausführen

TrilceAC
quelle
5

Ich denke, wenn Sie etwas haben, das strukturiert und komplex ist, könnten Sie etwas anderes als eine einzelne Dropdown-Box in Betracht ziehen.

Matthew Groves
quelle
4
Nicht mein Design, ich implementiere nur Dinge, obwohl ich damit einverstanden bin, dass es ziemlich verrückt ist. Ein Teil der Freude, an einem vorab vereinbarten Entwurf arbeiten zu dürfen.
Ed James
4

Ich weiß, dass dies schon eine Weile her ist, aber ich muss noch ein kleines Extra hinzufügen:

Dies ist in HTML5 oder früheren Spezifikationen nicht möglich und wird in HTML5.1 noch nicht vorgeschlagen. Ich habe eine Anfrage an die public-html-commentsMailingliste gestellt, aber wir werden sehen, ob etwas daraus wird.

Unabhängig davon, ob dies noch nicht möglich ist <select>, können Sie einen ähnlichen Effekt mit dem folgenden HTML-Code und etwas CSS erzielen, um die Schönheit zu verbessern:

<ul>
  <li>
	<input type="radio" name="location" value="0" id="loc_0" />
	<label for="loc_0">United States</label>
	<ul>
	  <li>
		Northeast
        <ul>
	      <li>
			<input type="radio" name="location" value="1" id="loc_1" />
			<label for="loc_1">New Hampshire</label>
		  </li>
          <li>
			<input type="radio" name="location" value="2" id="loc_2" />
			<label for="loc_2">Vermont</label>
		  </li>
          <li>
			 <input type="radio" name="location" value="3" id="loc_3" />
			 <label for="loc_3">Maine</label>
		  </li>
		 </ul>
	   </li>
       <li>
		   Southeast
           <ul>
			 <li>
				<input type="radio" name="location" value="4" id="loc_4" />
				<label for="loc_4">Georgia</label>
			 </li>
             <li>
				<input type="radio" name="location" value="5" id="loc_5" />
				<label for="loc_5">Alabama</label>
			 </li>
		   </ul>
		</li>
	  </ul>
    </li>
    <li>
	   <input type="radio" name="location" value="6" id="loc_6" />
	   <label for="loc_6">Canada</label>
       <ul>
		  <li>
			 <input type="radio" name="location" value="7" id="loc_7" />
			 <label for="loc_7">Ontario</label>
		  </li>
          <li>
			  <input type="radio" name="location" value="8" id="loc_8" />
		      <label for="loc_8">Quebec</label>
		  </li>
          <li>
			   <input type="radio" name="location" value="9" id="loc_9" />
			   <label for="loc_9">Manitoba</label>
		  </li>
		</ul>
	 </li>
  </ul>

Als zusätzlichen Zusatz bedeutet dies auch, dass Sie die Auswahl der zulassen können <optgroups> selbst können. Dies kann nützlich sein, wenn Sie beispielsweise verschachtelte Kategorien hatten, in denen die Kategorien sehr detailliert sind, und Sie möchten, dass Benutzer weiter oben in der Hierarchie auswählen können.

Dies funktioniert alles ohne JavaScript. Möglicherweise möchten Sie jedoch einige hinzufügen, um die Optionsfelder auszublenden, und dann die Hintergrundfarbe des ausgewählten Elements oder etwas ändern.

Denken Sie daran, dass dies alles andere als eine perfekte Lösung ist. Wenn Sie jedoch unbedingt eine verschachtelte Auswahl mit angemessener browserübergreifender Kompatibilität benötigen, ist dies wahrscheinlich so nah wie möglich.

James Billingham
quelle
Können Sie ein paar Beispiele für CSS-Schönheit für diejenigen von uns hinzufügen, die CSS nicht so gut kennen, wie wir es vielleicht sollten?
Pat
Ich würde dies als eine brillante Lösung betrachten.
Nj Subedi
Dies ist nichts weiter als eine verschachtelte Liste. Dies verfehlt völlig den Punkt der Frage, nämlich eine Art zusammenklappbare Liste zu haben.
Cerbrus
@ Cerbrus Vielleicht solltest du die Frage nochmal lesen. Zu keinem Zeitpunkt gibt er an, dass die Abschnitte zusammenklappbar sein müssen. Das spezifische Problem, das er lösen wollte, war eine Methode, verschachtelte <optgroup>s einzurücken. Natürlich kann man HTML mit sehr einfachem CSS und / oder JS wie ein Dropdown-Menü rendern, aber OP suchte keine Hilfe dabei.
James Billingham
Dies ist eine anständige Antwort für die visuelle Darstellung von Dingen, aber ein Listen-Tag ist nicht das Äquivalent von a select. Sie benötigen mehr CSS- und Javascript-Code, damit er sich wie einer verhält.
Suncat2000
3

Ich brauchte eine saubere und leichte Lösung (also kein jQuery und ähnliches), die genau wie normales HTML aussieht, auch dann weiter funktioniert, wenn nur einfaches HTML voreingestellt ist (Javascript verbessert es also nur) und die Suche durch Startbuchstaben ermöglicht ( einschließlich nationaler UTF-8-Buchstaben), wenn dies möglich ist, wenn kein zusätzliches Gewicht hinzugefügt wird. Es muss auch in sehr langsamen Browsern schnell funktionieren (denken Sie an rPi - also vorzugsweise kein Javascript, das nach dem Laden der Seite ausgeführt wird).

In Firefox wird die CSS-Identifikation verwendet und somit die Suche nach Buchstaben ermöglicht. In anderen Browsern wird das &nbsp;Voranstellen verwendet (dort wird jedoch die schnelle Suche nach Buchstaben nicht unterstützt). Wie auch immer, ich bin ziemlich zufrieden mit den Ergebnissen.

Sie können es hier in Aktion ausprobieren

Es geht so:

CSS:

.i0 { }
.i1 { margin-left: 1em; }
.i2 { margin-left: 2em; }
.i3 { margin-left: 3em; }
.i4 { margin-left: 4em; }
.i5 { margin-left: 5em; }

HTML (Klasse "i1", "i2" usw. bezeichnen die Identifikationsebene):

<form action="/filter/" method="get">
<select name="gdje" id="gdje">
<option value=1 class="i0">Svugdje</option>
<option value=177 class="i1">Bosna i Hercegovina</option>
<option value=190 class="i2">Babin Do</option>  
<option value=258 class="i2">Banja Luka</option>
<option value=181 class="i2">Tuzla</option>
<option value=307 class="i1">Crna Gora</option>
<option value=308 class="i2">Podgorica</option>
<option value=2 SELECTED class="i1">Hrvatska</option>
<option value=5 class="i2">Bjelovarsko-bilogorska županija</option>
<option value=147 class="i3">Bjelovar</option>
<option value=79 class="i3">Daruvar</option>  
<option value=94 class="i3">Garešnica</option>
<option value=329 class="i3">Grubišno Polje</option>
<option value=368 class="i3">Čazma</option>
<option value=6 class="i2">Brodsko-posavska županija</option>
<option value=342 class="i3">Gornji Bogićevci</option>
<option value=158 class="i3">Klakar</option>
<option value=140 class="i3">Nova Gradiška</option>
</select>
</form>

<script>
<!--
        window.onload = loadFilter;
// -->   
</script>

JavaScript:

function loadFilter() {
  'use strict';
  // indents all options depending on "i" CSS class
  function add_nbsp() {
    var opt = document.getElementsByTagName("option");
    for (var i = 0; i < opt.length; i++) {
      if (opt[i].className[0] === 'i') {
      opt[i].innerHTML = Array(3*opt[i].className[1]+1).join("&nbsp;") + opt[i].innerHTML;      // this means "&nbsp;" x (3*$indent)
      }
    }
  }
  // detects browser
  navigator.sayswho= (function() {
    var ua= navigator.userAgent, tem,
    M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*([\d\.]+)/i) || [];
    if(/trident/i.test(M[1])){
        tem=  /\brv[ :]+(\d+(\.\d+)?)/g.exec(ua) || [];
        return 'IE '+(tem[1] || '');
    }
    M= M[2]? [M[1], M[2]]:[navigator.appName, navigator.appVersion, '-?'];
    if((tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
    return M.join(' ');
  })();
  // quick detection if browser is firefox
  function isFirefox() {
    var ua= navigator.userAgent,
    M= ua.match(/firefox\//i);  
    return M;
  }
  // indented select options support for non-firefox browsers
  if (!isFirefox()) {
    add_nbsp();
  }
}  
Matija Nalis
quelle
Das Hinzufügen von CSS-Klassen zur Steuerung des Einrückens würde die Frage des OP lösen, ohne die Funktionalität des zu beeinträchtigen select. Gute Idee, da optgroupsnicht verschachtelt werden kann.
Suncat2000
Warum haben Sie Code, margin-left: 1em; wenn er nichts tut und Sie am Ende &nbsp;trotzdem s verwenden, nur um den Rand erscheinen zu lassen? Ihr CSS-Code hier macht überhaupt nichts. Demo der linken Ränder
funktioniert
@HoldOffHunger Beachten Sie, dass die obige Antwort aus dem Jahr 2015 stammt und eine spezielle isFirefox()Behandlung hat - damals brauchte Firefox keine &nbsp;(was die Suchfunktion von Dropdown-Listen beeinträchtigte) und es hat damals (leider) die Margen in Dropdown-Listen berücksichtigt , zumindest wie bei Firefox 78.5, funktioniert es nicht mehr so)
Matija Nalis
2

Ich habe eine schöne, verschachtelte Auswahl geschrieben. Vielleicht hilft es dir.

https://jsfiddle.net/nomorepls/tg13w5r7/1/

function on_change_select(e) {
  alert(e.value, e.title, e.option, e.select);
}

$(document).ready(() => {
  // NESTED SELECT

  $(document).on('click', '.nested-cell', function() {
    $(this).next('div').toggle('medium');
  });

  $(document).on('change', 'input[name="nested-select-hidden-radio"]', function() {
    const parent = $(this).closest(".nested-select");
    const value = $(this).attr('value');
    const title = $(this).attr('title');
    const executer = parent.attr('executer');
    if (executer) {
      const event = new Object();
      event.value = value;
      event.title = title;
      event.option = $(this);
      event.select = parent;
      window[executer].apply(null, [event]);
    }
    parent.attr('value', value);
    parent.parent().slideToggle();
    const button = parent.parent().prev();
    button.toggleClass('active');
    button.addClass('selected');
    button.children('.nested-select-title').html(title);
  });

  $(document).on('click', '.nested-select-button', function() {
    const button = $(this);
    let select = button.parent().children('.nested-select-wrapper');

    if (!button.hasClass('active')) {
      select = select.detach();
      if (button.height() + button.offset().top + $(window).height() * 0.4 > $(window).height()) {
        select.insertBefore(button);
        select.css('margin-top', '-44vh');
        select.css('top', '0');
      } else {
        select.insertAfter(button);
        select.css('margin-top', '');
        select.css('top', '40px');
      }
    }
    select.slideToggle();
    button.toggleClass('active');
  });
});
.container {
  width: 200px;
  position: relative;
  top: 0;
  left: 0;
  right: 0;
  height: auto;
}

.nested-select-box {
  font-family: Arial, Helvetica, sans-serif;
  display: block;
  position: relative;
  width: 100%;
  height: fit-content;
  cursor: pointer;
  color: #2196f3;
  height: 40px;
  font-size: small;
  /* z-index: 2000; */
}

.nested-select-box .nested-select-button {
  border: 1px solid #2196f3;
  position: absolute;
  width: calc(100% - 20px);
  padding: 0 10px;
  min-height: 40px;
  word-wrap: break-word;
  margin: 0 auto;
  overflow: hidden;
}

.nested-select-box.danger .nested-select-button {
  border: 1px solid rgba(250, 33, 33, 0.678);
}

.nested-select-box .nested-select-button .nested-select-title {
  padding-right: 25px;
  padding-left: 25px;
  width: calc(100% - 50px);
  margin: auto;
  height: fit-content;
  text-align: center;
  vertical-align: middle;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
}

.nested-select-box .nested-select-button.selected .nested-select-title {
  bottom: unset;
  top: 5px;
}

.nested-select-box .nested-select-button .nested-select-title-icon {
  position: absolute;
  height: 20px;
  width: 20px;
  top: 10px;
  bottom: 10px;
  right: 7px;
  transition: all 0.5s ease 0s;
}

.nested-select-box .nested-select-button.active .nested-select-title-icon {
  -moz-transform: scale(-1, -1);
  -o-transform: scale(-1, -1);
  -webkit-transform: scale(-1, -1);
  transform: scale(-1, -1);
}

.nested-select-box .nested-select-button .nested-select-title-icon::before,
.nested-select-box .nested-select-button .nested-select-title-icon::after {
  content: "";
  background-color: #2196f3;
  position: absolute;
  width: 70%;
  height: 2px;
  transition: all 0.5s ease 0s;
  top: 9px;
}

.nested-select-box .nested-select-button .nested-select-title-icon::before {
  transform: rotate(45deg);
  left: -1.6px;
}

.nested-select-box .nested-select-button .nested-select-title-icon::after {
  transform: rotate(-45deg);
  left: 7px;
}

.nested-select-box .nested-select-wrapper {
  width: 100%;
  top: 40px;
  position: relative;
  border: 1px solid #2196f3;
  background: #ffffff;
  z-index: 2005;
  opacity: 1;
}

.nested-select {
  font-family: Arial, Helvetica, sans-serif;
  display: inline-block;
  overflow-y: scroll;
  max-height: 40vh;
  width: calc(100% - 10px);
  padding: 5px;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.nested-select::-webkit-scrollbar {
  display: none;
}

.nested-select a,
.nested-select span {
  padding: 0 5px;
  border-radius: 3px;
  cursor: pointer;
  text-align: start;
}

.nested-select a:hover {
  background-color: #62b2f3;
  color: #ffffff;
}

.nested-select span:hover {
  background-color: #c4c4c4;
  color: #ffffff;
}

.nested-select input[type="radio"] {
  display: none;
}

.nested-select input[type="radio"]+span {
  display: block;
}

.nested-select input[type="radio"]:checked+span {
  background-color: #2196f3;
  color: #ffffff;
}

.nested-select div {
  margin-left: 15px;
}

.nested-select label>span:before,
.nested-select a:before {
  content: "\2022";
  margin-right: 5px;
}

.nested-select a {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="nested-select-box w-100">
    <div class="nested-select-button">
      <p class="nested-select-title">
        Account
      </p>
      <span class="nested-select-title-icon"></span>
    </div>
    <div class="nested-select-wrapper" style="display: none;">
      <div class="nested-select" executer="on_change_select">

        <label>
        <input title="Accounting and legal services" value="1565142000000891539" type="radio" name="nested-select-hidden-radio">
        <span>Accounting and legal services</span>
      </label>



        <label>
        <input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
        <span>Advertising agencies</span>
      </label>



        <a class="nested-cell">Advertising And Marketing</a>
        <div>



          <label>
          <input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
          <span>Advertising agencies</span>
        </label>



          <a class="nested-cell">Adwords - traffic</a>
          <div>



            <label>
            <input title="Adwords - traffic: Charters and general search" value="1565142000003929177" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Charters and general search</span>
          </label>



            <label>
            <input title="Adwords - traffic: Distance course" value="1565142000007821291" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Distance course</span>
          </label>



            <label>
            <input title="Adwords - traffic: Events" value="1565142000003929189" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Events</span>
          </label>



            <label>
            <input title="Adwords - traffic: Practices" value="1565142000003929165" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Practices</span>
          </label>



            <label>
            <input title="Adwords - traffic: Sailing tours" value="1565142000003929183" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Sailing tours</span>
          </label>



            <label>
            <input title="Adwords - traffic: Theoretical courses" value="1565142000003929171" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Theoretical courses</span>
          </label>



          </div>



          <label>
          <input title="Branded products" value="1565142000000891533" type="radio" name="nested-select-hidden-radio">
          <span>Branded products</span>
        </label>



          <label>
          <input title="Business cards" value="1565142000005438323" type="radio" name="nested-select-hidden-radio">
          <span>Business cards</span>
        </label>



          <a class="nested-cell">Facebook, Instagram - traffic</a>
          <div>



            <label>
            <input title="Facebook, Instagram - traffic: Charters and general search" value="1565142000003929145" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Charters and general search</span>
          </label>



            <label>
            <input title="Facebook, Instagram - traffic: Distance course" value="1565142000007821285" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Distance course</span>
          </label>



            <label>
            <input title="Facebook, Instagram - traffic: Events" value="1565142000003929157" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Events</span>
          </label>



            <label>
            <input title="Facebook, Instagram - traffic: Practices" value="1565142000003929133" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Practices</span>
          </label>



            <label>
            <input title="Facebook, Instagram - traffic: Sailing tours" value="1565142000003929151" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Sailing tours</span>
          </label>



            <label>
            <input title="Facebook, Instagram - traffic: Theoretical courses" value="1565142000003929139" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Theoretical courses</span>
          </label>



          </div>



          <label>
          <input title="Offline Advertising (posters, banners, partnerships)" value="1565142000000891377" type="radio" name="nested-select-hidden-radio">
          <span>Offline Advertising (posters, banners, partnerships)</span>
        </label>



          <label>
          <input title="Photos, video etc." value="1565142000000891371" type="radio" name="nested-select-hidden-radio">
          <span>Photos, video etc.</span>
        </label>



          <label>
          <input title="Prize fund" value="1565142000001404931" type="radio" name="nested-select-hidden-radio">
          <span>Prize fund</span>
        </label>



          <label>
          <input title="SEO" value="1565142000000891365" type="radio" name="nested-select-hidden-radio">
          <span>SEO</span>
        </label>



          <label>
          <input title="SMM Content creation (texts, copywriting)" value="1565142000000891389" type="radio" name="nested-select-hidden-radio">
          <span>SMM Content creation (texts, copywriting)</span>
        </label>



          <a class="nested-cell">YouTube</a>
          <div>



            <label>
            <input title="YouTube: travel expenses" value="1565142000008100163" type="radio" name="nested-select-hidden-radio">
            <span>YouTube: travel expenses</span>
          </label>



            <label>
            <input title="Youtube: video editing" value="1565142000008100157" type="radio" name="nested-select-hidden-radio">
            <span>Youtube: video editing</span>
          </label>



          </div>



        </div>

      </div>
    </div>
  </div>
</div>

Коля Крикунов
quelle