← Back to Articles         
Content Projection in Angular

Content Projection in Angular

Published on 29 Sep 2026     8 min read Angular
Angular Components

What Is Content Projection in Angular?

What is Content Projection?

Content projection is an Angular feature that allows a parent component to provide HTML/content to a child component, and the child decides where that content should appear.

Angular uses:

<ng-content></ng-content>

as the placeholder for the projected content.

In simple terms:

Parent provides the content → Child provides the layout/container.

Parent
   │
   │ HTML / Content
   ▼
Child Component
   │
   │ <ng-content>
   ▼
Rendered UI

A common example is a reusable Card component.


Why Do We Need Content Projection?

Suppose you want one reusable card component, but each card should contain different content:

Card
├── Product information
├── Customer information
├── Employee information
└── Order information

You could create many inputs:

title = input<string>();
description = input<string>();
buttonText = input<string>();

But if the parent needs to provide flexible HTML such as headings, paragraphs, buttons, images, or even other components, creating an input for everything becomes cumbersome.

Content projection allows this:

<app-card>
  <h2>Laptop</h2>
  <p>Price: ₹50,000</p>
  <button>Buy Now</button>
</app-card>

The Card component doesn't need to know what content will be provided.


Purpose

Content projection is mainly used to create flexible and reusable UI/container components.

Common examples:

  • Cards
  • Dialogs
  • Modals
  • Panels
  • Tabs
  • Layout components
  • Form containers
  • Headers and footers
  • Reusable UI libraries

Full Code Example

Let's create a reusable Card component.

Project Structure

src/app/
│
├── app.ts
├── app.html
│
└── card/
    ├── card.ts
    ├── card.html
    └── card.css

card.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: './card.html',
  styleUrl: './card.css'
})
export class Card {
}

card.html

<div class="card">

  <ng-content></ng-content>

</div>

card.css

.card {
  border: 1px solid #ccc;
  padding: 20px;
  margin: 20px;
  border-radius: 8px;
}

app.ts

import { Component } from '@angular/core';
import { Card } from './card/card';

@Component({
  selector: 'app-root',
  imports: [Card],
  templateUrl: './app.html'
})
export class App {
}

app.html

<h1>Products</h1>

<app-card>

  <h2>Laptop</h2>

  <p>Price: ₹50,000</p>

  <p>High-performance business laptop.</p>

  <button>Buy Now</button>

</app-card>

Code Explanation

Step 1 – Parent Provides Content

In app.html:

<app-card>

  <h2>Laptop</h2>

  <p>Price: ₹50,000</p>

  <p>High-performance business laptop.</p>

  <button>Buy Now</button>

</app-card>

Everything between:

<app-card>

and:

</app-card>

is the content provided by the parent.


Step 2 – Child Defines the Projection Location

Inside card.html:

<div class="card">

  <ng-content></ng-content>

</div>

<ng-content> tells Angular:

Insert the content supplied by the parent here.


Step 3 – Angular Projects the Content

Angular effectively produces:

<div class="card">

  <h2>Laptop</h2>

  <p>Price: ₹50,000</p>

  <p>High-performance business laptop.</p>

  <button>Buy Now</button>

</div>

The flow is:

Parent

<app-card>
   <h2>Laptop</h2>
   <p>₹50,000</p>
   <button>Buy Now</button>
</app-card>

             │
             │ Content Projection
             ▼

Child

<div class="card">
   <ng-content></ng-content>
</div>

             │
             ▼

Rendered UI

┌─────────────────────────┐
│ Laptop                  │
│ ₹50,000                 │
│ High-performance laptop │
│                         │
│ [ Buy Now ]             │
└─────────────────────────┘

Types of Content Projection

Angular mainly supports:

  1. Single-slot content projection
  2. Multi-slot content projection

1. Single-Slot Content Projection

Single-slot projection means the child has one location for projected content.

<ng-content></ng-content>

The example above is single-slot projection.

Parent:

<app-card>

  <h2>Laptop</h2>
  <p>₹50,000</p>
  <button>Buy</button>

</app-card>

Child:

<div class="card">

  <ng-content></ng-content>

</div>

Everything is projected into the same location.


2. Multi-Slot Content Projection

Sometimes we want different parent content to appear in different locations.

For example:

Card
│
├── Header
├── Body
└── Footer

We can use multiple <ng-content> elements with select.


Full Multi-Slot Example

card.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: './card.html',
  styleUrl: './card.css'
})
export class Card {
}

card.html

<div class="card">

  <header class="card-header">
    <ng-content select="[card-header]"></ng-content>
  </header>

  <main class="card-body">
    <ng-content select="[card-body]"></ng-content>
  </main>

  <footer class="card-footer">
    <ng-content select="[card-footer]"></ng-content>
  </footer>

</div>

card.css

.card {
  border: 1px solid #ccc;
  padding: 20px;
  border-radius: 8px;
}

.card-header {
  font-weight: bold;
  margin-bottom: 10px;
}

.card-body {
  margin-bottom: 10px;
}

.card-footer {
  margin-top: 10px;
}

app.ts

import { Component } from '@angular/core';
import { Card } from './card/card';

@Component({
  selector: 'app-root',
  imports: [Card],
  templateUrl: './app.html'
})
export class App {
}

app.html

<app-card>

  <h2 card-header>
    Laptop
  </h2>

  <div card-body>
    <p>Price: ₹50,000</p>
    <p>High-performance business laptop.</p>
  </div>

  <div card-footer>
    <button>Buy Now</button>
  </div>

</app-card>

Multi-Slot Code Explanation

The child contains:

<ng-content select="[card-header]"></ng-content>

Angular looks for content matching:

[card-header]

The parent provides:

<h2 card-header>
  Laptop
</h2>

Therefore Angular places it in the header.

Similarly:

<ng-content select="[card-body]"></ng-content>

matches:

<div card-body>

And:

<ng-content select="[card-footer]"></ng-content>

matches:

<div card-footer>

The flow is:

Parent Content                     Child Slot

<h2 card-header>        ────────►  [card-header]

<div card-body>         ────────►  [card-body]

<div card-footer>       ────────►  [card-footer]

Result:

┌────────────────────────────┐
│ Laptop                     │  ← Header
├────────────────────────────┤
│ Price: ₹50,000             │
│ High-performance laptop    │  ← Body
├────────────────────────────┤
│ [ Buy Now ]                │  ← Footer
└────────────────────────────┘

What Does select Do?

The select property determines which parent content should be inserted into a particular <ng-content> slot.

For example:

<ng-content select="[card-header]"></ng-content>

matches:

<h2 card-header>
  Laptop
</h2>

This allows us to create multiple projection locations.


Content Projection vs input()

This is an important distinction.

input()

Use input() when the parent needs to pass data.

Child:

productName = input<string>();

Parent:

<app-product
  [productName]="name">
</app-product>

The child decides how to display the data.


Content Projection

Use content projection when the parent needs to provide UI content/markup.

<app-card>

  <h2>Laptop</h2>

  <p>₹50,000</p>

  <button>Buy</button>

</app-card>

The child decides where the supplied content should appear.

Difference

input() Content Projection
Passes data Projects content
Parent → Child Parent content → Child template
String, number, object, etc. HTML/elements/components
Child controls rendering Parent controls projected markup
input() <ng-content>

Easy way to remember:

input()
   │
   └── Pass DATA


ng-content
   │
   └── Pass CONTENT / UI

Can We Project Angular Components?

Yes.

Projected content doesn't have to be plain HTML.

For example:

<app-card>

  <app-product-details>
  </app-product-details>

</app-card>

Child:

<div class="card">

  <ng-content></ng-content>

</div>

So you can project:

  • HTML
  • Buttons
  • Forms
  • Angular components
  • Other UI content

Real-World Example

A reusable dialog component might define:

Dialog
│
├── Title
├── Body
└── Actions

The dialog controls the layout:

<div class="dialog">

  <ng-content select="[dialog-title]"></ng-content>

  <ng-content select="[dialog-body]"></ng-content>

  <ng-content select="[dialog-actions]"></ng-content>

</div>

The parent controls the actual content:

<app-dialog>

  <h2 dialog-title>
    Delete Product
  </h2>

  <p dialog-body>
    Are you sure you want to delete this product?
  </p>

  <div dialog-actions>
    <button>Cancel</button>
    <button>Delete</button>
  </div>

</app-dialog>

This is one of the main real-world uses of content projection.


Advantages

1. Reusable Components

The same component can contain different content:

<app-card>
  Product Content
</app-card>

<app-card>
  Customer Content
</app-card>

2. Flexible UI

The parent can provide arbitrary markup rather than being limited to predefined input values.

3. Cleaner Components

You don't need to create an input for every possible piece of UI content.

4. Separation of Responsibilities

Child  → Controls layout/container

Parent → Controls projected content

5. Multiple Slots

A component can expose separate locations for:

Header
Body
Footer
Actions

Disadvantages

1. Can Become Complex

Many projection slots can make a component difficult to understand.

2. Less Structured Than Inputs

An input can provide a strongly typed contract:

product = input.required<Product>();

Projected HTML is more flexible but less structured.

3. Not Needed for Simple Data

If the child only needs:

Product Name
Price
ID

normal input() properties are usually simpler.

4. Overuse Can Hurt Maintainability

Content projection should be used when UI flexibility is required, not as a replacement for every component input.


Key Points

  • Content projection allows a parent to provide content/UI to a child.
  • Angular uses:
<ng-content></ng-content>
  • The parent places content between the component tags:
<app-card>
  <h2>Laptop</h2>
</app-card>
  • The child decides where it appears:
<div>
  <ng-content></ng-content>
</div>
  • Single-slot projection uses one <ng-content>.
  • Multi-slot projection uses multiple <ng-content> elements with select.
  • input() is mainly for data.
  • <ng-content> is mainly for content/UI markup.
  • It is commonly used for cards, dialogs, panels, tabs, and reusable layout components.

Interview Questions & Answers

Q1. What is content projection in Angular?

Content projection allows a parent component to provide HTML or component content to a child component. The child uses <ng-content> to specify where that content should be rendered.


Q2. What is <ng-content>?

<ng-content> is an Angular placeholder that defines where content supplied by a parent should appear inside a child component's template.

<div>
  <ng-content></ng-content>
</div>

Q3. What is single-slot content projection?

Single-slot projection uses one:

<ng-content></ng-content>

All applicable parent content is projected into that location.


Q4. What is multi-slot content projection?

Multi-slot projection allows different pieces of content to be placed in different locations using select.

<ng-content select="[header]"></ng-content>

<ng-content select="[body]"></ng-content>

<ng-content select="[footer]"></ng-content>

Q5. What does select do?

select specifies which projected content should go into a particular slot.

<ng-content select="[card-header]"></ng-content>

matches:

<h2 card-header>Laptop</h2>

Q6. What is the difference between input() and content projection?

input() passes data:

<app-product
  [product]="selectedProduct">
</app-product>

Content projection passes UI content:

<app-card>
  <h2>Laptop</h2>
  <button>Buy</button>
</app-card>

Q7. Can Angular components be projected?

Yes. Content projection can project plain HTML as well as Angular components.

<app-card>
  <app-product-details></app-product-details>
</app-card>

Q8. Where is content projection commonly used?

It is commonly used when building reusable:

  • Cards
  • Dialogs/modals
  • Panels
  • Tabs
  • Layout containers
  • UI library components

Interview-Ready Answer

Content projection is an Angular feature that allows a parent component to provide HTML or component content to a child component. The child uses <ng-content> as a placeholder to determine where the supplied content is rendered. Angular supports single-slot and multi-slot projection, with the select attribute used to route content to specific slots. It is commonly used to build reusable cards, dialogs, panels, and layout components.

← Back to Articles