如何突出显示和检测 CSS 网格行上的鼠标点击?

Posted

技术标签:

【中文标题】如何突出显示和检测 CSS 网格行上的鼠标点击?【英文标题】:How to highlight and detect mouse clicks on a css grid row? 【发布时间】:2019-04-25 12:27:15 【问题描述】:

我正在尝试创建一个使用 CSS 网格布局的菜单。我遇到的问题是弄清楚当鼠标悬停在每个菜单项上时如何使菜单交互。

当鼠标悬停在行中的任何菜单项上时,我希望能够突出显示整行。我可以通过添加 :hover css 规则来突出显示每个单独的网格单元格,但我不知道如何突出显示整个网格行。

第二部分是检测何时点击了一行。同样,我可以为每个单元格添加一个 onClick 事件处理程序,但这似乎并不理想,因为用户可能会不小心单击网格单元格之间的间隙。我在想,如果我能弄清楚如何突出显示整行,那么我可以将点击处理程序添加到该行突出显示中,这样就可以解决间隙点击问题。

我创建了一个 codepen 示例来演示当前如何构建菜单:https://codepen.io/marekKnows_com/pen/RqMgGw

html

<div class="myGrid">
  <div class="anchor" id="item1">
    <i class="image material-icons">folder_open</i>
  </div>
  <span class="text">Open...</span>
  <span class="shortcut">Ctrl+O</span>

  <div class="anchor" id="item2">
    <i class="image material-icons">save</i>
  </div>
  <span class="text">Save...</span>
  <span class="shortcut">Ctrl+S</span>

  <div class="anchor" id="item3"></div>
  <span class="text">Action</span>

  <div class="separator"></div>

  <div class="anchor" id="item4"></div>
  <span class="text">Exit</span>
  <span class="shortcut">Ctrl+X</span>
</div>

CSS:

.myGrid 
  border: 1px solid black;
  display: grid;
  grid-template-columns: 20px auto auto;
  grid-gap: 2px 6px;
  align-items: center;
  justify-items: start;
  padding: 10px;
  box-sizing: border-box;

.image  
  width: 24px;

.text 
  height: 28px;
  line-height: 28px

.shortcut 
  justify-self: end;
  padding: 0 5px;
  height: 28px;
  line-height: 28px

.separator 
  grid-column: 1 / span 3;
  width: 100%;
  height: 3px;
  border-bottom: 1px solid lightgray;

【问题讨论】:

使用弹性和改变结构更容易更快,也更合适。 只需添加#item1:hover > .mygridborder:1px solid red 我不能使用 flex,因为这并不能保证所有的图像、文本和快捷方式都会排列在漂亮的列中。这就是我选择网格而不是弹性布局的原因。 #item1:hover > .mygridborder:1px solid red 不起作用。我粘贴到我的 codepen 示例中,但没有看到任何事情发生 【参考方案1】:

一种选择是用 div 包装行元素,在包装器 div 中包含样式 display: contents;,将点击处理程序添加到包装器 div。

CSS 网格将在布局内容时将包装器内的元素视为没有包装器,因此它们将按照您的意愿对齐。请参阅MDN display-box 了解更多信息。该链接还指出浏览器存在display: contents; 的可访问性错误。

到目前为止,我只用 Firefox 进行了测试。

<div class="myGrid">

  <div class="row" onclick="console.log('click');">
    <div class="anchor" id="item1">
      <i class="image material-icons">folder_open</i>
    </div>
    <span class="text">Open...</span>
    <span class="shortcut">Ctrl+O</span>
  </div>

  <div class="row" onclick="console.log('click');">
    <div class="anchor" id="item2">
      <i class="image material-icons">save</i>
    </div>
    <span class="text">Save...</span>
    <span class="shortcut">Ctrl+S</span>
  </div>

  <div class="row" onclick="console.log('click');">
    <div class="anchor" id="item3"></div>
    <span class="text">Action</span>
  </div>

  <div class="separator"></div>

  <div class="row" onclick="console.log('click');">
    <div class="anchor" id="item4"></div>
    <span class="text">Exit</span>
    <span class="shortcut">Ctrl+X</span>
  </div>

</div>
.myGrid 
  border: 1px solid black;
  display: grid;
  grid-template-columns: 20px auto auto;
  grid-gap: 2px 6px;
  align-items: center;
  justify-items: start;
  padding: 10px;
  box-sizing: border-box;

.row 
  display: contents;

.image  
  width: 24px;

.text 
  height: 28px;
  line-height: 28px

.shortcut 
  justify-self: end;
  padding: 0 5px;
  height: 28px;
  line-height: 28px

.separator 
  grid-column: 1 / span 3;
  width: 100%;
  height: 3px;
  border-bottom: 1px solid lightgray;

【讨论】:

【参考方案2】:

我终于让它工作了。我最终做的是使锚元素具有相对位置。然后我在锚元素下添加了一个绝对位置的新 div。在 javascript 中,我可以将新元素的大小设置为网格的全宽,并使用 z-index 我可以相应地相对于行中的其他元素定位它。

【讨论】:

【参考方案3】:
       .anchor:hover > 
       .mygrid
        background:red  

如果它适用于悬停 item1,则检查此项,它将更改边框颜色(从黑色变为红色以突出显示)

【讨论】:

#item1:hover > .mygridborder:1px solid red 不起作用。我粘贴到我的 codepen 示例中,但我没有看到任何事情发生,您能否发布一个包含您建议更改的工作 codepen 示例。也许我错过了一个细节 您是否将鼠标悬停在 item1 上 是的,看这里。将鼠标悬停在任何项目上都不会以红色显示任何内容。 codepen.io/marekKnows_com/pen/rQdGOM 我已经替换了一些东西。实际上我正在尝试暴民,所以看不到悬停效果。您能否尝试添加我在上面再次编写的这种 css 样式 让我们continue this discussion in chat.【参考方案4】:

首先,您可能想要更改您的 html,以便 .anchor 元素包装每个项目。

<div class="myGrid">
    <div class="anchor" id="item1">
        <i class="image material-icons">folder_open</i>
        <span class="text">Open...</span>
        <span class="shortcut">Ctrl+O</span>
    </div>
    <div class="anchor" id="item2">
        <i class="image material-icons">save</i>
        <span class="text">Save...</span>
        <span class="shortcut">Ctrl+S</span>
    </div>
    <div class="anchor" id="item3">
        <span class="text">Action</span>
    </div>
    <div class="separator"></div>
    <div class="anchor" id="item4">
        <span class="text">Exit</span>
        <span class="shortcut">Ctrl+X</span>
    </div>
</div>

然后使用flex来对齐每个item的内容

.myGrid 
  border: 1px solid black;
  padding: 10px;
  box-sizing: border-box;


.anchor 
  display: flex;
  justify-content: flex-start;


/* Hover for each anchor */
.anchor:hover 
    background: red;


.image  
    width: 24px;


.text 
    height: 28px;
    line-height: 28px


.shortcut 
    margin-left: auto; /* push the shortcut to the right */
    padding: 0 5px;
    height: 28px;
    line-height: 28px


.separator 
    grid-column: 1 / span 3;
    width: 100%;
    height: 3px;
    border-bottom: 1px solid lightgray;

https://codepen.io/anon/pen/xQWLaE

【讨论】:

不能使用 flex 布局,因为它不能保证所有的图像、文本和快捷方式都会排列在漂亮的列中。这就是我改用网格的原因。请注意,在您的示例中,Action 和 Exit 不再正确对齐。

以上是关于如何突出显示和检测 CSS 网格行上的鼠标点击?的主要内容,如果未能解决你的问题,请参考以下文章

模拟网格行上的单击事件

如何使用 Javascript 鼠标事件和 CSS 重新创建“突出显示”选择?

如何在 CSS Grid 中突出显示行中的所有单元格(显示:网格)

使用 Sprite 的 CSS 导航菜单:如何突出显示当前页面的选项卡/按钮?

单击jqgrid网格时如何仅突出显示单元格

UIPicker 检测当前选定行上的点击