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

如何不使用Material UI库实现类Material UI风格的Select组件

实现Material UI风格的Select组件(无第三方依赖)

这里提供纯React+CSS的实现方案,无需依赖Material UI,可实现聚焦时标签上移至左上角的效果,同时支持默认选中值时标签保持在上方:

import { useState, useEffect } from 'react';
import './CustomSelect.css';

export default function CustomSelect({ placeholder, value, ...props }) {
  const [isFocused, setIsFocused] = useState(false);
  const [hasValue, setHasValue] = useState(!!value);

  // 监听选中值变化,确保有值时标签保持激活状态
  useEffect(() => {
    setHasValue(!!value);
  }, [value]);

  return (
    <div className="select-container">
      <select
        {...props}
        value={value}
        onFocus={() => setIsFocused(true)}
        onBlur={() => setIsFocused(false)}
        className="custom-select"
      />
      <label className={`select-label ${isFocused || hasValue ? 'active' : ''}`}>
        {placeholder}
      </label>
    </div>
  );
}

对应的CSS文件 CustomSelect.css:

.select-container {
  position: relative;
  width: 240px;
  margin: 24px 0;
}

.custom-select {
  width: 100%;
  padding: 14px 10px 8px;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  font-size: 16px;
  background-color: #fff;
  box-sizing: border-box;
  transition: border-color 0.2s ease;
}

.custom-select:focus {
  outline: none;
  border-color: #1976d2; /* 匹配Material UI主色调 */
}

.select-label {
  position: absolute;
  top: 14px;
  left: 10px;
  color: #757575;
  font-size: 16px;
  transition: all 0.2s ease;
  pointer-events: none; /* 避免标签干扰select的点击聚焦 */
  background-color: #fff;
  padding: 0 4px;
}

.select-label.active {
  top: -8px;
  left: 10px;
  font-size: 12px;
  color: #1976d2;
}

关键实现细节

  • 用isFocused跟踪聚焦状态,hasValue判断是否有选中值,确保默认有值时标签不会回到占位位置
  • 标签添加pointer-events: none,防止点击标签时干扰select的聚焦逻辑
  • 给标签设置白色背景,避免移动时与select边框重叠出现视觉断层
  • 过渡动画采用0.2s ease,与Material UI的动画速度保持一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:32:55