如何在 contenteditable 元素上实现 placeholder 占位符?
如何在 contenteditable 元素上实现 placeholder 占位符?
前几天写了一篇文章 《如何实现输入框跟随文字内容适配宽度?》,有 JY 评论说可以使用 <div contenteditable="true">
实现宽度跟随内容实时变化,看到后立即给他点了一个大大的赞 👍。
聊聊 contenteditable
那今天这篇文章就来说一说 contenteditable 属性,这个属性可以让元素变成可编辑状态。
你可以尝试打开任何一个网页,然后打开开发者工具,在 Elements 面板 选中 body 元素,在 body 元素上添加属性 contenteditable="true"
,你会发现整个页面的内容都可以自由编辑。
富文本编辑器
业界很多富文本编辑器,使用的都是 contenteditable 来实现编辑。
还有很多其它优秀的富文本编辑器,这里就不一一列举,大家有兴趣可以到 Github Topics 查看。
实现 placeholder
今天文章的主题是如何在 contenteditable 元素上实现 placeholder 占位符?跟 input 元素不一样,input 元素本身支持 placeholder 属性,自带无内容占位效果。
<input type="text" placeholder="占位符" />
但是 contenteditable 本身是个 HTML 元素的属性,而非 HTML 元素。所以并不会有 placeholder 占位符的特性,那我们该如何实现呢?
下文介绍两种方式实现这个特性,一种使用 CSS,另一种使用 JavaScript,来学习一下吧。
1. 使用 :not
:focus
:empty
伪类选择器和 ::before
伪元素
一下子看到这么多伪类、伪元素选择器是不是有点接受不来,如果有这个感觉,说明同学你的 CSS 不过关哟~
大多数同学应该都还没有听说过 :empty
伪类选择器,更别说使用了。这也很正常,毕竟现在做前端的大多不怎么写样式。
OK,我们先定义好 HTML 结构。
<div class="editable" contenteditable data-placeholder="占位符"></div>
注意,我们占位符的内容是写在 data-*
属性上。
然后,:empty
伪类选择器和其它选择器的结合使用方式如下。
.editable:not(:focus):empty::before {
content: attr(data-placeholder);
}
上面这段 CSS 代码我用人类中文中文语言来描述一下。
当 .editable
元素处于非 focus
聚焦状态时,如果元素的内容为空,则元素的 ::before
伪元素 content 内容为 data-placeholder
属性的值。
通过上面的描述,同学是不是稍微清楚一些啦?如果还没有的话,那就消化消化再往下看吧。
2. 使用 JavaScript
先定义好 HTML 结构:
<div
id="contentEidt"
class="editable"
contenteditable
data-placeholder="占位符"
></div>
同样需要利用到 data-placeholder
属性存储占位符。
通过 JavaScript 处理 focus
聚焦和 blur
失焦事件,逻辑如下:
- 先初始化元素的内容为
data-placeholder
的内容; - 当元素
focus
聚焦时,如果元素内容与data-placeholder
内容相等,则将元素内容设置为空; - 当元素
blur
失焦时,如果元素内容为空,则将元素内容设置为data-placeholder
当内容;
实现代码如下:
const ele = document.getElementById('contentEidt');
const placeholder = ele.getAttribute('data-placeholder');
ele.innerHTML === '' && (ele.innerHTML = placeholder);
ele.addEventListener('focus', function (e) {
const value = e.target.innerHTML;
value === placeholder && (e.target.innerHTML = '');
});
ele.addEventListener('blur', function (e) {
const value = e.target.innerHTML;
value === '' && (e.target.innerHTML = placeholder);
});
最后,来看看上述两种方案的实现效果:
全文完,如果觉得有用,欢迎 点赞 👍、评论 ✍️、收藏 👀
转载自:https://juejin.cn/post/7131372857682034719