基于子弹性项目的容器宽度[重复]

Posted

技术标签:

【中文标题】基于子弹性项目的容器宽度[重复]【英文标题】: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 = `$widthpx`;

【问题讨论】:

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


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>

【讨论】:

以上是关于基于子弹性项目的容器宽度[重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥弹性项目宽度随着 flex-grow 增长:0 [重复]

在两个不同宽度的弹性项目之间水平居中弹性项目[重复]

具有块内容的 Flexbox 项目溢出 flexbox 容器

如何安排弹性项目以占据容器的整个宽度?

flex弹性盒模型

将弹性项目保留在父容器内