HTML / CSS:在 <select> 字段中嵌套 <options>?

新手上路,请多包涵

是否可以在表单下拉列表中创建嵌套的选项字段,就像创建嵌套的 ul 列表一样?

由于更改只是美学上的,是否可以用 css 做到这一点?

原文由 stef 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 662
2 个回答

您可以使用 <optgroup> 创建单层嵌套…

 <select>
  <optgroup label="Options 1">
    <option>Option 1.1</option>
    <option>Option 1.2</option>
  </optgroup>
  <optgroup label="Options 2">
    <option>Option 2.1</option>
    <option>Option 2.2</option>
  </optgroup>
</select>

请注意,组标签不是可选择的选项。在那种情况下,我建议使用在他的评论中链接到的问题的最佳答案中提到的文本缩进解决方案。

原文由 Chris Marasti-Georg 发布,翻译遵循 CC BY-SA 4.0 许可协议

嵌套手风琴选择

我采用这种方法是因为找不到我正在搜索的内容。嵌套的手风琴选择。它的 CSS 非常简单,可以改进。您唯一需要的是一个包含要添加到选择中的键和值的对象。 Keys 将是子组,而键 values (数组和单个元素)将是可选项目。

一旦你有了你的数组,你唯一需要做的就是打电话

initAccordeon(obj);

以您的数据对象作为参数,嵌套的手风琴将出现:

 const obj = {
  Cars: {
    SwedishCars: [
      "Volvo",
      "Saab"
    ],
    GermanCars: [
      "Mercedes",
      {
        Audi: [
          "Audi A3",
          "Audi A4",
          "Audi A5"
        ]
      }
    ]
  },
  Food: {
    Fruits: [
      "Orange",
      "Apple",
      "Banana"
    ],
    SaltyFoods: [
      "Pretzels",
      "Burger",
      "Noodles"
    ],
    Drinks: "Water"
  }
};

initAccordeon(obj);   // <--------------------------- Call initialization

function accordeonAddEvents() {
  Array.from(document.getElementsByClassName("accordeon-header")).forEach(function(header) {
    if (header.getAttribute("listener") !== "true") {
      header.addEventListener("click", function() {
        this.parentNode.getElementsByClassName("accordeon-body")[0].classList.toggle("hide");
      });
      header.setAttribute("listener", "true");
    }
  });

  Array.from(document.getElementsByClassName("button-group")).forEach(function(but) {
    if (but.getAttribute("listener") !== "true") {
      but.addEventListener("click", function() {
        if (this.getAttribute("depth") === "-1") {
          let header = this;
          while ((header = header.parentElement) && header.className !== "accordeon");
          header.getElementsByClassName("accordeon-header")[0].innerHTML = this.innerHTML;
          return;
        }
        const groups = Array.from(this.parentNode.getElementsByClassName("accordeon-group"));
        groups.forEach(g => {
          if (g.getAttribute("uuid") === this.getAttribute("uuid") &&
            g.getAttribute("depth") === this.getAttribute("depth")) {
            g.classList.toggle("hide");
          }
        });
      });
      but.setAttribute("listener", "true");
    }
  });
}

function initAccordeon(data) {
  accordeons = Array.from(document.getElementsByClassName("accordeon-body"));
  accordeons.forEach(acc => {
    acc.innerHTML = "";
    const route = (subObj, keyIndex = 0, parent = acc, depth = 0) => {
      const keys = Object.keys(subObj);
      if (typeof subObj === 'object' && !Array.isArray(subObj) && keys.length > 0) {
        while (keyIndex < keys.length) {
          var but = document.createElement("button");
          but.className = "button-group";
          but.setAttribute("uuid", keyIndex);
          but.setAttribute("depth", depth);
          but.innerHTML = keys[keyIndex];
          var group = document.createElement("div");
          group.className = "accordeon-group hide";
          group.setAttribute("uuid", keyIndex);
          group.setAttribute("depth", depth);
          route(subObj[keys[keyIndex]], 0, group, depth + 1);
          keyIndex++;
          parent.append(but);
          parent.append(group);
        }
      } else {
        if (!Array.isArray(subObj)) subObj = [subObj];
        subObj.forEach((e, i) => {
          if (typeof e === 'object') {
              route(e, 0, parent, depth);
          } else {
              var but = document.createElement("button");
              but.className = "button-group";
              but.setAttribute("uuid", i);
              but.setAttribute("depth", "-1");
              but.innerHTML = e;
              parent.append(but);
          }
        });
      }
    };
    route(data);
  });
  accordeonAddEvents();
}
 .accordeon {
  width: 460px;
  height: auto;
  min-height: 340px;
  font-size: 20px;
  cursor: pointer;
  user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;
  display: block;
  position: relative;
  z-index: 10;
}

.accordeon-header {
  display: inline-block;
  width: 450px;
  border: solid 0.1vw black;
  border-radius: 0.2vw;
  background-color: white;
  padding-left: 10px;
  color: black;
}

.accordeon-header:hover {
  opacity: 0.7;
}

.accordeon-body {
  display: block;
  position: absolute;
}

.button-group {
  display: block;
  cursor: pointer;
  width: 460px;
  text-align: left;
  font-size: 20px;
  font-weight: bold;
}

.accordeon-group {
  padding-left: 20px;
}

.accordeon-group .button-group {
  width: 100%;
}

.button-group[depth="-1"] {
  color: green;
}

.hide {
  display: none;
}
 <div class="accordeon">
  <span class="accordeon-header">Select something</span>
  <div class="accordeon-body hide">

  </div>
</div>

原文由 AlexSp3 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏