34

whilst using the selects from Material UI, I'm struggling to get them working properly using a height and width with 'vh' and 'vw' appropriately and a text-size using 'vh'.

I end up having a proper size for the boxes, but the label text is not centered anymore due to apparently using a 'transform' to offset itself from the top left corner.

Anyway, here's what I have: https://codesandbox.io/s/material-demo-ujz2g

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormHelperText from "@material-ui/core/FormHelperText";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";

const useStyles = makeStyles(theme => ({
  formControl: {
    margin: theme.spacing(1),
    width: "20vw"
  },
  selectEmpty: {
    marginTop: theme.spacing(2)
  },
  select: {
    height: "10vh"
  },
  inputLabel: {
    fontSize: "4vh",
    alignSelf: "center"
  }
}));

export default function SimpleSelect() {
  const classes = useStyles();
  const [age, setAge] = React.useState("");

  const inputLabel = React.useRef(null);
  const [labelWidth, setLabelWidth] = React.useState(0);
  React.useEffect(() => {
    setLabelWidth(inputLabel.current.offsetWidth);
  }, []);

  const handleChange = event => {
    setAge(event.target.value);
  };

  return (
    <div>
      <FormControl variant="outlined" className={classes.formControl}>
        <InputLabel
          className={classes.inputLabel}
          ref={inputLabel}
          id="demo-simple-select-outlined-label"
        >
          Age
        </InputLabel>
        <Select
          className={classes.select}
          labelId="demo-simple-select-outlined-label"
          id="demo-simple-select-outlined"
          value={age}
          onChange={handleChange}
          labelWidth={labelWidth}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
      <FormControl variant="filled" className={classes.formControl}>
        <InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
        <Select
          labelId="demo-simple-select-filled-label"
          id="demo-simple-select-filled"
          value={age}
          onChange={handleChange}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  );
}

const { makeStyles, InputLabel, MenuItem, FormHelperText, FormControl, Select } = MaterialUI;

const useStyles = makeStyles(theme => ({
  formControl: {
    margin: theme.spacing(1),
    width: "20vw"
  },
  selectEmpty: {
    marginTop: theme.spacing(2)
  },
  select: {
    height: "10vh"
  },
  inputLabel: {
    fontSize: "4vh",
    alignSelf: "center"
  }
}));

function SimpleSelect() {
  const classes = useStyles();
  const [age, setAge] = React.useState("");

  const inputLabel = React.useRef(null);
  const [labelWidth, setLabelWidth] = React.useState(0);
  React.useEffect(() => {
    setLabelWidth(inputLabel.current.offsetWidth);
  }, []);

  const handleChange = event => {
    setAge(event.target.value);
  };

  return (
    <div>
      <FormControl variant="outlined" className={classes.formControl}>
        <InputLabel
          className={classes.inputLabel}
          ref={inputLabel}
          id="demo-simple-select-outlined-label"
        >
          Age
        </InputLabel>
        <Select
          className={classes.select}
          labelId="demo-simple-select-outlined-label"
          id="demo-simple-select-outlined"
          value={age}
          onChange={handleChange}
          labelWidth={labelWidth}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
      <FormControl variant="filled" className={classes.formControl}>
        <InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
        <Select
          labelId="demo-simple-select-filled-label"
          id="demo-simple-select-filled"
          value={age}
          onChange={handleChange}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  );
}

ReactDOM.render(<SimpleSelect />, document.querySelector('#root'));
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@material-ui/core@4/umd/material-ui.production.min.js"></script>
<div id="root"></div>

EDIT: the odd behavior is especially visible when zooming in and out - the label itself moves within the dropdown.

Olivier Tassinari
  • 8,238
  • 4
  • 23
  • 23
Bishonen_PL
  • 1,400
  • 4
  • 18
  • 31

4 Answers4

53

Try using size="small" attribute on FormControl

<FormControl variant="filled" size="small">
    <InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
    <Select
      labelId="demo-simple-select-filled-label"
      id="demo-simple-select-filled"
      value={age}
      onChange={handleChange}
    >
      <MenuItem value="">
        <em>None</em>
      </MenuItem>
      <MenuItem value={10}>Ten</MenuItem>
      <MenuItem value={20}>Twenty</MenuItem>
      <MenuItem value={30}>Thirty</MenuItem>
    </Select>
</FormControl>
Nikhil Waykos
  • 784
  • 6
  • 11
  • 1
    One more thing that I usually keep banging against thoo: The content of the `... 1 ` vs ` ` The first code will work with `size='small'` no problem, the second will break the height of the selector because ListItemText has a padding that cares not for the size – Don Kartacs Mar 30 '21 at 10:07
  • @DonKartacs Hey, am not sure about the exact/proper answer to this solution. But to get it to work, you can set the `style` attribute as `style={{margin:-2}}` on ``. Hope this will help you, looking for an alternative way. – Nikhil Waykos Mar 30 '21 at 12:34
26

Instead of declaring FormControl, InputLabel and Select manually and pass the size props to FormControl, you should create a selectable TextField and change the TextField size props.

It's the same as if you define a Select and FormControl but with better integration. Here is a minimal example:

<TextField select size='small' {...}>
  {names.map((name) => (
    <MenuItem key={name} value={name}>
      {name}
    </MenuItem>
  ))}
</TextField>

Live Demo

Edit 59196585/material-ui-select-select-size

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
2

You need to create a file mystyle.css and add the following entry in it. And finally import mystyle.css in your demo.js.

.MuiInputLabel-outlined {
  transform: translate(12px, 14px) scale(1) !important;
}

.MuiInputLabel-outlined.MuiInputLabel-shrink {
  transform: translate(12px, -6px) scale(0.75) !important;
}

Working demo : link

Himanshu Singh
  • 2,117
  • 1
  • 5
  • 15
  • Thanks Himanshu! Unfortunately, the first label still is stuck at the top of the select element (compared to being in the middle as shown in the second one). But even if this would work, it would hard code the translation again, and this would work only on the resolution on which it was set upon, no? – Bishonen_PL Dec 05 '19 at 15:56
  • @Bishonen_PL it will come back to its original position if you select "NONE" from dropdown. Do let me know what exactly do you want. – Himanshu Singh Dec 05 '19 at 15:59
  • Thanks and sorry, I could've stated the question better. The issue is exactly that the label for an not-yet-selected item is not centered. When an item is selected, it was already centered vertically in the codepen I posted, too. – Bishonen_PL Dec 05 '19 at 16:17
2

Try using style attribute on Select

<Select
  labelId="demo-simple-select-filled-label"
  id="demo-simple-select-filled"
  value={age}
  onChange={handleChange}
  style={{ height: 30 }}
>
  <MenuItem value="">
    <em>None</em>
  </MenuItem>
  <MenuItem value={10}>Ten</MenuItem>
  <MenuItem value={20}>Twenty</MenuItem>
  <MenuItem value={30}>Thirty</MenuItem>
</Select>