在Flexbox元素之间检测鼠标悬停和鼠标按下事件

4

我有以下HTML/CSS代码:

.item {
  border: 1px solid gray;
  text-align: center;
  box-sizing: border-box;
  padding: 10px;
}

.flex-row {
  width: 100%;
  display: flex;
  justify-content: space-around;
  margin-top: 10px;
}
<div class="flex-row">
    <div class="item" style="width: 25%;">
        25%
    </div>
    <div class="item" style="width: 25%;">
        25%
    </div>
    <div class="item" style="width: 10%;">
        10%
    </div>
    <div class="item" style="width: 20%;">
        20%
    </div>
    <div class="item" style="width: 20%;">
        20%
    </div>
</div>

<div class="flex-row">
    <div class="item" style="width: 50%;">
        50%
    </div>
    <div class="item" style="width: 18%;">
        18%
    </div>
    <div class="item" style="width: 12%;">
        12%
    </div>
    <div class="item" style="width: 20%;">
        20%
    </div>
</div>

(注:实际上我在项目中没有上述代码,它是由Angular在ngFor中生成的,但这并不重要。)
我想在flexbox中间插入间距,以便可以检测悬停和鼠标按下事件,如下所示:

.item {
  border: 1px solid gray;
  text-align: center;
  box-sizing: border-box;
  padding: 10px;
}

.spacer {
  width: 25px;
}

.spacer:hover {
  cursor: pointer;
  background-color: blue;
}

.flex-row {
  width: 100%;
  display: flex;
  justify-content: space-around;
  margin-top: 10px;
}
<div class="flex-row">
    <div class="item" style="width: 25%;">
        25%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 25%;">
        25%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 10%;">
        10%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 20%;">
        20%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 20%;">
        20%
    </div>
</div>

<div class="flex-row">
    <div class="item" style="width: 50%;">
        50%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 18%;">
        18%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 12%;">
        12%
    </div>

    <div class="spacer" (mousedown)="someFunction()"></div>

    <div class="item" style="width: 20%;">
        20%
    </div>
</div>

(不用担心这里(mousedown)调用的语法,只需知道我想在单击间隔器时调用一个函数)
问题在于间隔器破坏了flexbox的流程(如预期)。两个25%的元素不再与后面一行的50%元素完美对齐。
我发现可以使用border-box在Flex元素之间添加空格并保持对齐,但我无法弄清楚如何在不破坏布局的情况下跟踪鼠标悬停/单击事件。

你是否可以使用 display: grid 而不是 flexbox? - IronFlare
@IronFlare 这是为内部应用程序而设计的,因此我可以确保用户使用支持网格的浏览器。只要解决方案支持每行任意数量的元素,并动态适应额外的元素/更改宽度即可。因此 display: grid 是可以的。 - Christian Scillitoe
我需要知道哪一个被点击了。我打算将从 ngFor 传递的索引传递到所调用的函数中。 - Christian Scillitoe
好的。你有预定义的可能单元格宽度集吗? - IronFlare
好的,我有一个非常优雅的解决方案,但是当然,用于启用它的CSS特性是实验性的,还没有在浏览器中。请稍等。 - IronFlare
显示剩余2条评论
1个回答

2
注意:这里的第一个代码片段由于依赖于一项实验性功能,其浏览器支持为零,因此是非功能性的。这个功能在未来的某个时候可能会起作用,或者在它到达浏览器之前就被废弃。它不应该在生产环境(或开发或QA)中使用,因为它将回退到“width: auto”。话虽如此,我想包括它是因为我已经花时间编写它,一旦实现了它可能会有所帮助。

理想情况

最优雅的语法解决方案是使用CSS attr 属性从 HTML 属性提供的宽度中减去。不幸的是,这在任何地方都还没有得到支持,所以这种策略不起作用。如果它被支持,代码可能会像这样。

.item {
  border: 1px solid gray;
  text-align: center;
  box-sizing: border-box;
  padding: 10px;
  /* If this was supported, it would be great. */
  width: calc(attr(data-width length, 25px) - 25px);
}

.item:last-child {
  width: calc(attr(data-width length));
}

.flex-row {
  width: 100%;
  display: flex;
  margin-top: 10px;
}

.spacer {
  width: 25px;
}

.spacer:hover {
  cursor: pointer;
  background-color: blue;
}
<h1>This does not work because<br>attr is not fully supported :(</h1>

<div class="flex-row">
  <div class="item" data-width="25%">25%</div>
  <div class="spacer"></div>
  <div class="item" data-width="25%">25%</div>
  <div class="spacer"></div>
  <div class="item" data-width="10%">10%</div>
  <div class="spacer"></div>
  <div class="item" data-width="20%">20%</div>
  <div class="spacer"></div>
  <div class="item" data-width="20%">20%</div>
</div>

<div class="flex-row">
  <div class="item" data-width="50%">50%</div>
  <div class="spacer"></div>
  <div class="item" data-width="18%">18%</div>
  <div class="spacer"></div>
  <div class="item" data-width="12%">12%</div>
  <div class="spacer"></div>
  <div class="item" data-width="20%">20%</div>
</div>


现实主义

现在,有一种方法可以做到这一点,而不需要使用attr,但它的语法不太美观。您可以在除了行中最后一个元素之外的所有元素中,在内联style声明中使用calc()来减少宽度。该策略也用于先前的示例中。如果您正在使列可调整大小,则必须进行一些非常基本的字符串连接,以确保calc语句包含在内联样式中。

.item {
  border: 1px solid gray;
  text-align: center;
  box-sizing: border-box;
  padding: 10px;
}

.flex-row {
  width: 100%;
  display: flex;
  margin-top: 10px;
}

.spacer {
  width: 25px;
}

.spacer:hover {
  cursor: pointer;
  background-color: blue;
}
<div class="flex-row">
  <div class="item" style="width: calc(25% - 25px)">25%</div>
  <div class="spacer"></div>
  <div class="item" style="width: calc(25% - 25px)">25%</div>
  <div class="spacer"></div>
  <div class="item" style="width: calc(10% - 25px)">10%</div>
  <div class="spacer"></div>
  <div class="item" style="width: calc(20% - 25px)">20%</div>
  <div class="spacer"></div>
  <div class="item" style="width: 20%">20%</div>
</div>

<div class="flex-row">
  <div class="item" style="width: calc(50% - 25px)">50%</div>
  <div class="spacer"></div>
  <div class="item" style="width: calc(18% - 25px)">18%</div>
  <div class="spacer"></div>
  <div class="item" style="width: calc(12% - 25px)">12%</div>
  <div class="spacer"></div>
  <div class="item" style="width: 20%">20%</div>
</div>


calc() 语句应用于内部 flex 项非常完美,谢谢! - Christian Scillitoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接