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;时,应该红框之间都不能点击。

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

最后

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

相关推荐
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
猫爪笔记5 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html
风尚云网7 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
佚先森7 小时前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
Myli_ing8 小时前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
FØund4049 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
酷酷的威朗普9 小时前
医院绩效考核系统
javascript·css·vue.js·typescript·node.js·echarts·html5
渊兮兮9 小时前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画
一棵开花的树,枝芽无限靠近你10 小时前
【PPTist】添加PPT模版
前端·学习·编辑器·html
土豆湿10 小时前
拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流
开发语言·javascript·css