巨型菜单的CSS动态布局,根据菜单项的数量以行或列读取

问题描述 投票:0回答:1

我正在为一个大型菜单做一些原型设计,其中菜单项应该“智能”显示,根据菜单项的数量,它们将读取为行或列。

菜单项有自己的子项,所以它们真的很像:

 mega menu left text | menu item 1   menu item 2   menu item 3
                     | sublink1 A    sublink2 A    sublink3 A
                     | sublink1 B    sublink2 B
                     | sublink1 C

为了简单起见,我不包括以下内容。

显示内容取决于菜单项的数量。例如,如果有 1-3 个菜单项,它会读起来像一行:

mega menu left text | menu item 1   menu item 2   menu item 3

如果有超过 3 个菜单项,它会读成列,从上到下,然后到右侧,但它仍然需要“智能”,因为菜单项 4 在其自己的列中,而不是在菜单下方第3项(总是需要在右侧保持3列):

mega menu left text | menu item 1   menu item 3   menu item 4
                    | menu item 2

5 个菜单项:

mega menu left text | menu item 1   menu item 3   menu item 5
                    | menu item 2   menu item 4

6 个菜单项:

mega menu left text | menu item 1   menu item 3   menu item 5
                    | menu item 2   menu item 4   menu item 6

7 个菜单项:

mega menu left text | menu item 1   menu item 4   menu item 7
                    | menu item 2   menu item 5
                    | menu item 3   menu item 6

8 个菜单项:

mega menu left text | menu item 1   menu item 4   menu item 7
                    | menu item 2   menu item 5   menu item 8
                    | menu item 3   menu item 6

9 个菜单项:

mega menu left text | menu item 1   menu item 4   menu item 7
                    | menu item 2   menu item 5   menu item 8
                    | menu item 3   menu item 6   menu item 9

10 个菜单项:

mega menu left text | menu item 1   menu item 5   menu item 9
                    | menu item 2   menu item 6   menu item 10
                    | menu item 3   menu item 7   
                    | menu item 4   menu item 8

有没有办法在CSS中优雅地做到这一点?我认为 css 列可以做到这一点,但它不太有效。这是一个小提琴/演示,如果您移动左侧的滑块,您会看到它落下的位置:

https://jsfiddle.net/vsdpjwn9/
这在

break-inside: avoid-column;
 上使用 
<li>

https://jsfiddle.net/3x8scuwt/
这在

display: inline-block;
 上使用 
<li>

我还尝试了一个带有 Flexbox 的单独原型,但它似乎掉落得更快,所以我放弃了它。看起来 css 网格也是一样的。问题是,这些菜单项将是动态的,它们的数量不同,每个菜单项都有不同数量的子链接。可能不会超过 3 行,但我不想依赖于此。

任何 css 解决方案或者这需要 javascript 根据单个菜单项的数量设置自定义布局吗?

它也需要具有响应能力,但菜单项基本上变成了相互堆叠的手风琴。

这是小提琴的代码之一:

HTML:

<div id="container">
  <div class="left">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    <div style="margin-top:1rem;">
      <input id="slider" type="range" min="1" max="8" value="8">
      <p id="slider-output" style="margin-top:0;"></p>
    </div>

  </div>

  <div class="right">
    <ul>
      <li class="1">
          <h4>1 Secondary Content</h4>
          <a href="#a1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#a2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#a3">Lorem ipsum dolora</a><br>
          <a href="#a4">Lorem ipsum dolora</a><br>
          <a href="#a5">Lorem ipsum dolora</a>
      </li>

      <li class="2">
          <h4>2 Secondary Content</h4>
          <a href="#b1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#b2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#b3">Lorem ipsum dolora</a><br>
          <a href="#b4">Lorem ipsum dolora</a><br>
          <a href="#b5">Lorem ipsum dolora</a><br>
          <a href="#b6">Lorem ipsum dolora</a>
      </li>

      <li class="3">
          <h4>3 Secondary Content</h4>
          <a href="#c1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#c2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#c3">Lorem ipsum dolora</a><br>
          <a href="#c4">Lorem ipsum dolora</a>
      </li>

      <li class="4">
          <h4>4 Secondary Content</h4>
          <a href="#d1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#d4">Lorem ipsum dolora</a>
      </li>

      <li class="5">
          <h4>5 Secondary Content</h4>
          <a href="#e1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#e2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#e3">Lorem ipsum dolora</a><br>
          <a href="#e4">Lorem ipsum dolora</a><br>
          <a href="#e5">Lorem ipsum dolora</a>
      </li>

      <li class="6">
          <h4>6 Secondary Content</h4>
          <a href="#f1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#f2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#f3">Lorem ipsum dolora</a><br>
          <a href="#f4">Lorem ipsum dolora</a><br>
          <a href="#f5">Lorem ipsum dolora</a><br>
          <a href="#f6">Lorem ipsum dolora</a>
      </li>

      <li class="7">
          <h4>7 Secondary Content</h4>
          <a href="#g1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#g2">Lorem ipsum dolora</a>
      </li>
      
      <li class="8">
          <h4>8 Secondary Content</h4>
          <a href="#h1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#h2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
          <a href="#h3">Lorem ipsum dolora</a><br>
          <a href="#h4">Lorem ipsum dolora</a><br>
      </li>
    </ul>
  </div>
</div>

CSS:

    #container {
    width: 900px;
    min-height: 400px;
    display: flex;
    gap: 40px;
    padding: 1em;
    border: 1px solid #ccc;
}
.left {
    width: 25%;
    padding-right: 40px;
    border-right: 1px solid #ccc;
}
.right {
    width: 100%;
    margin-left: auto;
}
/*
ul {
  border: 1px solid red;
  height: 400px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
}
*/

ul {
  list-style: none;
  columns: 3;
  column-gap: 25px;
  margin: 0;
  padding: 0;
  width: 98%;
  border: 1px solid blue;
}

li {
  border: 1px solid red;
  list-style-type: none;
  margin: 0 0 15px 0;
  
  /*display: inline-block;*/
  break-inside: avoid-column;
  
}
li:first-child {
  margin-top: 0;
}

li a {
  display: inline-block;
  margin: .125rem 0;
}

h4 {
  margin: 0;
}

[hidden] {
  display: none !important;
}

JS:

    const slider = document.getElementById('slider');
const output = document.getElementById('slider-output');
const LIs = document.querySelectorAll('li');

output.innerHTML = slider.value;

slider.oninput = function() {
  output.innerHTML = this.value;

  LIs.forEach(li => {
    if (+li.classList.value > slider.value) {
      li.setAttribute('hidden', '');
    } else {
      li.removeAttribute('hidden');
    }
  });
}
css flexbox css-grid multiple-columns megamenu
1个回答
0
投票

据我所知,如果没有使用

nth-child
选择器的一些 hacky 方法,纯 CSS 是不可能的,这些方法都需要有限数量的项目。

但是,这可以通过 CSS 网格和一些 JavaScript 更改行数来轻松完成,如下所示:

ul {
    display: grid;
    --row-number: 3;
    grid-template-rows: repeat(var(--row-number), 1fr);
    grid-auto-flow: column;
}

const slider = document.getElementById('slider');
const output = document.getElementById('slider-output');
const LIs = document.querySelectorAll('li');
const ul = document.getElementById('right-grid');
let li = null;
output.innerHTML = slider.value;

slider.oninput = function() {
  output.innerHTML = this.value;

  LIs.forEach(li => {
    if (+li.classList.value > slider.value) {
      li.setAttribute('hidden', '');
    } else {
      li.removeAttribute('hidden');
    }
  });
  updateColumnNumber();
}

function updateColumnNumber() {
  if (slider.value == 4) {
    li = ul.querySelectorAll("li:not([hidden])")[3];
    li?.style.setProperty('grid-column', 3)
  } else if (li) {
    li?.style.removeProperty('grid-column');
    li = null;
  }
  ul.style.setProperty('--row-number', Math.ceil(slider.value / 3));
}

updateColumnNumber();
#container {
  width: 900px;
  min-height: 400px;
  display: flex;
  gap: 40px;
  padding: 1em;
  border: 1px solid #ccc;
}

.left {
  width: 25%;
  padding-right: 40px;
  border-right: 1px solid #ccc;
}

.right {
  width: 100%;
  margin-left: auto;
}

ul {
  list-style: none;
  display: grid;
  --row-number: 3;
  grid-template-rows: repeat(var(--row-number), 1fr);
  grid-auto-flow: column;
  gap: 25px;
  margin: 0;
  padding: 0;
  width: 98%;
  border: 1px solid blue;
}

li {
  box-sizing: border-box;
  border: 1px solid red;
  list-style-type: none;
  margin: 0 0 15px 0;
  /*display: inline-block;*/
  break-inside: avoid-column;
}

li:first-child {
  margin-top: 0;
}

li a {
  display: inline-block;
  margin: .125rem 0;
}

h4 {
  margin: 0;
}

[hidden] {
  display: none !important;
}
<div id="container">
  <div class="left">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    <div style="margin-top:1rem;">
      <input id="slider" type="range" min="1" max="10" value="10">
      <p id="slider-output" style="margin-top:0;"></p>
    </div>

  </div>

  <div class="right">
    <ul id="right-grid">
      <li class="1">
        <h4>1 Secondary Content</h4>
        <a href="#a1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#a2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#a3">Lorem ipsum dolora</a><br>
        <a href="#a4">Lorem ipsum dolora</a><br>
        <a href="#a5">Lorem ipsum dolora</a>
      </li>

      <li class="2">
        <h4>2 Secondary Content</h4>
        <a href="#b1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#b2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#b3">Lorem ipsum dolora</a><br>
        <a href="#b4">Lorem ipsum dolora</a><br>
        <a href="#b5">Lorem ipsum dolora</a><br>
        <a href="#b6">Lorem ipsum dolora</a>
      </li>

      <li class="3">
        <h4>3 Secondary Content</h4>
        <a href="#c1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#c2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#c3">Lorem ipsum dolora</a><br>
        <a href="#c4">Lorem ipsum dolora</a>
      </li>

      <li class="4">
        <h4>4 Secondary Content</h4>
        <a href="#d1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#d4">Lorem ipsum dolora</a>
      </li>

      <li class="5">
        <h4>5 Secondary Content</h4>
        <a href="#e1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#e2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#e3">Lorem ipsum dolora</a><br>
        <a href="#e4">Lorem ipsum dolora</a><br>
        <a href="#e5">Lorem ipsum dolora</a>
      </li>

      <li class="6">
        <h4>6 Secondary Content</h4>
        <a href="#f1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#f2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#f3">Lorem ipsum dolora</a><br>
        <a href="#f4">Lorem ipsum dolora</a><br>
        <a href="#f5">Lorem ipsum dolora</a><br>
        <a href="#f6">Lorem ipsum dolora</a>
      </li>

      <li class="7">
        <h4>7 Secondary Content</h4>
        <a href="#g1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#g2">Lorem ipsum dolora</a>
      </li>

      <li class="8">
        <h4>8 Secondary Content</h4>
        <a href="#h1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h3">Lorem ipsum dolora</a><br>
        <a href="#h4">Lorem ipsum dolora</a><br>
      </li>

      <li class="9">
        <h4>9 Secondary Content</h4>
        <a href="#h1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h3">Lorem ipsum dolora</a><br>
        <a href="#h4">Lorem ipsum dolora</a><br>
      </li>

      <li class="10">
        <h4>10 Secondary Content</h4>
        <a href="#h1">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h2">Lorem ipsum dalora itmet vistafa alotma pastruma</a><br>
        <a href="#h3">Lorem ipsum dolora</a><br>
        <a href="#h4">Lorem ipsum dolora</a><br>
      </li>
    </ul>
  </div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.