React Select auto size width

前端 未结 5 2094
闹比i
闹比i 2020-12-30 06:00

When using react-select it is not auto sizing by option value, but using width:100% as you can see in picture:

Options are short:<

相关标签:
5条回答
  • 2020-12-30 06:37

    SOLUTION 1

    You can leverage React's inline styles by updating the components' width based on the length of the selected option.

    Let me explain further: Say the selected value is HelloWorld. This string is of length 10. We could guess that each character accounts for say 8px each on average (total guess I have no clue at all). Thus, the width of this word is around 8*10=80px, right ? Also, there are some controls after the word (the carret and the cross) and we need some minimum padding: together they may be of 100px width. Then here you have it: your div's width should be ( 8px * 10 letters ) + 100px = 180px.

    More precisely, the correct formula is something like:

    (average_letter_size * selected_value.length) + other_elements_sizes
    

    When selected_value changes, so does its length, and therefore the width of the div gets updated with the new total.

    Example: if the selected value is now Lorem Ipsum dolor sit amet, the length is now 26. By applying the formula we get a larger width of : (8px * 26 letters) + 100px = 308px.

    For this to work in react, here is a snippet:

    <Select
      style={{width: `${(8*this.state.selectedOption2.length) + 100}px`}}            
      className="select-custom-class"
      name="form-field-name"
      value={this.state.selectedOption2}
      options={options2}
      onChange={(value) => { this.setState({ selectedOption2: value.value }); }}
     />
    

    As you can see I added :

    style={{width: `${(8*this.state.selectedOption2.length) + 100}px`}}
    

    to your component. Whenever the state gets updated, everything is propagated including the width of the component.

    See a working example in this fiddle.

    Eventually, you want to fine-tune the rules and averages to your needs. I also suggest you apply a letter size depending on the number of capital and lowercase letters in the selected value.

    SOLUTION 2 (edit)

    I came up with a pure CSS solution if you want. It should be better tested against your design, but this should work:

    // .Select-value comes with an absolute position to stack it below .Select-input
    // we need to scratch that in order for us to be able to let the div grow depending on its content size
    .Select-placeholder, .Select--single > .Select-control .Select-value {
      position: relative;
      padding-left: 0;
    }
    
    // All these 3 classes come with ugly "table" display...
    .Select-control, .Select-clear-zone, .Select-arrow-zone {
      display: inherit;
    }
    
    // here is the trick: we display the wrapper as flex in order to make it fit in height
    // we flip positions of .Select-value and .Select-input using row-reverse in order to have a nice input to the left and no to the right
    .select-custom-class .Select-multi-value-wrapper {
      display: flex;
      flex-direction: row-reverse;
    }
    
    // we put our controls back to a better center position
    .Select-clear-zone {
      position: absolute;
      top: 8px;
      right: 20px;
    }
    
    .Select-arrow-zone {
      position: absolute;
      top: 8px;
      right: 0px;
    }
    

    See a working fiddle (I changed some of the examples for better illustration)

    Tell me what you think. :)

    0 讨论(0)
  • 2020-12-30 06:37

    Inline styles did not work for me. I just wrapped the Select component in a div and gave the div the width I wanted.

    <div style={{width: '300px'}}>
      <Select 
        menuPlacement="auto"
        menuPosition="fixed"
        etc, etc..
      />
    </div>
    
    0 讨论(0)
  • 2020-12-30 06:37

    Update: for people who are using React-Select for a "tags autocomplete" feature but are having trouble where it sets a style width that is too narrow based on the previous tag you searched, this is what works for me:

    Set a style of:

    .myCustomPrefix__value-container > div {
      width: auto !important;
    }
    

    Set classNamePrefix="myCustomPrefix" in the component (docs).


    Old answer:

    See the official docs at https://react-select.com/styles#style-object

    I originally thought that setting width to "auto" for option worked for me:

    const customStyles = {
        option: (styles, { data, isDisabled, isFocused, isSelected }) => {
          return {
            ...styles,
            fontSize: '12px',
            textAlign: 'left',
            width: 'auto',
          }
        },
      }
    
    ...
    
    return (
        //https://react-select.com/props
        <AsyncSelect
          components={animatedComponents}
          isMulti
          // isDisabled={isLoading}
          // isLoading={isLoading}
          onChange={handleChange}
          onInputChange={handleInputChange}
          cacheOptions
          defaultOptions
          defaultMenuIsOpen={false}
          closeMenuOnSelect={closeMenuOnSelect}
          placeholder={placeholder}
          loadOptions={promiseOptions}
          value={selectedOptions}
          styles={customStyles}
          formatOptionLabel={formatOptionLabel}
        />
      )
    
    0 讨论(0)
  • 2020-12-30 06:38

    if you're using react-select v3 you can use customStyles object:

    const customStyles = {
      container: provided => ({
        ...provided,
        width: 150
      })
    };
    
    <Select
        styles={customStyles}
        {...otherProps}
    />
    
    0 讨论(0)
  • 2020-12-30 06:49

    9/2020

    Hey guys :) the solution is so simple than that workarounds !

    the problem in these classes __placeholder, __single-value

    just add this css to both of them and you will get auto sized react-select

    .CUSTOM_PREFIX__single-value,
    .CUSTOM_PREFIX__placeholder {
        position: static;
        top: auto;
        left: auto;
        transform: none;
        max-width: none;
      }
    
    0 讨论(0)
提交回复
热议问题