text-indent 导致点击事件失效?

问题

项目中一个弹框的关闭按钮,按钮有背景图片,文字使用缩进隐藏:

html 复制代码
<style>
  .modal-close {
    width: 20px;
    height: 20px;
    background-image: xxx;
    text-indent: 100%;
    overflow: hidden;
  }
</style>

<div class="modal">
  <div class="modal-header">
   <button class="modal-close" onclick="onClose()">关闭</button>
  </div>
</div>

<script>
  function onClose() {
    console.log('关闭');
  }
</script>

问题是什么呢?

点击没有效果。仔细观察,似乎是按钮右边一个区域无法点击,而左上的区域即使超出了元素范围也可以点击。

尝试

为什么 text-indent 使用值 100% 呢,因为用的 tailwindcss,一开始发现 100% 似乎好写一点,class="indent-[100%]"

MDN 中:

<percentage>:Indentation is a <percentage> of the containing block's width.

缩进包含容器宽度的百分比。理论上没问题啊,只要能隐藏文本。

使用 text-indent: -9999px;:

css 复制代码
.modal-close {
  text-indent: -9999px;
}

可以解决问题。

不使用 button 元素:

html 复制代码
<div class="modal-close" onclick="onClose()">关闭</div>

也可以解决问题。

或者根本不用写文字和使用 text-indent。

但是这个现象到底是什么原因导致的呢?

一个 demo

为了研究这个问题,给出一个具体的 demo:

codepen.io/zangbianxue...

红色按钮,靠右边大致红框的区域无法触发点击事件。

打开网页,打开控制台,打开 toggle device toolbar,点击第一个按钮,控制台输出 111,小心的把鼠标移动到按钮右侧的边缘附近,就会发现点击失效。而 div 元素没有此现象。

探究

Chrome 模拟移动设备

在探究的过程中,发现,只有在 Chrome 模拟移动设备中,才会出现这个问题,正常 PC 模式下没问题。按钮的任何区域都可以点击。

模拟移动设备似乎还有一个问题,Chrome 似乎为了方便移动端点击事件,给元素增加了一个点击范围,也就是说,即使超出了元素范围一点点,也是可以点击的。经过尝试,这个距离大概是 15px。

这里反映了一个同样的问题:html elements are picking click events outside their bounds

我搜了一下,却没有找到相关的说明(不知道什么原因)。却有很多 "Emulate Touch Events in Chrome" 的说明,找了半天,似乎当前 Chrome 已经没有了这个设置:

另外这里有个相关问题:Wrong clickable area of a button on mobile

以上,只是说明 Chrome 模拟移动设备的这个特性。

overflow: hidden

当删除 overflow: hidden; 时,是没有问题的。说明是文本缩进超出隐藏共同影响了点击范围。

在我们的 demo 中,text-indent 和 overflow 让文本的一部分隐藏了,一部分仍然在元素范围中。

元素的点击范围应该只是元素本身?

还是说 button 比较特殊,它的点击和文本有关系?

不同大小的元素比较

为了便于观察,扩大点击的范围,同时重置了一些 button 的默认样式:

html 复制代码
<style>
  .close {
    text-align: left;
    padding: 0;
    padding-block: 0;
    padding-inline: 0;
    writing-mode: horizontal-tb;
    word-wrap: break-word;
    margin: 15px;
    border: 1px solid red;
    width: 300px;
    height: 300px;
    text-indent: 300px;
    /* text-indent: -9999px; */
    overflow: hidden;
  }
</style>

<div class="close-wrapper">
  <button class="close" onclick="onClose()">关闭</button>
</div>

放大元素之后发现,不可点击的范围只是右边的一个小区域。

隐藏和扩大的可点击范围相结合

会发现,整个绿色的区域基本上都可以点击,除了大概蓝色的区域。不确定这个区域的具体范围,但是这个区域不就是缩进的文本周围吗??

就是说,"关"字虽然被隐藏了,就不能响应点击事件了,但是它又影响了什么?

经过反复测试,text-indent: 298px; text-indent: 295px; text-indent: 320px;

text-indent: 298px;

蓝色区域意料中的不能点击,但是黄色区域有一个小小的区域可以点击!

为了说明,特地录了个视频(结果还要上传西瓜视频):

反复尝试之后,似乎终于发现了问题所在:

  • Chrome 模拟移动设备为元素增加了点击范围,大概 15px;
  • 所以 button 元素周围 15px 可点击;
  • text-overflow: hidden; 隐藏文本,隐藏的部分当然不可点击,即使在 button 周围可点击范围;
  • 隐藏的部分也有一个扩大点击范围,因为隐藏的部分不可点击,它的扩大范围也不可点击,即使在元素本身的可点击范围之内;
  • 点击和不可点击(overflow-hidden)相互叠加之后,不可点击范围覆盖点击范围;

因此隐藏的文本"关"有一个扩大的不可点击范围,覆盖在了 button 按钮之上,所以造成了这种现象。

text-indent: 320px;

为了验证这种想法,当 text-indent: 320px; 时,应该 button 右侧大概 5px 可以点击。当当 text-indent: 315px;时,应该红框之间都不能点击。

但是在实际测的过程,还是有些不合理。当然扩大的点击范围值只是我的猜测,而且,这一切,都是我的假设和推理。

最后

虽然想要搞清楚,真实的实现原理还是不知道,苦于这方面的文档不知道怎么找。希望有看到和了解的,可以分享一下~

相关推荐
DogEgg_00125 分钟前
前端八股文(一)HTML 持续更新中。。。
前端·html
黎金安1 小时前
前端第二次作业
前端·css·css3
阳光开朗大男孩 = ̄ω ̄=2 小时前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
小马哥编程4 小时前
【前端基础】CSS基础
前端·css
Justinc.5 小时前
CSS3新增边框属性(五)
前端·css·css3
fruge5 小时前
纯css制作声波扩散动画、js+css3波纹催眠动画特效、【css3动画】圆波扩散效果、雷达光波效果完整代码
javascript·css·css3
As977_5 小时前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu10830189115 小时前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾5 小时前
前端基础-html-注册界面
前端·算法·html
我要洋人死8 小时前
导航栏及下拉菜单的实现
前端·css·css3