Manual Setup

If you can't use CLI, follow these steps to manually setup Angular Material and Tailwind CSS in your project.

> If you want to follow CLI setup, go to [CLI Setup](/docs/cli-setup) page. ## 1. Setup styles To easily distinguish between your styles and blocks styles, we recommend to keep them in separate folders, for example: keep below files in `📁src/app/ngm-dev-blocks` folder:
styles/themes/_dark.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/themes ``` **Manual**: ```scss /* To make `color-scheme: dark;` work make sure to have `color-scheme: light;` just before `@include mat.theme` and not `theme-type` in `color` property of `mat.theme` mixin in your @angular/material theme file */ .dark-theme { color-scheme: dark; } ```
styles/themes/_warn_.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/themes ``` **Manual**: ```scss @use '@angular/material' as mat; // In mat-button and some other components, color="warn" is used to indicate urgent or error state. [color='warn'], .warn-theme { @include mat.theme-overrides( ( primary: var(--mat-sys-error), primary-container: var(--mat-sys-error-container), on-primary: var(--mat-sys-on-error), on-primary-container: var(--mat-sys-on-error-container), ) ); } ```
styles/vendors/_tailwind.css
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/vendors ``` **Manual**: ```css @import 'tailwindcss'; /* base for setting the font-families */ @layer base { body { /* same as `plain-family` in angular material */ font-family: var(--mat-sys-body-large-font), sans-serif; /* apply @angular/material's background and foreground colors */ background-color: var(--mat-sys-surface); color: var(--mat-sys-on-surface); } h1, h2, h3, h4, h5, h6 { /* same as `brand-family` in angular material */ font-family: var(--mat-sys-display-large-font), sans-serif; } } @utility form-field-error-icon { vertical-align: bottom; font-variation-settings: 'FILL' 1; height: 16px !important; width: 16px !important; font-size: 16px !important; } @utility icon-filled { font-variation-settings: 'FILL' 1; } /* `.dark-theme` is the class name to enable dark mode in our application */ @custom-variant dark (&:where(.dark-theme, .dark-theme *)); /* `inline` is needed to use the CSS variables in tailwind's @theme */ @theme inline { --color-primary: var(--mat-sys-primary); --color-on-primary: var(--mat-sys-on-primary); --color-primary-container: var(--mat-sys-primary-container); --color-on-primary-container: var(--mat-sys-on-primary-container); --color-secondary: var(--mat-sys-secondary); --color-on-secondary: var(--mat-sys-on-secondary); --color-secondary-container: var(--mat-sys-secondary-container); --color-on-secondary-container: var(--mat-sys-on-secondary-container); --color-tertiary: var(--mat-sys-tertiary); --color-on-tertiary: var(--mat-sys-on-tertiary); --color-tertiary-container: var(--mat-sys-tertiary-container); --color-on-tertiary-container: var(--mat-sys-on-tertiary-container); --color-error: var(--mat-sys-error); --color-on-error: var(--mat-sys-on-error); --color-error-container: var(--mat-sys-error-container); --color-on-error-container: var(--mat-sys-on-error-container); --color-outline: var(--mat-sys-outline); --color-outline-variant: var(--mat-sys-outline-variant); --color-surface: var(--mat-sys-surface); --color-surface-container-highest: var(--mat-sys-surface-container-highest); --color-surface-container-high: var(--mat-sys-surface-container-high); --color-surface-container-medium: var(--mat-sys-surface-container-medium); --color-surface-container-low: var(--mat-sys-surface-container-low); --color-surface-container-lowest: var(--mat-sys-surface-container-lowest); --color-surface-container: var(--mat-sys-surface-container); --color-surface-variant: var(--mat-sys-surface-variant); --color-on-surface-variant: var(--mat-sys-on-surface-variant); --color-on-surface: var(--mat-sys-on-surface); /* same as `plain-family` in angular material */ --font-sans: var(--mat-sys-body-large-font), sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; --font-display: var(--mat-sys-display-large-font), sans-serif; /* angular material radiuses */ --radius-corner-extra-large: var(--mat-sys-corner-extra-large); --radius-corner-extra-small: var(--mat-sys-corner-extra-small); --radius-corner-full: var(--mat-sys-corner-full); --radius-corner-large: var(--mat-sys-corner-large); --radius-corner-medium: var(--mat-sys-corner-medium); --radius-corner-small: var(--mat-sys-corner-small); --radius-mat-card: var( --mdc-outlined-card-container-shape, var(--mat-sys-corner-medium) ); /* angular material font sizes */ /* body */ --text-body-small: var(--mat-sys-body-small-size); --text-body-small--line-height: var(--mat-sys-body-small-line-height); --text-body-small--letter-spacing: var(--mat-sys-body-small-tracking); --text-body-small--font-weight: var(--mat-sys-body-small-weight); --font-body-small: var(--mat-sys-body-small-font); --text-body-medium: var(--mat-sys-body-medium-size); --text-body-medium--line-height: var(--mat-sys-body-medium-line-height); --text-body-medium--letter-spacing: var(--mat-sys-body-medium-tracking); --text-body-medium--font-weight: var(--mat-sys-body-medium-weight); --font-body-medium: var(--mat-sys-body-medium-font); --text-body-large: var(--mat-sys-body-large-size); --text-body-large--line-height: var(--mat-sys-body-large-line-height); --text-body-large--letter-spacing: var(--mat-sys-body-large-tracking); --text-body-large--font-weight: var(--mat-sys-body-large-weight); --font-body-large: var(--mat-sys-body-large-font); /* display */ --text-display-small: var(--mat-sys-display-small-size); --text-display-small--line-height: var(--mat-sys-display-small-line-height); --text-display-small--letter-spacing: var(--mat-sys-display-small-tracking); --text-display-small--font-weight: var(--mat-sys-display-small-weight); --font-display-small: var(--mat-sys-display-small-font); --text-display-medium: var(--mat-sys-display-medium-size); --text-display-medium--line-height: var(--mat-sys-display-medium-line-height); --text-display-medium--letter-spacing: var(--mat-sys-display-medium-tracking); --text-display-medium--font-weight: var(--mat-sys-display-medium-weight); --font-display-medium: var(--mat-sys-display-medium-font); --text-display-large: var(--mat-sys-display-large-size); --text-display-large--line-height: var(--mat-sys-display-large-line-height); --text-display-large--letter-spacing: var(--mat-sys-display-large-tracking); --text-display-large--font-weight: var(--mat-sys-display-large-weight); --font-display-large: var(--mat-sys-display-large-font); /* headline */ --text-headline-small: var(--mat-sys-headline-small-size); --text-headline-small--line-height: var(--mat-sys-headline-small-line-height); --text-headline-small--letter-spacing: var(--mat-sys-headline-small-tracking); --text-headline-small--font-weight: var(--mat-sys-headline-small-weight); --font-headline-small: var(--mat-sys-headline-small-font); --text-headline-medium: var(--mat-sys-headline-medium-size); --text-headline-medium--line-height: var( --mat-sys-headline-medium-line-height ); --text-headline-medium--letter-spacing: var( --mat-sys-headline-medium-tracking ); --text-headline-medium--font-weight: var(--mat-sys-headline-medium-weight); --font-headline-medium: var(--mat-sys-headline-medium-font); --text-headline-large: var(--mat-sys-headline-large-size); --text-headline-large--line-height: var(--mat-sys-headline-large-line-height); --text-headline-large--letter-spacing: var(--mat-sys-headline-large-tracking); --text-headline-large--font-weight: var(--mat-sys-headline-large-weight); --font-headline-large: var(--mat-sys-headline-large-font); /* title */ --text-title-small: var(--mat-sys-title-small-size); --text-title-small--line-height: var(--mat-sys-title-small-line-height); --text-title-small--letter-spacing: var(--mat-sys-title-small-tracking); --text-title-small--font-weight: var(--mat-sys-title-small-weight); --font-title-small: var(--mat-sys-title-small-font); --text-title-medium: var(--mat-sys-title-medium-size); --text-title-medium--line-height: var(--mat-sys-title-medium-line-height); --text-title-medium--letter-spacing: var(--mat-sys-title-medium-tracking); --text-title-medium--font-weight: var(--mat-sys-title-medium-weight); --font-title-medium: var(--mat-sys-title-medium-font); --text-title-large: var(--mat-sys-title-large-size); --text-title-large--line-height: var(--mat-sys-title-large-line-height); --text-title-large--letter-spacing: var(--mat-sys-title-large-tracking); --text-title-large--font-weight: var(--mat-sys-title-large-weight); --font-title-large: var(--mat-sys-title-large-font); /* label */ --text-label-small: var(--mat-sys-label-small-size); --text-label-small--line-height: var(--mat-sys-label-small-line-height); --text-label-small--letter-spacing: var(--mat-sys-label-small-tracking); --text-label-small--font-weight: var(--mat-sys-label-small-weight); --font-label-small: var(--mat-sys-label-small-font); --text-label-medium: var(--mat-sys-label-medium-size); --text-label-medium--line-height: var(--mat-sys-label-medium-line-height); --text-label-medium--letter-spacing: var(--mat-sys-label-medium-tracking); --text-label-medium--font-weight: var(--mat-sys-label-medium-weight); --font-label-medium: var(--mat-sys-label-medium-font); --text-label-large: var(--mat-sys-label-large-size); --text-label-large--line-height: var(--mat-sys-label-large-line-height); --text-label-large--letter-spacing: var(--mat-sys-label-large-tracking); --text-label-large--font-weight: var(--mat-sys-label-large-weight); --font-label-large: var(--mat-sys-label-large-font); /* animations */ /* fade-in */ --animate-fadeIn: fadeIn 300ms ease-in-out forwards var(--animation-delay, 0ms); @keyframes fadeIn { 0% { opacity: 0; transform: translateY(-5px); } 100% { opacity: 1; transform: translateY(0); } } /* marquee */ --animate-marquee: marquee var(--duration, 40s) linear infinite; @keyframes marquee { 0% { transform: translateX(0); } 100% { transform: translateX(calc(-100% - var(--gap, 1rem))); } } --animate-marquee-vertical: marquee-vertical var(--duration, 40s) linear infinite; @keyframes marquee-vertical { 0% { transform: translateY(0); } 100% { transform: translateY(calc(-100% - var(--gap, 1rem))); } } } /* #region: Tailwind X Angular Material fix */ .mdc-notched-outline__notch { border-style: none; } .mat-mdc-icon-button { line-height: 1; } /* #endregion */ ``` Let's break down the file: 1. The `@use 'tailwindcss';` directive imports the tailwindcss styles. 2. The `@layer base` directive sets following: - font-families for the body and heading elements to be the same as the ones in angular material. - background and foreground colors for the body element to be the same as the ones in angular material. 3. The `@utility form-field-error-icon` directive sets the styles for the form-field error icon. 4. The `@utility icon-filled` directive sets the styles for the icon-filled class. 5. The `@theme inline` directive sets the colors, font-families, radiuses to be the same as the ones in angular material. 6. The `@custom-variant dark` directive sets the dark theme class. 7. Few styles are overridden to fix the styles for the Angular Material components.
styles/_base.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/_base ``` **Manual**: ```scss html { background-color: var(--mat-sys-background); color: var(--mat-sys-on-background); } ```
styles/_dialogs.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/_dialogs ``` **Manual**: ```scss @use '@angular/material' as mat; // In responsive mode, the dialog can be full screen. // usage example: // const options: MatDialogConfig = { // maxWidth: isHandset ? '100dvw' : '1024px', // panelClass: 'full-screen-dialog', // }; // if (isHandset) { // options.minWidth = '100dvw'; // options.minHeight = '100dvh'; // } // this.dialog.open(AddApplicationDialogComponent, options); .full-screen-dialog { @media (width < 40rem) { @include mat.dialog-overrides( ( container-shape: 0, ) ); .mat-mdc-dialog-content { // device height - header height -actions height max-height: calc(100dvh - 68px); } } } // As per [Material Design guidelines](https://m3.material.io/components/dialogs/specs), // dialog container should have a surface-container-high color. html { @include mat.dialog-overrides( ( container-color: var(--mat-sys-surface-container-high), ) ); } ```
styles/_sizes.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/_sizes ``` **Manual**: ```scss @use '@angular/material' as mat; $densities: 1, 2, 3, 4, 5; // Density is a utility that is used to set the density of the components. @mixin sizes() { @each $density in $densities { .density-#{$density} { @include mat.theme( ( density: -$density, ) ); mat-slide-toggle button { transform: scale(1 - calc($density / 10)); } } } } html { @include sizes(); } ```
styles/_tabs.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/_tabs ``` **Manual**: ```scss @use '@angular/material' as mat; // As per [Material Design guidelines](https://m3.material.io/components/tabs/specs), // primary tabs should have a 3px height and a 3px 3px 0 0 shape. [fitInkBarToContent], [ng-reflect-fit-ink-bar-to-content='true'] { > .mat-mdc-tab-header { @include mat.tabs-overrides( ( active-indicator-shape: 3px 3px 0 0, active-indicator-height: 3px, ) ); } } ```
styles/ngm-dev-blocks-styles.scss
**CLI (recommended)**: ```bash npx @ngm-dev/cli add styles/ngm-dev-blocks-styles ``` **Manual**: ```scss // this file should be part of your styles array in angular.json @forward './themes/dark'; // get it using `@ngm-dev/cli add styles/theme` @forward './themes/warn'; // get it using `@ngm-dev/cli add styles/theme` @forward './base'; // get it using `@ngm-dev/cli add styles/_base` @forward './dialogs'; // get it using `@ngm-dev/cli add styles/_dialogs` @forward './sizes'; // get it using `@ngm-dev/cli add styles/_sizes` @forward './tabs'; // get it using `@ngm-dev/cli add styles/_tabs` @forward './vendors/tailwind'; // get it using `@ngm-dev/cli add styles/vendors` ```
### 1.2. Setup styles in angular.json Once all the styles are in place, you can setup them in your angular.json file. ```json "styles": [ "src/app/ngm-dev-blocks/styles/ngm-dev-blocks-styles.scss" ] ``` ## 2. Install tailwindcss ```bash npm install tailwindcss @tailwindcss/postcss postcss --force ``` ## 3. Create PostCSS config file Create a `.postcssrc.json` file in the root of your project with below content: ```json // .postcssrc.json { "plugins": { "@tailwindcss/postcss": {} } } ``` ## 4. Install @angular/material > Replace `PROJECT_NAME` with your project name. ```bash ng add @angular/material --theme custom --typography --defaults --project PROJECT_NAME --skip-confirmation --non-interactive ``` For nx projects, you can use the following commands: ```bash npm i @angular/material ``` ```bash npx nx g @angular/material:ng-add --theme custom --typography --defaults --project PROJECT_NAME --skip-confirmation --non-interactive ``` ## 5. Add Material Symbols ### 5.1 Add fonts in index.html ```html ``` ### 5.2 Update app.config.ts to use Material Symbols ```angular-ts import { MAT_ICON_DEFAULT_OPTIONS } from "@angular/material/icon"; export const appConfig: ApplicationConfig = { providers: [ { provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: "material-symbols-outlined", }, }, ], }; ``` > Now you can also use filled variants of the icons by adding `icon-filled` to the class. We have already added this class to `_tailwind.css` file. > > ```html > home > ``` ## 6. Setup `ng2-charts` Some blocks use `ng2-charts` to render charts. If you want to use it in your project, follow the steps below. ### 6.1 Install dependencies ```bash npm install ng2-charts chart.js ``` ### 6.2 Add providers in app.config.ts ```angular-ts app.config.ts import { provideCharts, withDefaultRegisterables } from "ng2-charts"; export const appConfig: ApplicationConfig = { providers: [provideCharts(withDefaultRegisterables())], }; ```
Previous
CLI Setup
Next
CLI API reference
Angular Material Blocks Logo

Angular Material Dev UI (or Angular Material Blocks) is one place stop for developers to explore components and blocks for their Angular Material and Tailwind CSS based applications.

Find us on X (Twitter), LinkedIn, Instagram & Threads