#javascript #html #css
Вопрос:
Я создаю свой собственный раскрывающийся список с помощью CSS. Вы наводите на него курсор, затем под ним появляются некоторые опции, вы выбираете одну из них, и все. Если вариантов слишком много, чтобы поместиться, есть полоса прокрутки. Вы можете увидеть все это здесь: JSFiddle
let testData = [
"qwertyuiop",
"asdfghjkl",
"zxcvbnm",
"axdxfcbhdhvhv",
"äöäööäöääöää",
"zoinkszoinks",
"brrrrrrrrrr",
"gygygygyasdasda",
];
getTestStuff();
function getTestStuff() {
let content = document.getElementById("content");
let text = document.getElementById("text");
for (let group of testData) {
let div = document.createElement("div");
div.innerHTML = group;
div.addEventListener("click", function() {
text.innerHTML = group; // update button text
}, false);
content.appendChild(div);
}
}
let dropdown = document.getElementById("dropdown");
let arrow = document.getElementById("arrow");
let content = document.getElementById("content");
dropdown.addEventListener("mouseenter", function () {
arrow.className = "open";
content.classList.add("open");
}, false);
dropdown.addEventListener("mouseleave", function () {
arrow.className = "closed";
content.classList.remove("open");
}, false);
.dropdown-wrapper {
height: 40px;
float: left;
margin: 0px 5px;
}
.dropdown-wrapper, .dropdown-content {
width: 300px;
}
.dropdown-wrapper .header {
width: 100%;
height: 100%;
margin: 0;
background-color: #f1f1f1;
text-align: center;
border-radius: 5px;
font-size: 16px;
border: 1px solid grey;
display: table;
}
.dropdown-wrapper .header span {
text-align: center;
vertical-align: middle;
display: table-cell;
width: 100%;
}
.dropdown-wrapper .header div span {
font-size: 20px;
}
.dropdown-wrapper .header div {
margin-left: -40px;
width: 40px;
height: 40px;
float: right;
text-align: center;
display: table;
position: absolute;
}
.dropdown-content {
display: none;
float: none;
max-height: 300px;
overflow-x: hidden;
overflow-y: scroll;
position: absolute;
font-size: 16px;
background-color: #f1f1f1;
min-width: 0px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
margin-right: auto;
text-align: center;
}
.dropdown-content div {
color: black;
float: none;
padding: 12px 16px;
text-decoration: none;
display: block;
margin-right: -15px;
}
.dropdown-content div:hover {
background-color: #ddd;
}
.dropdown {
height: 100%;
width: 100%;
}
.dropdown:hover .dropdown-content {
display: block;
}
#arrow.open {
-webkit-animation-name: openArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#arrow.closed {
-webkit-animation-name: closeArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
@-webkit-keyframes openArrowAnimation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
}
}
@-webkit-keyframes closeArrowAnimation {
from {
-webkit-transform: rotate(180deg);
}
to {
-webkit-transform: rotate(0deg);
}
}
#content.open {
-webkit-animation-name: openDropdownAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
@-webkit-keyframes openDropdownAnimation {
from {
max-height: 0px;
}
to {
max-height: 300px;
}
}
<div class="dropdown-wrapper">
<div class="dropdown" id="dropdown">
<div class="header">
<span id="text">Test Thing</span>
<div id="arrow"><span>^</span></div>
</div>
<div id="content" class="dropdown-content">
</div>
</div>
</div>
Проблема:
- Полоса прокрутки появляется во время моей анимации. Что не является проблемой, если оно останется, но когда содержимое подходит, оно снова исчезает.
- Когда полосы прокрутки нет, пространство, которое занимала бы полоса прокрутки, не имеет правильного цвета фона, когда я навожу курсор на опцию. Образуется очень уродливый пробел.
Я знаю об overflow: auto;
этом, но я все еще использую overflow: scroll;
с margin-right: -16px;
детьми, потому что моя полоса прокрутки перемещает детей, и у меня есть эта полоса прокрутки только иногда.
Мне нужен какой-то условный взлом CSS, чтобы установить overflow
значение скрыто, если нам это не нужно, или использовать JS для изменения margin-right
, но попытка проверить высоту родителей после добавления детей дала мне это:
Содержание.высота: не определена
содержание.стиль.высота: пустая строка
Так что я очень запутался в этом.
Комментарии:
1. Я не уверен, о чем вы спрашиваете, поэтому я спрашиваю: вы хотите изменить css с родительского узла в зависимости от содержимого дочернего узла? Это невозможно только с помощью css
2. Я на самом деле не ищу никакого конкретного решения этой проблемы. Я видел некоторые css-хаки, использующие calc () , но я недостаточно понимаю их, чтобы редактировать любое решение, которое я нахожу, в соответствии со своей проблемой.
3. Если вы «не ищете конкретного решения», то этот вопрос выходит за рамки темы.
4. 2. это связано с тем , что вы задаете
overflow-y: scroll;
, заставляя «заполнитель» для потенциальной полосы прокрутки. Если вы не хотите этого, установитеauto
вместо этого.5. «Высота смещения и высота прокрутки равны 0, так как я не определил никакой высоты» — это не причина, причина в том, что вы пытаетесь прочитать их, пока элемент имеет
display:none
. Элементы с таким стилем вообще не имеют никаких размеров.
Ответ №1:
Я заставил его работать с этим трюком над детьми:
margin-right: calc(100% - 300px);
И установка родителя overflow
на auto
Это работает, потому что здесь 100% — это элементы во всю ширину. Без полосы прокрутки 100% составляет 300 пикселей, поэтому поле равно 0. С полосой прокрутки 100% составляет около 290 пикселей, поэтому поле равно примерно -10, поэтому текст остается по центру.
Ответ №2:
Как отметил @CBroe, я не мог достичь высоты своей стихии или детей, потому что это было display: none
так, чтобы обойти это:
let content = document.getElementById("content");
content.style.display = "block";
let height = content.offsetHeight;
content.style.display = "";
Удивительно, что такая глупость так хорошо работает. Теперь я могу скрыть полосу прокрутки, когда она мне не нужна, и исправить смещение, которое создает полоса прокрутки, когда она мне нужна:
if (height < 300) {
content.style.overflowY = "hidden";
} else {
content.style.overflowY = "scroll";
for (let kid of content.children) {
kid.style.marginRight = "-16px";
}
}
Это решение имеет дополнительный бонус в том, что оно хорошо работает с моей анимацией. Проблема, которую не могло решить единственное решение CSS.