基于子弹性项目的容器宽度[重复]
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 来计算元素并设置所需的宽度,但如果你真的做不到,这可能会有所帮助:
首先我设置侧边栏的高度,然后设置ul
将li
s 包裹在里面。这会将li
s 设置在正确的位置。
添加overflow: hidden
将隐藏除第一列之外的所有内容。
在悬停时,我将溢出设置为可见 - 这样您就可以看到 li
s 的其余部分。
因为我们无法为溢出的部分添加背景,所以我通过在每个li
中添加div
来模拟它。
这几乎可以解决问题。但是,当最后一列未满时,您会在最后一列中看到一个没有背景的空白。
因此,为了克服它,我在最后一个元素中添加了一个 after
选择器,其高度与整个 ul
相同,并添加了一个 container
和 overflow: 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;
属性。这里非常重要。如果您想在li
s 中使用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>
【讨论】:
此解决方案是否适用于可变高度?我的侧边栏可以有不同的高度,具体取决于屏幕尺寸。我已经更新了我的问题。 您的解决方案不适用于可变高度侧边栏,因此我稍微修改了您的代码。我已经用我对您的代码所做的更改更新了我的问题。 此解决方案不适用于可变高度。您需要更改一些代码。我想你可以得到li
s 的高度并加入计算。
我已经用我对您的解决方案所做的更改更新了我的问题。我还将您的回答标记为我的问题的解决方案。【参考方案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 [重复]