删除 "required" 标签时无法正常工作

On remove "required" label not working properly

Codepen: link


.body {
  position: relative;
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}

.wrap {
  position: absolute;
  right: 0;
  top: 40%;
  width: 350px;
  left: 0;
  margin: 0 auto;
}


/* select starting stylings ------------------------------*/

.select {
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
  position: relative;
  width: 350px;
}

.select-text {
  position: relative;
  font-family: inherit;
  background-color: transparent;
  width: 350px;
  padding: 10px 10px 10px 0;
  font-size: 18px;
  border-radius: 0;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}


/* Remove focus */

.select-text:focus {
  outline: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0);
}


/* Use custom arrow */

.select .select-text {
  appearance: none;
  -webkit-appearance: none
}

.select:after {
  position: absolute;
  top: 18px;
  right: 10px;
  /* Styling the down arrow */
  width: 0;
  height: 0;
  padding: 0;
  content: '';
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid rgba(0, 0, 0, 0.12);
  pointer-events: none;
}


/* LABEL ======================================= */

.select-label {
  color: rgba(0, 0, 0, 0.26);
  font-size: 18px;
  font-weight: normal;
  position: absolute;
  pointer-events: none;
  left: 0;
  top: 10px;
  transition: 0.2s ease all;
}


/* active state */

.select-text:focus~.select-label,
.select-text:valid~.select-label {
  color: #2F80ED;
  top: -20px;
  transition: 0.2s ease all;
  font-size: 14px;
}


/* BOTTOM BARS ================================= */

.select-bar {
  position: relative;
  display: block;
  width: 350px;
}

.select-bar:before,
.select-bar:after {
  content: '';
  height: 2px;
  width: 0;
  bottom: 1px;
  position: absolute;
  background: #2F80ED;
  transition: 0.2s ease all;
}

.select-bar:before {
  left: 50%;
}

.select-bar:after {
  right: 50%;
}


/* active state */

.select-text:focus~.select-bar:before,
.select-text:focus~.select-bar:after {
  width: 50%;
}


/* HIGHLIGHTER ================================== */

.select-highlight {
  position: absolute;
  height: 60%;
  width: 100px;
  top: 25%;
  left: 0;
  pointer-events: none;
  opacity: 0.5;
}
<html>
<head>
</head>
<body>
  <div class="wrap">
    <!--Select with pure css-->
    <div class="select">
      <select class="select-text" required>
        <option value="" disabled selected></option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <span class="select-highlight"></span>
      <span class="select-bar"></span>
      <label class="select-label">Select</label>
    </div>
    <!--Select with pure css-->

  </div>
</body>

</html>

<select>required 时,它工作正常。

但问题是,当我删除 "required" 时,它是没有选中选项的浮动标签。

在这种情况下如何维护浮动标签?
我错过了什么?还是我们需要 JavaScript?

所以想法是当标签为空时不要浮动。

我使用

解决了 input 问题

我从这个改的

.select-text:focus~.select-label,
.select-text:valid~.select-label {

/* your code */

}

至此

.select-text:focus~.select-label {
    
/* your code */

}

现在可以使用了,这里是固定代码:

.body {
  position: relative;
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}

.wrap {
  position: absolute;
  right: 0;
  top: 40%;
  width: 350px;
  left: 0;
  margin: 0 auto;
}


/* select starting stylings ------------------------------*/

.select {
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
  position: relative;
  width: 350px;
}

.select-text {
  position: relative;
  font-family: inherit;
  background-color: transparent;
  width: 350px;
  padding: 10px 10px 10px 0;
  font-size: 18px;
  border-radius: 0;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}


/* Remove focus */

.select-text:focus {
  outline: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0);
}


/* Use custom arrow */

.select .select-text {
  appearance: none;
  -webkit-appearance: none
}

.select:after {
  position: absolute;
  top: 18px;
  right: 10px;
  /* Styling the down arrow */
  width: 0;
  height: 0;
  padding: 0;
  content: '';
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid rgba(0, 0, 0, 0.12);
  pointer-events: none;
}


/* LABEL ======================================= */

.select-label {
  color: rgba(0, 0, 0, 0.26);
  font-size: 18px;
  font-weight: normal;
  position: absolute;
  pointer-events: none;
  left: 0;
  top: 10px;
  transition: 0.2s ease all;
}


/* active state, where I changed */

.select-text:focus~.select-label {
  color: #2F80ED;
  top: -20px;
  transition: 0.2s ease all;
  font-size: 14px;
}


/* BOTTOM BARS ================================= */

.select-bar {
  position: relative;
  display: block;
  width: 350px;
}

.select-bar:before,
.select-bar:after {
  content: '';
  height: 2px;
  width: 0;
  bottom: 1px;
  position: absolute;
  background: #2F80ED;
  transition: 0.2s ease all;
}

.select-bar:before {
  left: 50%;
}

.select-bar:after {
  right: 50%;
}


/* active state */

.select-text:focus~.select-bar:before,
.select-text:focus~.select-bar:after {
  width: 50%;
}


/* HIGHLIGHTER ================================== */

.select-highlight {
  position: absolute;
  height: 60%;
  width: 100px;
  top: 25%;
  left: 0;
  pointer-events: none;
  opacity: 0.5;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="wrap">
    <!--Select with pure css-->
    <div class="select">
      <select class="select-text">
        <option value="" disabled selected></option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <span class="select-highlight"></span>
      <span class="select-bar"></span>
      <label class="select-label">Select</label>
    </div>
    <!--Select with pure css-->
  </div>
</body>

</html>

它按预期工作。

<select>required 时,它工作正常。

这是因为这种风格 .select-text:valid ~ .select-label

当select为required时,如果你select第一个值为null的选项,那么你的select无效,css 样式 .select-text:valid ~ .select-label 不起作用,这意味着您的标签将是灰色的。如果 select 不是 required,那么如果您 select 第一个选项,则 .select-text 将处于有效状态,并且将应用样式 .select-text:valid ~ .select-label , 这使得标签变小变蓝。

要解决这个问题,我们必须使用 css + javascript 解决方案。

我已经参考this答案实现了解决方案。

工作解决方案

.body {
  position: relative;
  font-family:
    'Roboto','Helvetica','Arial',sans-serif;
}

.wrap {
  position: absolute;
  right: 0;
  top: 40%;
  width: 350px;
  left: 0;
  margin: 0 auto;
}

/* select starting stylings ------------------------------*/
.select {
  font-family:
    'Roboto','Helvetica','Arial',sans-serif;
    position: relative;
    width: 350px;
}

.select-text {
    position: relative;
    font-family: inherit;
    background-color: transparent;
    width: 350px;
    padding: 10px 10px 10px 0;
    font-size: 18px;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid rgba(0,0,0, 0.12);
}

/* Remove focus */
.select-text:focus {
    outline: none;
    border-bottom: 1px solid rgba(0,0,0, 0);
}

    /* Use custom arrow */
.select .select-text {
    appearance: none;
    -webkit-appearance:none
}

.select:after {
    position: absolute;
    top: 18px;
    right: 10px;
    /* Styling the down arrow */
    width: 0;
    height: 0;
    padding: 0;
    content: '';
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 6px solid rgba(0, 0, 0, 0.12);
    pointer-events: none;
}


/* LABEL ======================================= */


/* active state */
.select-text:focus ~ .select-label,
.select-text:valid ~ .select-label {
    color: #2F80ED;
    top: -20px;
    transition: 0.2s ease all;
    font-size: 14px;
}

.select-label,
.select-text[data-chosen=''] ~ .select-label {
    color: rgba(0,0,0, 0.26);
    font-size: 18px;
    font-weight: normal;
    position: absolute;
    pointer-events: none;
    left: 0;
    top: 10px;
    transition: 0.2s ease all;
}



/* BOTTOM BARS ================================= */
.select-bar {
    position: relative;
    display: block;
    width: 350px;
}

.select-bar:before, .select-bar:after {
    content: '';
    height: 2px;
    width: 0;
    bottom: 1px;
    position: absolute;
    background: #2F80ED;
    transition: 0.2s ease all;
}

.select-bar:before {
    left: 50%;
}

.select-bar:after {
    right: 50%;
}

/* active state */
.select-text:focus ~ .select-bar:before, .select-text:focus ~ .select-bar:after {
    width: 50%;
}

/* HIGHLIGHTER ================================== */
.select-highlight {
    position: absolute;
    height: 60%;
    width: 100px;
    top: 25%;
    left: 0;
    pointer-events: none;
    opacity: 0.5;
}
<div class="wrap">

<!--Select with pure css-->
  <div class="select">
      <select class="select-text" onchange="this.dataset.chosen = this.value; ">
        <option value="" selected></option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <span class="select-highlight"></span>
      <span class="select-bar"></span>
      <label class="select-label">Please Select</label>
    </div>
<!--Select with pure css-->

</div>

只需删除 :valid select或者,如果不需要输入,则 valid 始终为真。

删除后:

.select-text:valid ~ .select-label

如果用户 select 有选择,您将面临另一个问题,即在删除 :focus 后保持标签。

因此您需要添加 onchange 事件

onchange="this.dataset.chosen=this.value;"

然后,如果用户select编辑了选项,您可以轻松地保留标签。

.select-text[data-chosen] ~.select-label

这样,如果 select 有值,标签就会保持不变。

它变成如下片段:

.body {
  position: relative;
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}

.wrap {
  position: absolute;
  right: 0;
  top: 40%;
  width: 350px;
  left: 0;
  margin: 0 auto;
}


/* select starting stylings ------------------------------*/

.select {
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
  position: relative;
  width: 350px;
}

.select-text {
  position: relative;
  font-family: inherit;
  background-color: transparent;
  width: 350px;
  padding: 10px 10px 10px 0;
  font-size: 18px;
  border-radius: 0;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}


/* Remove focus */

.select-text:focus {
  outline: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0);
}


/* Use custom arrow */

.select .select-text {
  appearance: none;
  -webkit-appearance: none
}

.select:after {
  position: absolute;
  top: 18px;
  right: 10px;
  /* Styling the down arrow */
  width: 0;
  height: 0;
  padding: 0;
  content: '';
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid rgba(0, 0, 0, 0.12);
  pointer-events: none;
}


/* LABEL ======================================= */

.select-label {
  color: rgba(0, 0, 0, 0.26);
  font-size: 18px;
  font-weight: normal;
  position: absolute;
  pointer-events: none;
  left: 0;
  top: 10px;
  transition: 0.2s ease all;
}


/* active state */

.select-text:focus~.select-label,
.select-text[data-chosen] ~.select-label{
  color: #2F80ED;
  top: -20px;
  transition: 0.2s ease all;
  font-size: 14px;
}


/* BOTTOM BARS ================================= */

.select-bar {
  position: relative;
  display: block;
  width: 350px;
}

.select-bar:before,
.select-bar:after {
  content: '';
  height: 2px;
  width: 0;
  bottom: 1px;
  position: absolute;
  background: #2F80ED;
  transition: 0.2s ease all;
}

.select-bar:before {
  left: 50%;
}

.select-bar:after {
  right: 50%;
}


/* active state */

.select-text:focus~.select-bar:before,
.select-text:focus~.select-bar:after {
  width: 50%;
}


/* HIGHLIGHTER ================================== */

.select-highlight {
  position: absolute;
  height: 60%;
  width: 100px;
  top: 25%;
  left: 0;
  pointer-events: none;
  opacity: 0.5;
}
<html>
<head>
</head>
<body>
  <div class="wrap">
    <!--Select with pure css-->
    <div class="select">
      <select class="select-text" onchange="this.dataset.chosen=this.value;">
        <option value="" disabled selected></option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <span class="select-highlight"></span>
      <span class="select-bar"></span>
      <label class="select-label">Select</label>
    </div>
    <!--Select with pure css-->

  </div>
</body>

</html>

编辑:

如果用户 select 的空选项,标签下来,这个新的解决方案有效,

我只是添加了空值 select 或者为了保持标签向上, 并在 select 更改时添加了一个 blur() 事件以平滑所有内容。

查看代码片段:

.body {
  position: relative;
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}

.wrap {
  position: absolute;
  right: 0;
  top: 40%;
  width: 350px;
  left: 0;
  margin: 0 auto;
}


/* select starting stylings ------------------------------*/

.select {
  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
  position: relative;
  width: 350px;
}

.select-text {
  position: relative;
  font-family: inherit;
  background-color: transparent;
  width: 350px;
  padding: 10px 10px 10px 0;
  font-size: 18px;
  border-radius: 0;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}


/* Remove focus */

.select-text:focus {
  outline: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0);
}


/* Use custom arrow */

.select .select-text {
  appearance: none;
  -webkit-appearance: none
}

.select:after {
  position: absolute;
  top: 18px;
  right: 10px;
  /* Styling the down arrow */
  width: 0;
  height: 0;
  padding: 0;
  content: '';
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid rgba(0, 0, 0, 0.12);
  pointer-events: none;
}


/* LABEL ======================================= */

.select-label,select.select-text[data-chosen=""] ~.select-label {
  color: rgba(0, 0, 0, 0.26);
  font-size: 18px;
  font-weight: normal;
  position: absolute;
  pointer-events: none;
  left: 0;
  top: 10px;
  transition: 0.2s ease all;
}


/* active state */

select.select-text:focus~.select-label,
.select-text[data-chosen] ~.select-label{
  color: #2F80ED;
  top: -20px;
  transition: 0.2s ease all;
  font-size: 14px;
}


/* BOTTOM BARS ================================= */

.select-bar {
  position: relative;
  display: block;
  width: 350px;
}

.select-bar:before,
.select-bar:after {
  content: '';
  height: 2px;
  width: 0;
  bottom: 1px;
  position: absolute;
  background: #2F80ED;
  transition: 0.2s ease all;
}

.select-bar:before {
  left: 50%;
}

.select-bar:after {
  right: 50%;
}


/* active state */

.select-text:focus~.select-bar:before,
.select-text:focus~.select-bar:after {
  width: 50%;
}


/* HIGHLIGHTER ================================== */

.select-highlight {
  position: absolute;
  height: 60%;
  width: 100px;
  top: 25%;
  left: 0;
  pointer-events: none;
  opacity: 0.5;
}
<html>
<head>
</head>
<body>
  <div class="wrap">
    <!--Select with pure css-->
    <div class="select">
      <select class="select-text" onchange="this.dataset.chosen=this.value;this.blur();">
        <option value="" selected></option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <span class="select-highlight"></span>
      <span class="select-bar"></span>
      <label class="select-label">Select</label>
    </div>
    <!--Select with pure css-->

  </div>
</body>

</html>