You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/TS表单中实现输入框标签双场景移位的CSS问题

React/TS表单标签移位问题解决:输入框有内容时的标签定位

问题背景

需要实现输入框标签在两种场景下移位:

  • 输入框获得焦点时
  • 输入框有内容(占位符未显示)时

目前焦点触发的移位已经通过.grid__item--fixedrowcolone实现,但输入框有内容时的场景始终无法生效。输入框与标签作为网格元素重叠放置且默认垂直居中,之前尝试了多种选择器变体都没成功,比如:

.grid__item--fixedrowcolone {
  &:not(~ .form__inputfield:placeholder-shown) {
    color: green;
  }
}

相关代码

React表单组件代码

<div className={styles.form__inputwrapper} data-testid='form-input'>
  <div className={styles.form__inputsymbol} data-testid='form-input-icon'>
    <img src={lockSvg} alt='lock' width='24' height='24' />
  </div>
  <div className={styles.grid__container} data-testid='form-input-field'>
    <div className={styles['grid__item--fixedrowcolone']}>
      <input
        className={styles.form__inputfield}
        type='text'
        pattern='^.*{8,}'
        id='pwd1'
        name='pwd1'
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder=' '
        required
        data-testid='forminput-input'
      />
    </div>

    <div className={styles['grid__item--fixedrowcoltwo']}>
      <label
        className={styles.form__inputlabel}
        htmlFor='pwd1'
        data-testid='forminput-inputlabel'
      >
        wachtwoord
        <span className={styles.form__inputlabelvalmsg}>
          +312234
        </span>
      </label>
    </div>
  </div>
</div>

CSS Module SCSS代码

.grid {
  &__container {
    display: grid;
    justify-items: stretch;
  }

  &__item {
    &--fixedrowcolone, &--fixedrowcoltwo {
      display: flex;
      grid-column: 1;
      grid-row: 1;
    }
  }
}

.form {
  &__inputwrapper {
    display: flex;
    margin-bottom: 10px;
    position: relative;
    background: var(--theme_form_field_bg_color);
    border-radius: 4px;
  }

  &__inputsymbol {
    display: flex;
    align-self: center;
    padding-left: 10px;
    pointer-events: none;
    color: var(--theme_fg_color);
    font-size: 1.5em;
    transition: all 0.4s;
    filter: var(--theme_fg_color_filter)
  }

  &__inputfield {
    align-self: center;
    font-size: 1.5em;
    height: 50px;
    color: var(--theme_fg_color);
    background: none;
    outline: none;
    border: none;
    max-width: 280px;
    min-width: 250px;
    overflow: visible;
    touch-action: manipulation;
  }

  &__inputlabel {
    align-self: center;
    font-size: 1.5em;
    transition: .3s all ease;
  }

  &__inputlabelvalmsg {
    display: none;
  }
}

.grid__item--fixedrowcolone {
  &:focus-within ~ .grid__item--fixedrowcoltwo {
    top: 5px;
    font-size: .5em;
    align-self: start;
  }
}

问题分析

之前的选择器错误在于:

  1. .form__inputfield是.grid__item--fixedrowcolone的子元素,不是兄弟元素,所以~兄弟选择器完全不生效
  2. 需要控制的目标是.grid__item--fixedrowcoltwo里的标签,而不是.grid__item--fixedrowcolone本身

另外,输入框的placeholder=' '设置是对的——当输入内容后,占位符会隐藏,:placeholder-shown伪类会失效,这个逻辑没问题。

解决方案

利用CSS的:has()伪类(现代浏览器均支持),让.grid__item--fixedrowcolone根据子元素输入框的状态,控制兄弟元素.grid__item--fixedrowcoltwo的样式。同时需要给.grid__item--fixedrowcoltwo添加相对定位,确保top属性生效。

修改后的SCSS代码

首先给标签所在的网格项添加相对定位:

.grid__item--fixedrowcoltwo {
  position: relative;
}

然后更新聚焦和内容触发的样式规则:

.grid__item--fixedrowcolone {
  // 输入框聚焦时移位
  &:focus-within ~ .grid__item--fixedrowcoltwo,
  // 输入框有内容(占位符未显示)时移位
  &:has(.form__inputfield:not(:placeholder-shown)) ~ .grid__item--fixedrowcoltwo {
    top: 5px;
    font-size: .5em;
    align-self: start;
  }
}

效果验证

  • 输入框聚焦时:标签正常移位
  • 输入框输入内容后:即使失去焦点,标签也保持移位状态
  • 清空输入框:标签回到默认垂直居中位置

内容的提问来源于stack exchange,提问作者pcvnes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:40:31