【问题标题】:Placeholder that disappears character by character逐字符消失的占位符
【发布时间】:2018-10-08 20:19:31
【问题描述】:

我的目标是有一个输入元素,当您在输入中键入字符时,占位符会逐个字符地消失。最好使用带有占位符MM/DD/YYYY 的“生日”输入来解释这一点。如果您在输入中键入06,则占位符/DD/YYYY 仍应保留。

虽然这个问题的答案是: text box with placeholder text that dissapears character by character,我还有一个限制:“输入”必须是“contenteditable="true"div。那里接受的答案不适用于contenteditable divs。

纯 HTML、CSS 和 JavaScript 的纯解决方案是最好的。请不要使用 jQuery。

【问题讨论】:

  • 正确,但需要从头开始编写(和测试)一些复杂的代码。为什么它必须在 contenteditable 中?
  • 1) 更简单,2) 如果我想切换到输入字段,我无法在链接线程中使用该解决方案,因为它使用 jQuery,我个人厌恶 jQuery。
  • 周围还有其他的屏蔽脚本
  • @charlietfl 我同意解决方案需要一些技巧才能完成,但我认为这实际上是一个有趣的案例。试图在我的回答中涵盖大部分内容(我希望)。它包含一些不寻常的 CSS 选择器,但几乎不包含任何 JavaScript 代码(除了关注一个元素)

标签: javascript html css


【解决方案1】:

这是我的诀窍:

  • 占位符位于contenteditable 后面
  • contenteditable 需要根据内容大小增长。这是通过在contenteditable 上设置display: inline-block 来完成的。
  • 父元素和contenteditable 应该具有相同的背景颜色。
  • onclick 函数被添加到父元素中,以允许在 editablecontent 的宽度为 0% 时关注它
  • monospace 字体用于确保字体中的每个字符具有相同的宽度(使您编写的每个字符都隐藏一个字符)
  • contenteditable 的宽度为0 时,会添加一个假插入符号来指示焦点(这实际上是在占位符内)。这是使用blink 动画完成的,带有通用兄弟组合器 (~)、:empty 选择器和 :focus 选择器
  • 占位符也可以使用afterbefore 伪元素来实现,但是由于我们不能将伪元素放在contenteditable 中,因此使用实际的dom 元素作为占位符可以使用使用通用兄弟组合器来处理 contenteditable 空状态
  • 某些浏览器会在宽度为 0 时显示原始插入符号(例如 firefox)。为了解决双插入符号,我们将输入插入符号隐藏在空状态

CSS 变量 用于同步嵌套在主容器内的所有元素的颜色。我添加了版本:灰色背景和白色背景。此外,这是此处使用的唯一 CSS 功能,尚未被所有现代浏览器完全支持。因此,如果您想要完整的浏览器支持,您可以特别放弃它,因为它对结果不是必需的:-)

IE & Edge 仍然在空状态下显示原来的插入符号。 (我在 javascript 中添加了一个函数来删除这些浏览器上的假插入符号)

// Get IE or Edge browser version
var isIEOrEdge = detectIE();

if (isIEOrEdge) {
  let editables = document.querySelectorAll('.kb-editable');

  for (let i = 0; i < editables.length; i++) {
    editables[i].classList.add('kb-edge');
  }
}

// this is the only function that is actually needed if the double IE\Edge caret doesn't bother you
function getFocus(id) {
  document.getElementById(id).focus();
}



/* VERY OPTIONAL :-) */
/**
 * detect IE
 * returns version of IE or false, if browser is not Internet Explorer
 */
function detectIE() {
  var ua = window.navigator.userAgent;

  // Test values; Uncomment to check result …

  // IE 10
  // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';

  // IE 11
  // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';

  // Edge 12 (Spartan)
  // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';

  // Edge 13
  // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';

  var msie = ua.indexOf('MSIE ');
  if (msie > 0) {
    // IE 10 or older => return version number
    return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
  }

  var trident = ua.indexOf('Trident/');
  if (trident > 0) {
    // IE 11 => return version number
    var rv = ua.indexOf('rv:');
    return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
  }

  var edge = ua.indexOf('Edge/');
  if (edge > 0) {
    // Edge (IE 12+) => return version number
    return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
  }

  // other browser
  return false;
}
.kb-editable {
  --bg-color: #D3D3D3;
  --placeholder-color: grey;
  --text-color: black;
  --border-color: transparent;
  --padding: 5px;
  width: 200px;
  height: 200px;
  background: var(--bg-color);
  position: relative;
  align-items: start;
  font-family: 'Anonymous Pro', monospace;
  font-size: 14px;
  overflow-y: auto;
  display: inline-block;
  cursor: text;
  border: 1px solid var(--border-color);
  padding: var(--padding);
}

.kb-editable [contenteditable="true"] {
  position: relative;
  z-index: 2;
  background: var(--bg-color);
  color: var(--text-color);
  outline: none;
  max-width: 100%;
  max-height: 100%;
  display: inline-block;
  /* deal with long words (break them to multiple lines) */
  word-wrap: break-word;
}

.kb-editable .kb-placeholder {
  position: absolute;
  top: var(--padding);
  bottom: var(--padding);
  left: var(--padding);
  right: var(--padding);
  color: var(--placeholder-color);
}


/* used for non-chrome to hide original caret on empty state */
[contenteditable="true"]:focus:empty {
  color: transparent;
  text-shadow: 0 0 0 black;
}

.kb-editable:not(.kb-edge) [contenteditable="true"]:focus:empty~.kb-placeholder:before {
  content: "|";
  color: var(--text-color);
  position: absolute;
  top: 0;
  left: 0;
  animation: 1s blink step-end infinite;
  caret-color: transparent;
}

@keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}
<link href="https://fonts.googleapis.com/css?family=Anonymous+Pro" rel="stylesheet">

<div class="kb-editable" onclick="getFocus('black')">
  <div contenteditable="true" id="black"></div>
  <span class="kb-placeholder">I'm a placeholder</span>
</div>

<div class="kb-editable" onclick="getFocus('white')" style="--bg-color: white; --border-color: black">
  <div contenteditable="true" id="white"></div>
  <span class="kb-placeholder">I'm the white version!</span>
</div>

【讨论】:

    猜你喜欢
    • 2018-02-13
    • 1970-01-01
    • 2011-11-19
    • 2023-03-10
    • 2018-12-30
    • 2016-03-04
    • 1970-01-01
    • 2016-01-29
    相关资源
    最近更新 更多