Я пытаюсь создать боковую панель, которая выравнивает по вертикали неопределенное количество элементов списка. Когда количество элементов достигает нижней части боковой панели, они группируются в столбцы с помощью гибкости.
Моя проблема в том, что я хочу, чтобы ширина боковой панели была 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`;
}
Я пометил его как дубликат, потому что этот вопрос задавался и исследовался много раз раньше. Кроме того, ваш ответ не объясняет проблемы. Он также не объясняет ответ (что на самом деле является обходным путем). Но если вы считаете, что ваш ответ - полезное решение общей проблемы, опубликуйте его в основном (дублирующем) посте. @ItayGal
Я подумал, что мы здесь ищем обходные пути, чтобы заставить все работать, даже если это не тривиально и легко :) И я не думаю, что мне нужно объяснять проблему, просто чтобы объяснить, как я ее преодолеваю, и я подробно остановлюсь на своем решение скоро.






Я действительно пытался писать код только с помощью CSS и вашего кода, но безуспешно. Я достиг желаемого результата с помощью некоторого кода JavaScript. Пожалуйста, дайте мне знать, сможете ли вы получить более элегантный вариант.
Обратите внимание на свойство css pointer-events: none; в ваших элементах li. Здесь это очень важно. Если вы хотите использовать href в li, я считаю, что потребуется некоторый рефакторинг.
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 и добавить ее в расчет.
Я обновил свой вопрос изменениями, внесенными в ваше решение. Я также отметил ваш ответ как решение моей проблемы.
Этот фрагмент некрасивый, но может дать вам кое-что, с чем можно поработать. Я скрыл переполнение на боковой панели. Установите ширину вашего первого столбца. Затем при наведении курсора на боковую панель измените ширину на размер обоих столбцов.
.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>Это легко сделать с помощью Javascript. Вы получите количество элементов списка, затем выполните небольшой расчет, чтобы определить количество необходимых столбцов, и примените этот стиль ширины к боковой панели.
Подобрался только с помощью CSS. Вы не сможете анимировать открытие / закрытие.
Мое предложение использует небольшой JavaScript для подсчета элементов и установки необходимой ширины, но если вы действительно не можете, это может помочь:
Сначала я установил высоту боковой панели, а затем установил ul так, чтобы li находился внутри. Это установит li в правильное место.
Добавление overflow: hidden скроет все, кроме первого столбца.
при наведении курсора я устанавливаю видимость переполнения, чтобы вы могли видеть остальные li.
поскольку мы не можем добавить фон к той части, которая выходит за пределы, я смоделировал это, добавив div внутри каждого li.
Это почти поможет. НО, когда последний столбец не заполнен, вы увидите пустой промежуток без фона в последнем столбце.
Итак, чтобы преодолеть это, я добавил селектор 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>Я собираюсь попробовать ваше решение сегодня. Я вернусь с обратной связью.
Ваше решение работает, но мне действительно нужны анимации. По этой причине я не пометил ваш ответ как ответ. Умная мысль;)
Не уверен, почему @Michael_B пометил его как дубликат, похоже, это не тот же вопрос, и я нашел решение только с css