Content Projection (ng-content)
Pass markup into a component using ng-content, including multi-slot projection with select.
Basic Content Projection
An <ng-content> element inside a component's template marks a spot where the parent can inject its own markup — Angular's equivalent of a slot.
// card.component.ts@Component({ selector: 'app-card', standalone: true, template: ` <div class="card"> <ng-content /> </div> `,})export class CardComponent {}<!-- Parent template --><app-card> <h3>Product Name</h3> <p>Product description goes here.</p></app-card>Multi-Slot Projection with select
Multiple <ng-content> elements, each with a select attribute matching a CSS selector, let a component define several distinct insertion points.
// layout.component.ts@Component({ selector: 'app-layout', standalone: true, template: ` <header><ng-content select="[header]" /></header> <main><ng-content /></main> <footer><ng-content select="[footer]" /></footer> `,})export class LayoutComponent {}<!-- Parent template --><app-layout> <h1 header>My Site</h1> <p>Main page content goes into the default (unselected) slot.</p> <p footer>© 2026</p></app-layout>select="[header]" matches an attribute, but it can just as easily match a tag name (select="h1") or a class (select=".highlight") — whatever CSS selector best identifies the content that belongs in that slot.
Fallback Content
Unlike some frameworks' slot systems, plain <ng-content> does not support inline fallback content directly — if you need a default, conditionally show your own fallback markup based on whether ng-content has projected content, typically checked via a ContentChild query.
Common Beginner Mistakes
If the parent needs to pass arbitrary HTML or components (not just data), ng-content is the right tool — an @Input can only carry data values, not template structure.
Any content that doesn't match a select attribute needs an unselected <ng-content /> present, or it's simply dropped.
FAQs
The default, unselected <ng-content /> is conceptually similar; the select attribute goes further, letting you target multiple distinct insertion points by CSS selector.
Yes — a @ContentChild or @ContentChildren query lets a component inspect or interact with its own projected content programmatically.
Summary
ng-content lets a parent inject markup into specific places inside a child's template, with the select attribute enabling multiple named insertion points. Next, you'll learn the lifecycle hooks available on every Angular component.