React中Material UI日期选择器空状态显示及自定义样式咨询
Hey there! Let's fix that empty state styling for your DatePicker. The issue usually boils down to overriding Material UI's default input and label behaviors when no date is selected. Here's how you can adjust your implementation to match your desired look:
First, Let's Break Down the Problem
By default, MUI's DatePicker shifts the label upward as soon as the input is focused—even if there's no selected date. To get the empty state you want, we need to control when the label shrinks and refine the input's styling to match your design.
Updated Implementation
We'll use MUI's built-in components and styling tools to get precise control. First, make sure you have the necessary imports:
import { MuiPickersUtilsProvider, DatePicker } from '@material-ui/pickers'; import DateFnsUtils from '@date-io/date-fns'; import { FormControl, InputLabel } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles';
Next, create custom styles tailored to your empty state needs:
const useStyles = makeStyles(() => ({ formControl: { width: '300px', margin: '0 0 16px', }, datepicker: { margin: '2px 0', height: '60px', padding: '20px 15px 10px', borderBottom: '2px solid #e0e0e0', // Replace with your $lightGrey value backgroundColor: '#fff', color: '#2c2c2c', fontWeight: 600, // Style label for empty state '& .MuiInputLabel-root': { transform: 'translate(15px, 25px) scale(1)', transition: 'all 0.2s ease', // Shrink label only when date is selected or input is focused '&.Mui-focused, &.MuiInputLabel-shrink': { transform: 'translate(15px, 10px) scale(0.75)', color: '#2c2c2c', }, }, // Remove MUI's default underline '& .MuiInput-underline': { display: 'none', }, // Adjust input content positioning '& .MuiInputBase-input': { padding: 0, height: 'auto', }, }, }));
Now update your component code to integrate these styles:
const YourComponent = () => { const classes = useStyles(); const [dob, setDob] = useState(null); // Assuming you're using useState for the date return ( <MuiPickersUtilsProvider utils={DateFnsUtils}> <FormControl className={classes.formControl}> {/* Manually control label shrink based on date presence */} <InputLabel shrink={!!dob}>Date of Birth</InputLabel> <DatePicker fullWidth value={dob} label="Date of Birth" format="dd / MM / yyyy" maxDate={new Date()} onChange={(selectedDate) => setDob(selectedDate)} InputProps={{ className: classes.datepicker, disableUnderline: true, // Disable default underline to use your border }} /> </FormControl> </MuiPickersUtilsProvider> ); };
Key Changes Explained
- FormControl & InputLabel: Wrapping with
FormControlgives us better control over label behavior. We setshrink={!!dob}so the label only moves upward when a date is selected. - Custom Label Styling: The
& .MuiInputLabel-rootselector targets the label, setting its default position for empty states and adjusting it when focused or populated. - Disable Default Underline: We turn off MUI's built-in underline to use your custom bottom border.
- Input Padding Fix: Adjusted the input's internal padding to match your CSS without conflicting with MUI's defaults.
If You Prefer Using Your Existing CSS File
If you want to stick with your external CSS instead of makeStyles, update your .datepicker class with these rules:
.datepicker { margin: 2px 0px 2px 0px; height: 60px; width: fit-content; padding: 20px 15px 10px; border-bottom: 2px solid $lightGrey; background-color: #fff; color: #2c2c2c; width: 300px; font-weight: 600; } /* Empty state label position */ .datepicker .MuiInputLabel-root:not(.MuiInputLabel-shrink):not(.Mui-focused) { transform: translate(15px, 25px) scale(1); transition: all 0.2s ease; } /* Label when focused or date selected */ .datepicker .MuiInputLabel-root.MuiInputLabel-shrink, .datepicker .MuiInputLabel-root.Mui-focused { transform: translate(15px, 10px) scale(0.75); color: #2c2c2c; } /* Remove default MUI underline */ .datepicker .MuiInput-underline:before, .datepicker .MuiInput-underline:after { display: none; } /* Adjust input content positioning */ .datepicker .MuiInputBase-input { padding: 0; height: auto; }
Then adjust your component to include the FormControl, InputLabel, and disableUnderline: true as shown in the JSX example above.
This setup will make your empty state match your desired design—with the label sitting inside the input field at the correct position, and shrinking upward only when a date is selected or the input is focused.
内容的提问来源于stack exchange,提问作者Harsh Nagalla

