Mat-select panel min-width

Viewed 15242

I'm trying to customize mat-select with multiple checkboxes. for some reason the panel get wrong min-width as below:

enter image description here

and I don't know where its calculating this min-width. also I tried to add panelClass and override the min-width from this class, for example:

<mat-select #multipleSelect (selectionChange)="selectItem($event.value)" panelClass="multiple-panel" multiple>      

&.multiple-panel {
   min-width: 200px !important;
}

but when opening the dropdown its open with the original width (like in the pic) and after few millisecond"jump" to the custom min-width defined on the panel class.

I find the mat-select very hard to style. anybody knows how to solve this problem?

5 Answers

You can style your mat-select dialog box by giving a panel class (as you mentioned).
Please follow this demo : https://stackblitz.com/edit/angular-matselect-style?file=src/styles.css
to see the styled mat-select components.

Reason :

  • Reason for the delay is that angular for dialog-boxes, create a cdk-overlay-pane inside the cdk-overlay-container container, So in case of mat-select it provides a min-width of 180px, which is overridden by our panel class in the slight delay.
  • Yes, there is a slight delay in opening of dialog box and customizing its width to the specified width provided in the panel class. But the delay is acceptable in the project that i was working on.
    So, you can find the demo for styling the mat-select component, as i have provided 2 components and you can modify any css properties.
  • Try to use styles using ::ng-deep or :host >>>, if not finding any luck,
    please paste the styles in style.css.


Update 1 :
Tried css animations, and opacity for making smooth opening of the mat-select options.

.panel-class-applied-on-mat-select {
  animation-name: opacityDelay !important;
  animation-duration: 0.3s !important;
}

@keyframes opacityDelay {
   0%   {opacity: 0;}
  25%  {opacity: 0;}
  50%  {opacity: 0;}
  75%  {opacity: 0;}
  100% {opacity: 1;}
}

Updated StackBlitz Demo

I used another approach. Just added this piece of code to global style.

.mat-select-panel {
// some your code
  &.ng-animating {
       visibility: hidden;
    }
  }

You can try this solution on DEMO StackBlitz.
Hack with opacity did not fix jumping width when select is closing.

You'll need to change viewEncapsulation to none at your component decorator.and then add following css to remove the transition effect.Have a look at viewencapsulation in angular docs https://angular.io/guide/component-styles#view-encapsulation.

@Component({
selector: 'app-selector',
templateUrl: './template.html',
styleUrls: ['./template.css'],
encapsulation: ViewEncapsulation.None
})
//CSS
.cdk-overlay-connected-position-bounding-box .cdk-overlay-pane .mat-select-panel.ng-animating {
display: none;
}

Try this way : define a panel class for your mat-select in the code and then in the global/app styling file just add:

.panel-class-name .mat-select-panel {
 // add your styling here
}

It worked for me to add some component specific styling for material components.

Please go easy on me S.O. This is my first time contributing. :)

After debugging the console, and running into this issue. Solutions were not clear online. So I'm posting mine here in case someone else runs into this.

I found that there is a width permanently set for the infix class. If you unset it, and optionally add some padding to the right of the value, you'll find that will resolve the issue. Add :host for encapsulation when using ::ng-deep.

Important to Note: ::ng-deep is being permanently deprecated after Angular v14. There is a property in the @Component() annotation called encapsulation which can be used to turn off the view encapsulation for the component instead of using ::ng-deep.

Solution for the deprecation of ::ng-deep:

@Component({
  selector: 'app-selector-name',
  template: `<div>Hello World!</div>`,
  encapsulation: ViewEncapsulation.None,
  styles: [
    `
      :host mat-form-field .mat-form-field-infix {
        width: unset;
      }
      :host mat-form-field .mat-select-value {
        padding-right: 0.5rem; /* 8px */ 
        /* Alternatively, for TailwindCSS: @apply pr-2 */
      }
      :host .random-class {
         /* some encapsulated styling... */
      }
      .another-random-class {
         /* some non-encapsulated styling... */
      }
    `
  ]
})

Solution if you do not care about the deprecation of ::ng-deep:

      :host ::ng-deep mat-form-field .mat-form-field-infix {
        width: unset;
      }
      :host ::ng-deep mat-form-field .mat-select-value {
        padding-right: 0.5rem; /* 8px */
      }
Related