39

I am trying to set the Material UI Select component's width. For this, I have to provide a class to the FormControl component, such as mw-120 which links to a CSS class defining the min-width of 120px.

Material UI Select component:

<FormControl className='mw-120'>
    <InputLabel htmlFor='selected-language'>Language</InputLabel>
    <Select value={this.state.selectedLanguage}
            onChange={(e) => this.onLanguageChange(e.target.value)}
            inputProps={{
                name: 'language',
                id: 'selected-language',
            }}>
        {menuItems}
    </Select>
</FormControl>

CSS class:

.mw-120 {
    min-width: 120px;
}

While I would expect the size of the Select component to now have a width of 120px minimum, the component remains exactly the same after rendering, as shown in the following picture. In other words, it is to narrow. The width is not big enough. The width should be greater than the label Language.

width of Select component too small

An element analysis within the Chrome Developer Tools has shown that the main DIV element of that component has a class .MuiFormControl-root-234 that contains min-width: 0;, and it is located/ranked higher than my .mw-120 class. I guess this overrides my .mw-120 class, right? Is there any other way to influence the width of the Material UI Select component? There are no helpful examples of influencing the width of this component on the Material UI Select component page.

Olivier Tassinari
  • 8,238
  • 4
  • 23
  • 23
Socrates
  • 8,724
  • 25
  • 66
  • 113
  • 1
    Your class isn't working because it is higher in the compiled css file. Right solution is to make sure you new class is lower in that file. Or use inline styles and `!important` if your don't care about your project. – Arseniy-II May 14 '19 at 13:16
  • You might want to read this section of the mui docs? https://material-ui.com/customization/components/#1-specific-variation-for-a-one-time-situation – Hans Spieß Apr 04 '21 at 21:11

5 Answers5

44

If you are doing something a one-off styling, you can use the inline style, it worked for me.

<FormControl style={{minWidth: 120}}> // this line
    <InputLabel htmlFor='selected-language'>Language</InputLabel>
    <Select value={this.state.selectedLanguage}
            onChange={(e) => this.onLanguageChange(e.target.value)}
            inputProps={{
                name: 'language',
                id: 'selected-language',
            }}>
        {menuItems}
    </Select>
</FormControl>

enter image description here

If you would reuse it in more code and want to avoid code duplication, you will probably want to work with Themes

Pedro Vieira
  • 2,266
  • 1
  • 20
  • 35
  • 1
    @PedroVieira Thanks, the `style` param does the trick indeed. And you are right about the code duplication. I use SASS for all the styles and I believe that Material UI adds some CSS, too. This leads to the point, that my CSS will always be under the Material UI one, and hence be overwritten. – Socrates May 14 '19 at 18:06
  • 1
    @Socrates the application that I worked on is pretty straight forward, so I never went through that, but maybe you could reduce duplication with themes, as I said, but I don't know if your CSS won't be overwritten this way too – Pedro Vieira May 14 '19 at 18:17
  • 1
    Excellent Pedro. Now, what if I want to use as a % and no a fixed length? ´style={{width:'33%'}} has no effect, and my items alredady have an `xs={4}` atribute – Juan Salvador Dec 16 '19 at 13:58
  • Thanks +1. If not on-off, then also use useStyles https://stackoverflow.com/a/66861308/984471 – Manohar Reddy Poreddy Aug 26 '22 at 03:00
6

For potential re-use, the official doc samples accomplish this with makeStyles like this:

import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles((theme) => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
  },
}));

Then useStyles generates class names like this:

const classes = useStyles();

Then add to your FormControl component like this:

<FormControl className={classes.formControl}>

Demo in Stack Snippets

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

const App = function () {

  const useStyles = makeStyles((theme) => ({
    formControl: {
      margin: theme.spacing(1),
      minWidth: 120,
    },
  }));

  const classes = useStyles();

  return (
    <div className="App">
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-simple-select-label">Age</InputLabel>
        <Select
          labelId="demo-simple-select-label"
          id="demo-simple-select"
          value={''}
        >
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  )
}

ReactDOM.render(
   <App />,
   document.getElementById('root')
);
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@material-ui/core@4.11.3/umd/material-ui.development.js"></script>

<div id="root"></div>
KyleMit
  • 30,350
  • 66
  • 462
  • 664
4

In Material UI v5 you can use the sx prop. Note that the example below uses a select TextField which is essentially the same as Select except that it can display the label and the helper text. See this answer for more detail about how TextField works.

<TextField select label="Select" sx={{ minWidth: 130 }}>
  {currencies.map((option) => (
    <MenuItem key={option.value} value={option.value}>
      {option.label}
    </MenuItem>
  ))}
</TextField>

Codesandbox Demo

Olivier Tassinari
  • 8,238
  • 4
  • 23
  • 23
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
0

In our case selectors .MuiFormControl-root and .mv-120 have the same specificity, so the order in which they are declared matters. Generated styles are injected last in the <head> section of the page, and when custom styles are also placed in this section, they have a lower priority:

const { FormControl, InputLabel, Select, MenuItem } = MaterialUI

const App = function () {
    return (<FormControl className="mw-120">
        <InputLabel id="language-label">Language</InputLabel>
        <Select
            labelId="language-label"
            id="language"
            value="">
            <MenuItem value={"en"}>English</MenuItem>
            <MenuItem value={"de"}>German</MenuItem>
            <MenuItem value={"ru"}>Russian</MenuItem>
        </Select>
    </FormControl>)
}

ReactDOM.render(<App />, document.getElementById('root'))
.mw-120 {
    min-width: 120px;
}
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@material-ui/core@4.11.3/umd/material-ui.development.js"></script>
    
<div id="root"></div>

But when custom styles are in the <body> section, they take precedence:

const { FormControl, InputLabel, Select, MenuItem } = MaterialUI

const App = function () {
    return (<FormControl className="mw-120">
        <InputLabel id="language-label">Language</InputLabel>
        <Select
            labelId="language-label"
            id="language"
            value="">
            <MenuItem value={"en"}>English</MenuItem>
            <MenuItem value={"de"}>German</MenuItem>
            <MenuItem value={"ru"}>Russian</MenuItem>
        </Select>
    </FormControl>)
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@material-ui/core@4.11.3/umd/material-ui.development.js"></script>

<style>
  .mw-120 {
    min-width: 120px;
  }
</style>

<div id="root"></div>

There are other methods to control the placement of generated <style> tags, which are described here.

Spatz
  • 18,640
  • 7
  • 62
  • 66
0

you can use the inline style, it worked for me.

<FormControl size="small" sx={{ width: "100%" }}>
              <InputLabel id="demo-select-small-label">Delay</InputLabel>
              <Select
                labelId="demo-select-small-label"
                id="demo-select-small"
                // value={delay}
                label="Delay"
                // onChange={handleOnDelayChange}
              >
                <MenuItem value={1000}>1 sec</MenuItem>
                <MenuItem value={2000}>2 sec</MenuItem>
                <MenuItem value={3000}>3 sec</MenuItem>
              </Select>
            </FormControl>
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 17 '23 at 01:44