DEV Community

Cover image for Building a Modern Portfolio with Angular 20, Tailwind CSS 4, and Material Design
Prasun Chakraborty
Prasun Chakraborty

Posted on

Building a Modern Portfolio with Angular 20, Tailwind CSS 4, and Material Design

Welcome to our comprehensive course on building modern web applications with Angular 20! In this chapter, we'll create a professional portfolio website that demonstrates the power of combining Angular 20, Angular Material Design, and Tailwind CSS 4.

Our project, karmakanban/devportfolio, will showcase:

  • Modern Angular 20 standalone components
  • Professional Material Design UI components
  • Responsive design with Tailwind CSS 4
  • Theme-driven architecture
  • Dynamic navigation with scroll-based highlighting
  • Responsive, modular, reusable UI components

You can test your knowledge with a small quiz after going through the article, You will find the quiz in the README File

Before we begin, ensure you have:

  • Node.js (v22.16 or higher)
  • npm or yarn package manager
  • Angular CLI (v20+)

Angular CLI

Step 1: Project Setup

1.1 Create New Angular Application

First, let's create a new Angular 20 project:


# Create new Angular project
ng new devportfolio --style=scss --zoneless=false --ssr=false

# Navigate to project directory
cd devportfolio
Enter fullscreen mode Exit fullscreen mode

1.2 Install Angular Material

# Add Angular Material to the project
ng add @angular/material

# Choose the following options:
# - Choose a prebuilt theme: I choose "cyan-orange"
# - Set up global Angular Material typography styles: "Yes"
# - Set up browser animations for Angular Material: "Yes"
Enter fullscreen mode Exit fullscreen mode

1.3 Verify Installation

Check that the following files were updated:

  • angular.json - Material theme and styles added
  • src/styles.scss - Material typography imported
  • src/index.html - Material icons font added

1.4 Install Tailwind CSS 4

# Install Tailwind CSS 4 and PostCSS
npm install tailwindcss @tailwindcss/postcss postcss --force
Enter fullscreen mode Exit fullscreen mode

--force: This is necessary sometimes to resolve peer dependency issues, especially with newer versions of Angular or other libraries, as Angular CLI might have specific peer dependency requirements.

1.5 Configure PostCSS

Create .postcssrc.json in the project root: Tailwind CSS 4 relies on PostCSS for processing.

{
  "plugins": {
    "@tailwindcss/postcss": {}
  }
}
Enter fullscreen mode Exit fullscreen mode

1.6 Update Global Styles

In Tailwind CSS 4, the tailwind.config.js file is no longer required by default. Configuration is now primarily CSS-first. If you want to embrace the new CSS-first approach, you'll manage most of your Tailwind configuration directly in your src/styles.css file, Just like we have done.
Update src/styles.scss

This file serves as the global stylesheet for your Angular application, combining Tailwind CSS, Angular Material theming, and custom utility classes.

  • @use "tailwindcss" imports Tailwind CSS into your project, making all Tailwind utility classes available

  • Basic Styling : Sets the HTML and body elements to take up 100% of viewport height, removes default margin from the body and sets Roboto as the primary font with fallbacks to Helvetica Neue and system sans-serif fonts (added by and standard for Material Design)

html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
Enter fullscreen mode Exit fullscreen mode
  • CSS Custom Properties (Theme Variables): Defines CSS variables in the :root scope (global availability), Includes text color variables for proper contrast on each background
:root {
  /* Primary colors from cyan-orange theme */
  --primary-color: #00bcd4;
  ...
  --warn-text: #ffffff;
}
Enter fullscreen mode Exit fullscreen mode
  • Utility Classes: Uses the CSS variables defined earlier for consistent theming they can be applied directly in HTML templates (e.g. <div class="primary-bg">)
.primary-text { color: var(--primary-color); }
...
.accent-border { border-color: var(--accent-color); }
Enter fullscreen mode Exit fullscreen mode
  • Material Design Token Fallbacks: Provides fallback classes that match Angular Material's naming convention. Ensures compatibility with some Material components that might expect these class names and can be used to override default Material component styling

Step 2: Component Architecture

Components are the main building blocks of Angular applications. Each component represents a part of a larger web page. Organizing an application into components helps provide structure to your project, clearly separating code into specific parts that are easy to maintain and grow over time.

The Angular CLI provides a powerful way to generate components. The basic syntax is: ng generate component <component-name>
or its shorthand: ng g c <component-name>
Let's analyze one of our command that we are going to use:
ng g c features/profile/components/profile-header --flat --skip-tests --inline-template --inline-style
This command creates a component called profile-header in the specified path with several configuration flags.

  • --flat: Creates the component files directly in the specified directory. It doesn't create a dedicated folder for the component. Without this flag, Angular would create a profile-header folder inside components.
  • --skip-tests: Doesn't generate a test file (.spec.ts). It's useful when you're not writing unit tests or will add them later.

  • --inline-template: Places the HTML template directly in the component TypeScript file using template instead of templateUrl. They are good for small templates that don't need separate files

  • --inline-style: Places the CSS styles directly in the component TypeScript file using styles instead of styleUrls. They are also useful for component-specific styles that are short

A component Consists of:

  • A Component decorator that contains configuration used by Angular.
  • An HTML template that controls what renders into the DOM.
  • A CSS selector that defines how the component is used in HTML.
  • A TypeScript class with behaviors, such as handling user input or making requests to a server.

We have divided the portfolio page into 7 component so they can be maintained separately and independently.

Angular Component Infographic

2.1 Create Profile Header Component

ng g c features/profile/components/profile-header --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

Let's Understand the Profile Header Component

  • selector: 'app-profile-header': Defines the HTML tag (<app-profile-header>) to use this component.

  • imports: [MatIconModule]: MatIconModule is directly imported Used in standalone components, which were introduced in Angular 14 and is default since v17

  • ngOnInit(): Lifecycle hook for initialization logic. Runs when the component initializes.

  • ngOnDestroy(): Lifecycle hook for cleanup before component destruction. Not used here but is a good practice.

  • HostListener('window:scroll'): Decorator to listen to DOM events (here, window:scroll). Calls updateActiveSection() to keep activeSection updated.

  • updateActiveSection(): Gets scroll position (window.scrollY). Checks if the scroll position falls within a section’s bounds (offsetTop, offsetHeight). Updates activeSection accordingly.

2.2 Create Profile Hero Component

ng g c features/profile/components/profile-hero --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

Let's Understand the Profile Hero Component
One new concept the button element that wasn't present in the previous ProfileHeader component.

  • MatButtonModule:: Provides Material Design button components. Offers styled, accessible buttons with different variants. mat-raised-button is for contained button with elevation and mat-stroked-button for an outlined button with a border and they uses the theme's primary and accent colors.

2.3 Create Profile About, Profile Skills Component

ng g c features/profile/components/profile-about --flat --skip-tests --inline-template --inline-style
ng g c features/profile/components/profile-skill --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

The Profile About Component
The Profile Skills Component
No new angular concept is introduced in these component.

2.4 Create Profile Projects Component

ng g c features/profile/components/profile-project --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

Let's Understand the Profile Projects Component
One new concept, the button element that weren’t present in the previous components.

  • MatCardModule:: Provides Material Design card components. Wheremat-card is a container element, mat-card-image is a special directive for card images, mat-card-content is for the main content area and mat-card-actions is for the footer area for actions or buttons.

2.5 Create Profile Contact Component

ng g c features/profile/components/profile-contact --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

Let's Understand the Profile Contact Component

Two new concept that weren’t present in the previous components.

  • MatFormFieldModule:: Provides styled form field containers with floating labels. mat-form-field is the container for the label and input. mat-label is the floating label that animates when focused.

  • MatInputModule:: Adds Material Design input fields and textareas. matInput is the material styled input field and textarea supports multiline text input with same material styling

2.6 Create Footer About

ng g c features/profile/components/profile-footer --flat --skip-tests --inline-template --inline-style
Enter fullscreen mode Exit fullscreen mode

The Profile Footer Component
No new angular concept is introduced in these component.

Step 3: Portfolio Page Assembly

Why we structured the project this way

  • Modular Architecture: Each portfolio section is developed independently and can be reused in other contexts also its easier to maintain and update individual sections

  • Performance Benefits: Angular can lazy-load or preload these components independently, change detection is more efficient with component boundaries. We can add routing between sections later

  • Development Workflow: Different team members can work on different sections simultaneously and much easier for testing

  • Future Flexibility: We can easily reorder sections by changing the template or conditionally show/hide sections with *ngIf

3.1 Create Portfolio Page

ng g c features/profile/pages/portfolio/portfolio
Enter fullscreen mode Exit fullscreen mode

The Portfolio Component
The Portfolio Template

This Portfolio component serves as the container/layout component that assembles all the individual profile sections into a complete portfolio page. Each section is designed with alternating background colors (white and subtle gradients) to create visual separation, with a sticky header for persistent navigation

3.2 Update Main App Component

The main AppComponent serves as the root container that initializes and mounts the standalone PortfolioComponent, creating a clean entry point for the Angular application. It follows Angular's best practices by keeping the root minimal and delegating all rendering logic to feature components, enabling future scalability.
The Main Component
The Main Template

Step 4: Assets and Images

Create a public/images/ directory and add your profile and project images. This follows standard web convention where the public folder contains static assets directly accessible via URL.

Congratulations! You've successfully built a modern, professional portfolio website using Angular 20, Material Design, and Tailwind CSS. This project demonstrates modern web development practices by implementing a component-based architecture with standalone components, responsive design, and a clean separation of concerns. This foundation will serve as the basis for more advanced features in the upcoming chapters.

Top comments (0)