【问题标题】:Case collision with flex-wrap: wrap when increasing width onHover与 flex-wrap 的案例冲突:增加宽度 onHover 时换行
【发布时间】:2019-02-13 17:30:21
【问题描述】:

我有一个有趣的问题,也许有人已经遇到过,我有一个使用 display:flex 和 flex-wrap:wrap 的列表。这也很好用,我的问题是我在 li 的右侧设置了一个 li 的 onHover 图标为可见,因此 li 的宽度增加了,并且由于空间不足和包装标志,li 被移到了下方。到目前为止一切都很好,但我还在 onmouseleave 中隐藏了图标,因此空间再次减小并且 li 向后跳,所以如果你能想象的话,这一切都会变得疯狂。下面的代码重现了这个问题,至少在我的显示器和 crhome 上,悬停在最后一个 li 上。

var ul = document.getElementById("fileList");
let listItem = document.createElement("li");
listItem.setAttribute('id', "li");
listItem.textContent = "Crazy jumping";
listItem.onmouseover = function (event) {  
  let removeIcon = document.getElementById("remove");
  removeIcon.setAttribute('class', 'removeIconVisible');
  event.preventDefault();
  return false;
};

listItem.onmouseleave = function () {
  let idTemp = listItem.getAttribute("id");
  let id = idTemp.slice(2, idTemp.length);
  let removeIcon = document.getElementById("remove" + id);
  removeIcon.setAttribute('class', 'removeIcon');
  return false; // Prevents propagation of the event to the parents.
};

let removeButton = document.createElement('img');
removeButton.setAttribute('id', "remove");
removeButton.setAttribute('src', "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAARElEQVR42mNgGAVUAApAfB+I/6Ph+1A5ssB/MvHgsYAugOauH7Vg1IJRC0YtIAI8IsHwR+RY4AHEj4kw/DFU7SggDwAAyTHHV/YXjncAAAAASUVORK5CYII=");
removeButton.setAttribute('class', 'removeIcon');
listItem.appendChild(removeButton);
ul.appendChild(listItem);
<!DOCTYPE html>
<html>
<head>
<style>
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
  display: flex;
            align-items: center;
            flex-wrap: wrap;
}

li {
   display: flex;
            font-family: sans-serif;
            background-color: gold;
            float: left;
            padding: 8px;
            margin-right: 8px;
            margin-bottom: 8px;
            border-radius: 10px;
            text-align: center;
            align-items: center;
}

li:hover {
  background-color: #FFFFFF;
}

.removeIcon {
    display: none;
    visibility: collapse;
}

.removeIconVisible {
    display: flex;
    visibility: visible;
}
        
</style>
</head>
<body>

<ul class="fileList" id="fileList">
  <li>
    <span class="text">Home</span>
  </li>
  <li>
    <span class="text">Home2</span>
  </li>
  <li>
    <span class="text">Home3</span>
  </li>
  <li>
    <span class="text">Home4</span>
  </li>
  <li>
    <span class="text">Home5</span>
  </li>
  <li>
    <span class="text">Home6Bigger</span>
  </li>
</ul>

</body>
</html>

【问题讨论】:

  • 最好看到而不是想象它;)
  • 如果您在示例中添加所有代码(html、js)会很有用
  • 这是不可能的,因为我都是用 JS 动态构建的。
  • 所以我们无法为您提供帮助..
  • 您可以添加构建代码的静态副本,对吗?或者至少有一个截图来说明问题?

标签: javascript html css flexbox


【解决方案1】:

根本没有足够的空间让项目有图像(没有包装)。 “疯狂的跳跃”想想也没有那么疯狂:

  1. 你悬停,onmouseover 被解雇
  2. 图片添加完毕,列表项换行
  3. 因为空间不足,这会触发onmouseleave 事件(鼠标不再悬停)
  4. 图像被移除,项目移回原位
  5. 一遍遍……

为了防止项目包装从列表中删除flex-wrap: wrap;。但这可能意味着物品不适合容器。

或者,您可以随时为图像保留空间。这意味着您总是渲染图像,默认隐藏它并在悬停时显示它。下面的示例使用 CSS 悬停来显示/隐藏图像:

let ul = document.getElementById("fileList");

// Create new list item
let listItem = document.createElement("li");
listItem.textContent = "Crazy jumping";

// Create remove icon
let removeIcon = document.createElement("img");
removeIcon.classList.add("removeIcon");
removeIcon.setAttribute("id", "remove");
removeIcon.setAttribute("src", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAARElEQVR42mNgGAVUAApAfB+I/6Ph+1A5ssB/MvHgsYAugOauH7Vg1IJRC0YtIAI8IsHwR+RY4AHEj4kw/DFU7SggDwAAyTHHV/YXjncAAAAASUVORK5CYII=");

// Append items
listItem.appendChild(removeIcon);
ul.appendChild(listItem);
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

li {
  display: flex;
  font-family: sans-serif;
  background-color: gold;
  float: left;
  padding: 8px;
  margin-right: 8px;
  margin-bottom: 8px;
  border-radius: 10px;
  text-align: center;
  align-items: center;
}

li:hover {
  background-color: #FFFFFF;
}

li:hover .removeIcon {
  visibility: visible;
}

.removeIcon {
  visibility: hidden;
}
<ul class="fileList" id="fileList">
  <li>
    <span class="text">Home</span>
  </li>
  <li>
    <span class="text">Home2</span>
  </li>
  <li>
    <span class="text">Home3</span>
  </li>
  <li>
    <span class="text">Home4</span>
  </li>
  <li>
    <span class="text">Home5</span>
  </li>
  <li>
    <span class="text">Home6Bigger</span>
  </li>
</ul>

编辑:

说“当鼠标在项目上不换行时,只是溢出”或类似的话似乎不合逻辑。

就像我之前说的,从列表中删除 flex-wrap: wrap 以防止它被换行。您还可以通过添加white-space: nowrap 来防止文本换行(参见下面的示例)。

难道不能在 onmouseover 中设置属性吗?问题 还会是什么属性?

我建议在可能的情况下使用 CSS 而非 JavaScript 进行样式设置,例如用于在悬停时隐藏等(如上面的示例)。 当然,您可以使用onmouseoveronmouseleave 事件来切换removeIconVisible 类:

let ul = document.getElementById("fileList");

// Create new list item
let listItem = document.createElement("li");
listItem.textContent = "Crazy jumping";

// Create remove icon
let removeIcon = document.createElement("img");
removeIcon.classList.add("removeIcon");
removeIcon.setAttribute("id", "remove");
removeIcon.setAttribute("src", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAARElEQVR42mNgGAVUAApAfB+I/6Ph+1A5ssB/MvHgsYAugOauH7Vg1IJRC0YtIAI8IsHwR+RY4AHEj4kw/DFU7SggDwAAyTHHV/YXjncAAAAASUVORK5CYII=");

listItem.onmouseover = function () {  
  removeIcon.classList.add("removeIconVisible");
};

listItem.onmouseleave = function () {
  removeIcon.classList.remove("removeIconVisible");
};

// Append items
listItem.appendChild(removeIcon);
ul.appendChild(listItem);
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
  display: flex;
  align-items: center;
  /*flex-wrap: wrap;*/
  white-space: nowrap;
}

li {
  display: flex;
  font-family: sans-serif;
  background-color: gold;
  float: left;
  padding: 8px;
  margin-right: 8px;
  margin-bottom: 8px;
  border-radius: 10px;
  text-align: center;
  align-items: center;
}

li:hover {
  background-color: #FFFFFF;
}

.removeIcon {
  display: none;
  visibility: collapse;
}

.removeIconVisible {
  display: flex;
  visibility: visible;
}
<ul class="fileList" id="fileList">
  <li>
    <span class="text">Home</span>
  </li>
  <li>
    <span class="text">Home2</span>
  </li>
  <li>
    <span class="text">Home3</span>
  </li>
  <li>
    <span class="text">Home4</span>
  </li>
  <li>
    <span class="text">Home5</span>
  </li>
  <li>
    <span class="text">Home6Bigger</span>
  </li>
</ul>

替代方案

您还可以将图标定位为绝对位置,将其放置在悬停时的文本上(屏蔽)。这将防止项目包装和溢出。

li {
  position: relative;
}

li:hover .removeIcon {
  background-color: white;
  position: absolute;
  right: 2px;
}

【讨论】:

  • 谢谢,难道不能在onmouseover中设置属性吗?问题也将是什么属性?说“当鼠标在项目上不换行时,只是溢出”或类似的话似乎不合逻辑。
  • 我已经更新了答案。我建议尽可能使用 CSS 进行样式设置而不是 JavaScript,例如用于在悬停时隐藏东西等。
  • “就像我之前说的,从列表中删除 flex-wrap: wrap 以防止它被换行。” 但是我需要换行,我的列表是动态填充的,所以它可能会变得很长。关于文本换行我不知道你在这种情况下是什么意思。
  • 所以你想让它们换行,但防止它们在悬停时换行?我不知道还有哪些其他选项,我认为它要么为图标保留空间(第一个示例),要么将图标绝对定位在项目内部(或外部);在我的答案中添加了替代 sn-p。
猜你喜欢
  • 2017-12-03
  • 2017-12-17
  • 2016-10-15
  • 2020-03-16
  • 2019-09-08
  • 1970-01-01
  • 2019-01-31
  • 1970-01-01
  • 2021-09-20
相关资源
最近更新 更多