【问题标题】:Container width based on child flex items [duplicate]基于子弹性项目的容器宽度[重复]
【发布时间】:2019-04-16 18:10:52
【问题描述】:

我正在尝试制作一个垂直对齐未确定数量的列表项的侧边栏。当项目的数量到达侧边栏的底部时,它们通过 flex 分组到列中。

我的问题是我希望侧边栏的宽度在关闭时为 100 像素,在打开时我希望它是列的宽度。如果我对打开状态使用固定宽度,则会发生这种情况:

HTML:

<nav class="sidebar">
    <ul>
        <li>
            1
        </li>
        <li>
            2
        </li>
        <li>
            3
        </li>
        <li>
            4
        </li>
        <li>
            5
        </li>       
        <li>
            ...
        </li>       
    </ul>
</nav>

SCSS:

.sidebar {
    background: #ccc;
    width: 100px;

    ul {
        list-style-type: none;
        height: 100vh;

        display: flex;
        flex-wrap: wrap;
        flex-direction: column;
        align-content: flex-start;

        li {
            background: #000;
            height: 80px;
            width: 80px;
        }
    }

    &:hover
    {
        //width: !?!?!?!
    }
}

我怎样才能做到这一点?如何打开侧边栏并显示所有列?

更新:侧边栏的高度可能因屏幕尺寸而异。我用原始设置更新了代码。

更新 #2: 我测试了这两种解决方案,虽然 @itay-gal 是一个聪明的 CSS 唯一选项,但它缺乏动画的能力。由于我已经在使用 JS,所以我最终使用了@pablo-darde 解决方案。

我对@pablo-darde 做了一个小改动,以便它可以使用可变高度的侧边栏:

const sidebar = document.querySelector('.sidebar');
const ul = sidebar.querySelector('ul');
const li = ul.querySelector('li');

const showRemainder = () => {
    const ulHeight = ul.clientHeight;
    const liHeight = li.clientHeight;
    const width = ul.clientWidth * Math.ceil(ul.children.length / (ulHeight / liHeight));
    sidebar.style.maxWidth = `${width}px`;
}

【问题讨论】:

  • 不知道为什么@Michael_B 将其标记为重复,这似乎不是同一个问题,我找到了仅使用 css 的解决方案
  • 我把它标记为重复,因为这个问题之前已经被问过和探索过很多次了。另外,您的回答并不能解释问题。它也没有解释答案(这实际上只是一种解决方法)。但是,如果您认为您的答案是对整个问题的有用解决方案,请将其发布在主要(重复)帖子上。 @ItayGal
  • 我认为我们在这里所做的是找到解决方法以使事情正常进行,即使它不是微不足道和容易的 :) 我认为我不必解释这个问题,只是为了解释我是如何克服它的,我会尽快详细说明我的解决方案。

标签: html css layout sass flexbox


【解决方案1】:

仅与 CSS 接近。您将无法为打开/关闭设置动画。

我的建议是使用一些 javascript 来计算元素并设置所需的宽度,但如果你真的做不到,这可能会有所帮助:

首先我设置侧边栏的高度,然后设置ullis 包裹在里面。这会将lis 设置在正确的位置。

添加overflow: hidden 将隐藏除第一列之外的所有内容。

在悬停时,我将溢出设置为可见 - 这样您就可以看到 lis 的其余部分。

因为我们无法为溢出的部分添加背景,所以我通过在每个li 中添加div 来模拟它。

这几乎可以解决问题。但是,当最后一列未满时,您会在最后一列中看到一个没有背景的空白。

因此,为了克服它,我在最后一个元素中添加了一个 after 选择器,其高度与整个 ul 相同,并添加了一个 containeroverflow: hidden 以隐藏不必要的部分。

可能缺少什么?

我们不能为它制作动画,因为overflow 不支持动画。

.sidebar {
  list-style-type: none;
  overflow: hidden;
  width: 100px;
  transition: all 1s;
  height: 400px;
  display: flex;
}

.sidebar ul {
  list-style-type: none;
  margin: 0px;
  padding: 0px;
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  align-content: flex-start;
}

.sidebar li {
  background-color: #ccc;
  padding: 10px;
}

.sidebar li div {
  background-color: red;
  height: 80px;
  width: 80px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 32px;
  font-weight: bold;
  position: relative;
}

.sidebar:hover {
  overflow: visible;
}

.sidebar li:last-child div:after{
  height: 400px;
  background-color: #ccc;
  content:"     htr   ";
  position: absolute;
  display: none;
  z-index: -1;
  top: 0px;
  width: 100px;
}

.sidebar:hover li:last-child div:after{
  display: inline-block;
}
.container{
 height: 400px;
 overflow-y: hidden;
}
<div class="container">
<nav class="sidebar">
  <ul>
    <li>
      <div>1</div>
    </li>
    <li>
      <div>2</div>
    </li>
    <li>
      <div>3</div>
    </li>
    <li>
      <div>4</div>
    </li>
    <li>
      <div>5</div>
    </li>
    <li>
      <div>6</div>
    </li>
    <li>
      <div>7</div>
    </li>
    <li>
      <div>8</div>
    </li>
    <li>
      <div>9</div>
    </li>
    <li>
      <div>10</div>
    </li>
    <li>
      <div>11</div>
    </li>
    <li>
      <div>12</div>
    </li>
    <li>
      <div>13</div>
    </li>
     <li>
      <div>14</div>
    </li>
  </ul>
</nav>
</div>

【讨论】:

  • 我今天要试试你的解决方案。我会回复反馈。
  • 你的解决方案有效,但我真的需要一些动画。出于这个原因,我没有将你的标记为答案。聪明的一个想法;)
【解决方案2】:

我真的尝试只使用 CSS 和您的代码进行编码,但没有成功。我使用一些 JavaScript 代码达到了预期的结果。请让我知道您是否可以变得更优雅。

注意 li 元素中的 css pointer-events: none; 属性。这里非常重要。如果您想在lis 中使用href,我相信需要进行一些重构。

const sidebar = document.querySelector('.sidebar');
const ul = sidebar.querySelector('ul');

const showRemainder = () => {
  const width = ul.clientWidth * Math.ceil(ul.children.length / 5);
  sidebar.style.maxWidth = `${width}px`;
}

const hideRemainder = () => {
	sidebar.style.maxWidth = '80px';
}

sidebar.addEventListener('mouseover', showRemainder);

sidebar.addEventListener('mouseout', hideRemainder);
.sidebar {
  background: #ccc;
  max-width: 80px;
  width: auto;
  height: 400px;
  overflow: hidden;
  transition: all 0.5s ease;
}

.sidebar ul {
  list-style-type: none;
  height: 400px;
  display: flex;
  padding: 0;
  margin: 0;
  flex-flow: column wrap;
  align-content: flex-start;
}

.sidebar ul li {
  display: flex;
  pointer-events: none;
  justify-content: center;
  align-items: center;
  background: #000;
  height: 80px;
  width: 80px;
  color: #fff;
  box-sizing: border-box;
  border: 1px solid #fff;
}
<nav class="sidebar">
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
        <li>11</li>
        <li>12</li>
        <li>13</li>
    </ul>
</nav>

【讨论】:

  • 此解决方案是否适用于可变高度?我的侧边栏可以有不同的高度,具体取决于屏幕尺寸。我已经更新了我的问题。
  • 您的解决方案不适用于可变高度侧边栏,因此我稍微修改了您的代码。我已经用我对您的代码所做的更改更新了我的问题。
  • 此解决方案不适用于可变高度。您需要更改一些代码。我想你可以得到lis 的高度并加入计算。
  • 我已经用我对您的解决方案所做的更改更新了我的问题。我还将您的回答标记为我的问题的解决方案。
【解决方案3】:

这可以通过一点点 Javascript 轻松完成。您将获得列表项的数量,然后进行一些计算以确定所需的列数,并将该宽度样式应用于侧边栏。

【讨论】:

    【解决方案4】:

    这个 sn-p 不是很漂亮,但它可能会给你一些东西。我在侧边栏上放置了一个隐藏的溢出。将其设置为第一列的宽度。然后在侧边栏悬停时,将宽度更改为两列的大小。

    .sidebar {
      background: #ccc;
      width: 100px;
      overflow:hidden;
      -webkit-transition: width 1s;
      transition: width 1s;    
    }
    
    ul {
      margin-left: -20px;
      list-style-type: none;
      height: 500px;
      display: flex;
      flex-wrap: wrap;
      flex-direction: column;
      align-content: flex-start;
      justify-content: center;
    }
    
    li {
      background-color: #000;
      height: 80px;
      width: 80px;
      color: white;
      text-align: center;
    }
    
    .sidebar:hover {
      width: 200px;
    }
    <nav class="sidebar">
      <ul>
        <li>
          1
        </li>
        <li>
          2
        </li>
        <li>
          3
        </li>
        <li>
          4
        </li>
        <li>
          5
        </li>
        <li>
          6
        </li>
        <li>
          7
        </li>
        <li>
          8
        </li>
        <li>
         9
        </li>
        <li>
         10
        </li>
        <li>
          11
        </li>
        <li>
          12
        </li>    
        
      </ul>
    </nav>

    【讨论】:

      猜你喜欢
      • 2021-09-06
      • 2016-07-20
      • 2017-03-14
      • 2017-03-01
      • 2020-07-04
      • 2021-08-28
      • 1970-01-01
      相关资源
      最近更新 更多