95

How to style mat-select's panel component. From the docs I get that I need to provide panelClass so I make it like this:

<mat-form-field>
  <mat-select placeholder="Search for"
    [(ngModel)]="searchClassVal"
    panelClass="my-select-panel-class"
    (change)="onSearchClassSelect($event)">
    <mat-option *ngFor="let class of searchClasses" [value]="class.value">{{class.name}}</mat-option>
  </mat-select>
</mat-form-field>

I inspected in developer tools that this class is attached to the panel in DOM and it is attached. So I have my custom scss class attached to this element. Now when I provide css it just don't work. My scss for example looks like this:

.my-select-panel-class {
    width:20px;
    max-width:20px;
    background-color: red;
    font-size: 10px;
}

The width of the panel is always equal to the width of the select element. Sometimes In options You have too long strings and I would like to make it a little bit wider. Is there any way how to do this. My style from my component just not working even background-color is not working. Does somebody knows why this behaves so strange?

I'm using: Angular 4.4.5 @angular/material: 2.0.0-beta.12

Vega
  • 27,856
  • 27
  • 95
  • 103
Marcin Kapusta
  • 5,076
  • 3
  • 38
  • 55
  • Is this what you are looking for (I set the width an other value)? https://plnkr.co/edit/gXaf7j6EfWkT3nRMOXOi?p=preview – Vega Oct 16 '17 at 12:09
  • Hey! Thank You for Your example. It actually works but I tried to avoid this kind of solutions with `::ng-deep` because of that: https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep – Marcin Kapusta Oct 16 '17 at 12:14
  • Then you can remove ::ng-deep and set encapsulation: ViewEncapsulation.None :) – Vega Oct 16 '17 at 12:15
  • You know I'm pretty fresh to angular and material design. I came from iOS development. What is encapsulation? Could You point me to some docs? – Marcin Kapusta Oct 16 '17 at 12:17
  • Thank You! Why this is not working when I put my style to the main style.scss file (this style that is not attached to any specific component)? I think I need to be careful with disabling encapsulation because it can affect other components or I'am wrong? – Marcin Kapusta Oct 16 '17 at 12:22
  • Check out this demo: https://plnkr.co/edit/JMhijQ7kPNFGFBspZuEn?p=preview – Vega Oct 16 '17 at 12:29
  • I did it like this: .mat-option-text { font-family: Garamond !important; font-size: 1.8rem !important; font-weight: 800 !important; } – John Gilmer Mar 15 '23 at 14:10

11 Answers11

151

For Angular9+, according to this, you can use:

.mat-select-panel {
    background: red;
    ....
}

Demo


Angular Material uses mat-select-content as class name for the select list content. For its styling I would suggest four options.

1. Use ::ng-deep:

Use the /deep/ shadow-piercing descendant combinator to force a style down through the child component tree into all the child component views. The /deep/ combinator works to any depth of nested components, and it applies to both the view children and content children of the component. Use /deep/, >>> and ::ng-deep only with emulated view encapsulation. Emulated is the default and most commonly used view encapsulation. For more information, see the Controlling view encapsulation section. The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.

CSS:

::ng-deep .mat-select-content{
    width:2000px;
    background-color: red;
    font-size: 10px;   
}

DEMO


2. Use ViewEncapsulation

... component CSS styles are encapsulated into the component's view and don't affect the rest of the application. To control how this encapsulation happens on a per component basis, you can set the view encapsulation mode in the component metadata. Choose from the following modes: .... None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This is essentially the same as pasting the component's styles into the HTML.

None value is what you will need to break the encapsulation and set material style from your component. So can set on the component's selector:

Typscript:

  import {ViewEncapsulation } from '@angular/core';
  ....
  @Component({
        ....
        encapsulation: ViewEncapsulation.None
 })  

CSS

.mat-select-content{
    width:2000px;
    background-color: red;
    font-size: 10px;
}

DEMO


3. Set class style in style.css

This time you have to 'force' styles with !important too.

style.css

 .mat-select-content{
   width:2000px !important;
   background-color: red !important;
   font-size: 10px !important;
 } 

DEMO


4. Use inline style

<mat-option style="width:2000px; background-color: red; font-size: 10px;" ...>

DEMO

Vega
  • 27,856
  • 27
  • 95
  • 103
  • Thank You for response. It is working but I'm wondering why we have this `panelClass` parameter in mat-select element. Is it not working as expected or the purpose of this parameter is something different? – Marcin Kapusta Oct 16 '17 at 14:26
  • Great explanation in which view encapsulation is also explained. One for the docs. Oh, bytheway, what was the SO documentation project called again? Where in the SO documentation can I find the link for it, again? – Michahell Jan 31 '18 at 14:59
  • @Vega font-size changing for options doesn't work correctly because options positioning is calculated with default font size. e.g in your 2nd example try to move select component lower by adding `padding-top:100px` to `.basic-container`. After it select the last option in the list and open dropdown again, as a result the options list will be shown above the select field. – IgorCh Jul 30 '18 at 11:14
  • @MarcinKapusta I believe their intention is for you to use the `ViewEncapsulation`, they use it in their example here: https://material.angular.io/components/select/overview#adding-custom-styles-to-the-dropdown-panel if you go there, click on <> and click on TS – Jared Nov 30 '18 at 07:31
  • Also, another thing I had to do was add quotes in the css class name, like this `[panelClass]="'my-select-panel-class'"` after that, the class was properly assigned, then you just need `ViewEncapsulation` for it to work. :-) – Jared Nov 30 '18 at 07:37
  • 7
    `::ng-deep` is deprecated: https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep Try to use the inputs in the Angular components before messing with ViewEncapsulation & using styles.css. I try to avoid ::ng-deep where possible since it's deprecated, it could be dropped at any point. Although Angular haven't come up with an alternative yet... – RonanCodes Jul 17 '19 at 18:50
  • 1
    @RonanC Not completly and not yet. And because of possible depreciation, I have put more options :) – Vega Jul 17 '19 at 18:53
  • @RonanC, the documentation is little confusing, the deprication doesn't concerne ng-deep, only first two! https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep – Vega Jul 17 '19 at 19:07
  • @Vega All three are deprecated, see: "The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools." I guess browsers will come up with an alternative to shadow piercing and Angular will add something to work with that new thing. – RonanCodes Jul 19 '19 at 15:21
  • @Vega `::ng-deep` is deprecated, but not yet removed. The other options you listed are good though, I do use them when I have no other choice. – RonanCodes Jul 19 '19 at 15:25
  • Unfortunately, this does not work on Angular Material 9, there is no such class as `.mat-select-content`. – Michael May 13 '20 at 08:55
  • @Michael, try .mat-select-panel {background:red}, no ::ng-deep – Vega May 13 '20 at 09:31
8

Put your class name on the mat-form-field element. This works for all inputs.

Lee Grindon
  • 2,117
  • 2
  • 16
  • 8
  • 3
    This works for the input styling, but if you're scoping styling to the class on the `mat-form-field` then you can't style the overlay of `mat-options`. Just a side-note. – kbpontius Jul 24 '19 at 20:17
4

Working solution is by using in-build: panelClass attribute and set styles in global style.css (with !important):

https://material.angular.io/components/select/api

/* style.css */
.matRole .mat-option-text {
  height: 4em !important;
}
<mat-select panelClass="matRole">...
4

I would like to add an explanation to why the options in a select cannot be styled in the standard way, like a mat-form-field, for example.

Elements like the options in a mat-select or a material modal are not inside the angular application, but in a container cdk-overlay-container. The cdk-overlay-container is on the same level as the angular application. So that explains why normal css rules in a component are not applied to the elements.

example from the angular docs

This is why we need to access the class like in @Vega's answer

::ng-deep {
  .mat-option {
    font-family: cursive;
  }
}
Sofía
  • 784
  • 10
  • 24
1

In css copy this code to make 100% width

mat-form-field {
  width: 100%;
}
Kevin Jose
  • 856
  • 8
  • 22
0

Angular material 11.2.6

      <mat-select class="text-sm">
        <mat-option> Text </mat-option>
      </mat-select>

Where text-sm (as of tailwindcss)

.text-sm {
  font-size: 0.875rem; /* 14px */ 
  line-height: 1.25rem; /* 20px */
}
krzyma
  • 5
  • 1
  • 3
Cristian Cimuca
  • 177
  • 1
  • 8
0

Here's a fully fledged solution for styling mat select.

HTML follows:

<mat-form-field class="booking-facility">
  <mat-select disableOptionCentering placeholder="facility" panelClass="booking-facility-select" [ngModel]="facilityId"
                      (ngModelChange)="updateFacility($event)">
    <mat-option *ngFor="let fac of facilities | keyvalue" [value]="fac.value.id">
      <span>{{ fac.value.name | lowercase }}</span>
    </mat-option>
  </mat-select>
</mat-form-field>

SCSS follows (use global stylesheet, namely styles.scss):

.booking-facility-styles {
  font-family: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  letter-spacing: 1px;
  font-size: 22px;
  color: #55595C;
}

.booking-facility {
  // label
  @extend .booking-facility-styles;

  // label
  .mat-form-field-label {
    @extend .booking-facility-styles;
    color: #BBB !important;
  }

  .mat-select-value-text {
    // select
    @extend .booking-facility-styles;
  }
}

.booking-facility-select .mat-option {
  // options
  @extend .booking-facility-styles;
  font-size: 16px !important;
}
danday74
  • 52,471
  • 49
  • 232
  • 283
0

  .mat-form-field .mat-input-element, .mat-form-field .mat-select,
  .mat-form-field.mat-form-field-appearance-legacy .mat-input-element,
  .mat-form-field.mat-form-field-appearance-legacy .mat-select {
    background-color: #0A0A0A !important;

    .mat-select-value {
      color: #fefefe !important;
      font-size: 14px !important;
      font-weight: $font-w-light;
    }
  }
0

In your component, disable styles encapsulation:

@Component({
    selector: 'xxx',
    templateUrl: './xxx.component.html',
    styleUrls: ['./xxx.component.scss'],
    encapsulation: ViewEncapsulation.None
})

For appearance (color/font), use

.mat-select-panel {
   background: red;
}

Having options with very long text, you may want to change width of the list. In such case you should use:

.mat-form-field {
    width: 100%;

    .mat-form-field-infix {
        width: 100%;
    }
}

No !important; css shenanigans required.
(tested with ang12+)

0

For <mat-option> inside <mat-autocomplete> you can set the panelWidth attribute of the autocomplete:

<mat-autocomplete panelWidth="240px">
Russ
  • 623
  • 8
  • 14
0

Can be achieved by adding simple class in mat-option like

<mat-option class="no-hover">Text here</mat-option>

and adding class

.no-hover:hover {
   background-color: red!important;
}

or to be more specific

.no-hover:hover:not(.mat-option-disabled), .no-hover:focus:not(.mat-option-disabled) {
background-color: red;
    color:#909090;
}

Note: If needed use !important to override it

nirmal
  • 2,143
  • 1
  • 19
  • 29