likes
comments
collection
share

如何在 contenteditable 元素上实现 placeholder 占位符?

作者站长头像
站长
· 阅读数 70

如何在 contenteditable 元素上实现 placeholder 占位符?

前几天写了一篇文章 《如何实现输入框跟随文字内容适配宽度?》,有 JY 评论说可以使用 <div contenteditable="true"> 实现宽度跟随内容实时变化,看到后立即给他点了一个大大的赞 👍。

如何在 contenteditable 元素上实现 placeholder 占位符?

聊聊 contenteditable

那今天这篇文章就来说一说 contenteditable 属性,这个属性可以让元素变成可编辑状态。

你可以尝试打开任何一个网页,然后打开开发者工具,在 Elements 面板 选中 body 元素,在 body 元素上添加属性 contenteditable="true",你会发现整个页面的内容都可以自由编辑。

如何在 contenteditable 元素上实现 placeholder 占位符?

富文本编辑器

业界很多富文本编辑器,使用的都是 contenteditable 来实现编辑。

如何在 contenteditable 元素上实现 placeholder 占位符?

如何在 contenteditable 元素上实现 placeholder 占位符?

如何在 contenteditable 元素上实现 placeholder 占位符?

还有很多其它优秀的富文本编辑器,这里就不一一列举,大家有兴趣可以到 Github Topics 查看。

实现 placeholder

今天文章的主题是如何在 contenteditable 元素上实现 placeholder 占位符?跟 input 元素不一样,input 元素本身支持 placeholder 属性,自带无内容占位效果。

<input type="text" placeholder="占位符" />

如何在 contenteditable 元素上实现 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
评论
请登录