CSS伪元素input-placeholder :: after在文本框中显示有无值

时间:2016-02-05 05:49:36

标签: html css google-chrome pseudo-element

我尝试在验证后使用占位符伪元素(从文本框开始)为用户在表单元素上获取一些UI标记。我想要的是当文本框中存在值以及文本框中没有值时(例如,当存在无效值或何时)时,将显示::input-placeholder::after伪元素需要一个值 - 应通过::input-placeholder::after伪元素在文本框的最右侧显示红色" X"。

这里是小提琴: https://jsfiddle.net/edsinek/L8u7s25d/

这是我用来显示" X"的CSS的片段。对于无效值:

.input-invalid input[type=text]::-webkit-input-placeholder::after {
  content: "\2716"; // "X"
  font-size: 18px;
  color: #ff0000;
  padding-right: 0;
  float: right;
}

注意:我目前只对Chrome进行编码,因此请原谅特定于webkit的内容。

有什么想法吗?或者这是不可能的并且依赖于UA?

2 个答案:

答案 0 :(得分:8)

原始答案:(在Chrome v47及以上 + 中不起作用)

当您开始在文本框中输入内容时,::-webkit-input-placeholder元素的可见性设置为hidden。要显示其::after元素,即使输入框有值,我们也需要覆盖它并将visibility设置为visible

.input-invalid input[type=text]::-webkit-input-placeholder::after {
  visibility: visible;
}

    var addFormFocusEventHandler = function() {
      var placeholder;
      // using the document syntax in case input & container added to DOM dynamically
      $(document).on("focus", "div.input-container :input", function() {
        $(this).closest("div.input-container").addClass("input-focused");
        placeholder = $(this).prop("placeholder");
        $(this).prop("placeholder", " ");
      }).on("blur", "div.input-container :input", function() {
        $(this).closest("div.input-container").removeClass("input-focused");
        $(this).prop("placeholder", placeholder);
        placeholder = "";
      });
    };
    var addFormValueEventHandler = function() {
      // using the document syntax in case input & container added to DOM dynamically
      $(document).on("blur", "div.input-container :input", function() {
        if ($(this).val()) {
          $(this).closest("div.input-container").addClass("input-has-value");
        } else {
          $(this).closest("div.input-container").removeClass("input-has-value");
        }
      });
    };

    var initialize = function() {
      addFormFocusEventHandler();
      addFormValueEventHandler();
    };

    initialize();
 label {
   color: transparent;
   display: block;
 }
 input[type=text] {
   display: block;
   border-width: 0 0 1px !important;
   border-radius: 0;
   border-style: solid;
   border-color: rgba(0, 0, 0, 0.12);
 }
 .input-focused:not(.input-invalid) label {
   color: rgb(16, 108, 200);
 }
 .input-focused:not(.input-invalid) input[type=text] {
   border-color: rgb(16, 108, 200);
 }
 .input-has-value:not(.input-invalid):not(.input-focused) label {
   color: #595959;
 }
 .input-invalid.input-focused label,
 .input-invalid.input-has-value label {
   color: #ff0000;
 }
 .input-invalid input[type=text] {
   border-color: #ff0000;
 }
 .input-invalid input[type=text]::-webkit-input-placeholder {
   color: #ff0000;
 }
 .input-invalid input[type=text]::-webkit-input-placeholder::after {
   content: "\2716";
   /* "X" */
   font-size: 18px;
   color: #ff0000;
   padding-right: 0;
   float: right;
 }
 .input-valid input[type=text]::-webkit-input-placeholder::after {
   content: "\2714";
   /* checkmark */
   font-size: 18px;
   color: #438D5B;
   padding-right: 0;
   float: right;
 }
 .input-invalid input[type=text]::-webkit-input-placeholder::after {
   visibility: visible;
 }
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row">
    <div class="col-xs-12 input-container input-required">
      <label for="merchantAddress">Merchant Address</label>
      <input type="text" class="full-width" id="merchantAddress" placeholder="Merchant Address" />
    </div>
    <div class="col-xs-12 input-container input-valid">
      <label for="merchantCity">Merchant City</label>
      <input type="text" class="full-width" id="merchantCity" placeholder="Merchant City" value="" />
    </div>
    <div class="col-xs-12 input-container input-invalid">
      <label for="merchantState">Merchant State Code</label>
      <input type="text" class="full-width" id="merchantState" placeholder="Merchant State Code" value="" />
    </div>
    <div class="col-xs-12 input-container input-invalid input-required">
      <label for="merchantZip">Merchant Zip Code</label>
      <input type="text" class="full-width" id="merchantZip" placeholder="Merchant Zip Code" value="Bad Data" />
    </div>
  </div>
</div>

  

注意:不建议使用占位符伪元素或其子伪元素用于此目的,但如果您仍希望继续上述答案,为你工作。

+ 为什么上述内容在Chrome v47及更高版本中无效?

正如Pete Talks Web在评论中指出的那样,上面的内容似乎不适用于Chrome v47,而它适用于Chrome v43。这似乎是因为在输入文本后,占位符伪元素(::-webkit-input-placeholder)的隐藏方式存在关键差异。在v43中,visibility属性用于隐藏它,而在v47中,似乎使用了display:none。我无法访问v47,但假设这是基于在Opera中观察到的也使用WebKit的行为。还会添加!important。这个以及将属性添加为内联样式的事实意味着不可能仅使用CSS来覆盖它。 UA's shadow DOM elements cannot be accessed through JS also因此,一旦键入文本,就无法使伪元素可见。

最新的Chrome会发生什么?

在Chrome v50.0.2638.0 dev-m中,提供的小提琴本身不起作用。也就是说,不会显示十字标记和刻度标记。似乎WebKit已经开始抑制向::-webkit-input-placeholder添加伪元素。这是我一直期待发生的一件事,这正是我在答案中添加该注释的原因。

替代解决方案:

另一种解决方案是将伪元素添加到包装器div并将其定位为apt。在下面的代码片段中,我将input和伪元素更改为内联块,相对定位了伪元素,并为其添加了负margin-left。这些使它出现在输入框的右边缘附近。 (我还在width: 100%添加了label,使其跨越整行。

var addFormFocusEventHandler = function() {
  var placeholder;
  // using the document syntax in case input & container added to DOM dynamically
  $(document).on("focus", "div.input-container :input", function() {
    $(this).closest("div.input-container").addClass("input-focused");
    placeholder = $(this).prop("placeholder");
    $(this).prop("placeholder", " ");
  }).on("blur", "div.input-container :input", function() {
    $(this).closest("div.input-container").removeClass("input-focused");
    $(this).prop("placeholder", placeholder);
    placeholder = "";
  });
};
var addFormValueEventHandler = function() {
  // using the document syntax in case input & container added to DOM dynamically
  $(document).on("blur", "div.input-container :input", function() {
    if ($(this).val()) {
      $(this).closest("div.input-container").addClass("input-has-value");
    } else {
      $(this).closest("div.input-container").removeClass("input-has-value");
    }
  });
};

var initialize = function() {
  addFormFocusEventHandler();
  addFormValueEventHandler();
};

initialize();
label {
  color: transparent;
  display: block;
  width: 100%; /* add this */
}
input[type=text] {
  display: inline-block; /* modify this */
  border-width: 0 0 1px !important;
  border-radius: 0;
  border-style: solid;
  border-color: rgba(0, 0, 0, 0.12);
}
.input-focused:not(.input-invalid) label {
  color: rgb(16, 108, 200);
}
.input-focused:not(.input-invalid) input[type=text] {
  border-color: rgb(16, 108, 200);
}
.input-has-value:not(.input-invalid):not(.input-focused) label {
  color: #595959;
}
.input-invalid.input-focused label,
.input-invalid.input-has-value label {
  color: #ff0000;
}
.input-invalid input[type=text] {
  border-color: #ff0000;
}
.input-invalid input[type=text]::-webkit-input-placeholder {
  color: #ff0000;
}
.input-invalid::after { /* change the selector */
  position: relative; /* add this */
  display: inline-block; /* add this */
  margin-left: -1em; /* add this */
  content: "\2716";  /* "X" */
  font-size: 18px;
  color: #ff0000;
}
.input-valid::after {/* change the seletor */
  position: relative; /* add this */
  display: inline-block; /* add this */
  margin-left: -1em; /* add this */
  content: "\2714";  /* checkmark */
  font-size: 18px;
  color: #438D5B;
}
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row">
    <div class="col-xs-12 input-container input-required">
      <label for="merchantAddress">Merchant Address</label>
      <input type="text" class="full-width" id="merchantAddress" placeholder="Merchant Address" />
    </div>
    <div class="col-xs-12 input-container input-valid">
      <label for="merchantCity">Merchant City</label>
      <input type="text" class="full-width" id="merchantCity" placeholder="Merchant City" value="" />
    </div>
    <div class="col-xs-12 input-container input-invalid">
      <label for="merchantState">Merchant State Code</label>
      <input type="text" class="full-width" id="merchantState" placeholder="Merchant State Code" value="" />
    </div>
    <div class="col-xs-12 input-container input-invalid input-required">
      <label for="merchantZip">Merchant Zip Code</label>
      <input type="text" class="full-width" id="merchantZip" placeholder="Merchant Zip Code" value="Bad Data" />
    </div>
  </div>
</div>

答案 1 :(得分:2)

一旦用户开始在输入框中输入内容,浏览器就会隐藏占位符,并使用它来隐藏你的X.

不幸的是,您不能将其放在输入旁边:after,因为目前不支持。

如果您依次在输入旁边放置X,我建议在输入旁边放置一个div,并在必要时添加/显示X.

否则,我会像移动占位符一样移动X.

在焦点上,您将占位符设置为&#34; &#34;并给标签一个颜色。这使得标签对用户可见并保持占位符存在,X可以是:after。您可以将占位符设置为&#34;&#34;,这将从输入框中删除您的X,但在标签之后添加:after或:before,并在那里显示X.

CSS在标签后显示X

.input-invalid.input-focused label:after,
.input-invalid.input-has-value label:after {
    content: "  \2716";
}