Angular Component Styling
When building Angular applications, styling your components properly is crucial for creating visually appealing and user-friendly interfaces. Angular provides several powerful options for styling components that help maintain style isolation and organization.
Introduction to Component Styling
Angular components are self-contained units with their own templates, logic, and styles. This encapsulation makes it easier to develop and maintain components independently. When it comes to styling, Angular provides different ways to add CSS to your components:
- Inline styles
- Component-specific stylesheets
- Global stylesheets
- Style encapsulation options
Let's dive into each approach and understand when to use them.
Component-Specific Stylesheets
The most common way to style an Angular component is by using component-specific stylesheets defined in the component decorator.
Basic Component Styling Example
import { Component } from '@angular/core';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.css']
})
export class ButtonComponent {
// Component logic
}
In button.component.css
:
.custom-button {
background-color: #3498db;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.custom-button:hover {
background-color: #2980b9;
}
In button.component.html
:
<button class="custom-button">Click Me!</button>
This approach keeps styles scoped to the component, preventing them from affecting other parts of your application.
Inline Styles
For simple components or when you need to define styles programmatically, you can use inline styles directly in the component decorator:
@Component({
selector: 'app-info-card',
template: `
<div class="info-card">
<h2>{{ title }}</h2>
<p>{{ content }}</p>
</div>
`,
styles: [`
.info-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
margin: 10px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
h2 {
color: #333;
margin-top: 0;
}
p {
color: #666;
}
`]
})
export class InfoCardComponent {
@Input() title: string = 'Information';
@Input() content: string = 'No content available';
}
Style Encapsulation
One of Angular's powerful features is style encapsulation, which prevents styles from one component affecting other components. Angular provides three encapsulation strategies:
1. Emulated (Default)
This is the default mode where Angular adds unique attributes to component elements and prefixes CSS selectors with these attributes.
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css'],
encapsulation: ViewEncapsulation.Emulated // This is default
})
export class ProfileComponent { }
2. None
With this mode, styles are not encapsulated and are applied globally.
@Component({
selector: 'app-global-styles',
templateUrl: './global-styles.component.html',
styleUrls: ['./global-styles.component.css'],
encapsulation: ViewEncapsulation.None
})
export class GlobalStylesComponent { }
3. ShadowDom
This uses the browser's native Shadow DOM to encapsulate styles completely, creating a true style boundary.
@Component({
selector: 'app-isolated',
templateUrl: './isolated.component.html',
styleUrls: ['./isolated.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class IsolatedComponent { }
Don't forget to import ViewEncapsulation from @angular/core when using these encapsulation modes:
import { Component, ViewEncapsulation } from '@angular/core';
Dynamic Styling with [ngClass] and [ngStyle]
Angular provides directives for applying styles dynamically based on component state.
ngClass Example
@Component({
selector: 'app-task-item',
template: `
<div
class="task-item"
[ngClass]="{'completed': isCompleted, 'priority-high': isPriority}"
(click)="toggleComplete()"
>
{{ taskName }}
</div>
`,
styles: [`
.task-item {
padding: 10px;
margin: 5px 0;
background-color: #f5f5f5;
border-left: 4px solid #ddd;
}
.completed {
text-decoration: line-through;
opacity: 0.7;
border-left-color: #4CAF50;
}
.priority-high {
border-left-color: #F44336;
}
`]
})
export class TaskItemComponent {
@Input() taskName: string = '';
@Input() isPriority: boolean = false;
isCompleted: boolean = false;
toggleComplete() {
this.isCompleted = !this.isCompleted;
}
}
ngStyle Example
@Component({
selector: 'app-progress-bar',
template: `
<div class="progress-container">
<div
class="progress-bar"
[ngStyle]="{
'width': progress + '%',
'background-color': getColorForProgress()
}"
></div>
<span>{{ progress }}%</span>
</div>
`,
styles: [`
.progress-container {
height: 20px;
background-color: #e0e0e0;
border-radius: 4px;
position: relative;
margin: 15px 0;
}
.progress-bar {
height: 100%;
border-radius: 4px;
transition: width 0.3s ease;
}
span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-weight: bold;
text-shadow: 1px 1px 1px rgba(0,0,0,0.5);
}
`]
})
export class ProgressBarComponent {
@Input() progress: number = 0;
getColorForProgress(): string {
if (this.progress < 30) return '#F44336'; // Red
if (this.progress < 70) return '#FFC107'; // Yellow
return '#4CAF50'; // Green
}
}
Using External CSS Libraries
Angular applications can easily incorporate external CSS libraries like Bootstrap, Material Design, or Tailwind CSS.
Adding Bootstrap to Your Angular Project
- Install Bootstrap:
npm install bootstrap
- Add Bootstrap to your global styles in
angular.json
:
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.css"
],
- Use Bootstrap classes in your components:
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Card Title</h5>
<p class="card-text">Some example content for this card.</p>
<button class="btn btn-primary">Read More</button>
</div>
</div>
</div>
</div>
</div>
Using SCSS/SASS in Angular Components
Angular supports SCSS/SASS out of the box. To use it:
- Create your component with
.scss
files:
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent { }
- In your
dashboard.component.scss
file, use SCSS features:
$primary-color: #3f51b5;
$secondary-color: #ff4081;
$padding-base: 15px;
.dashboard {
padding: $padding-base;
.header {
background-color: $primary-color;
color: white;
padding: $padding-base;
h1 {
margin: 0;
font-size: 24px;
}
}
.content {
padding: $padding-base;
.card {
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: $padding-base;
&:hover {
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.card-title {
color: $primary-color;
}
.card-actions {
button {
background-color: $secondary-color;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
&:hover {
background-color: darken($secondary-color, 10%);
}
}
}
}
}
}
Real-World Example: Theme Switching
Let's create a component that demonstrates theme switching functionality:
@Component({
selector: 'app-theme-switcher',
template: `
<div class="theme-container" [ngClass]="currentTheme">
<div class="content-card">
<h2>Theme Switcher Example</h2>
<p>Current theme: {{ currentTheme }}</p>
<div class="theme-options">
<button (click)="setTheme('light-theme')" class="theme-btn light">Light</button>
<button (click)="setTheme('dark-theme')" class="theme-btn dark">Dark</button>
<button (click)="setTheme('blue-theme')" class="theme-btn blue">Blue</button>
</div>
</div>
</div>
`,
styles: [`
.theme-container {
padding: 20px;
transition: all 0.3s ease;
min-height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
.content-card {
background-color: var(--card-bg);
color: var(--text-color);
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
width: 300px;
}
.theme-options {
display: flex;
gap: 10px;
margin-top: 20px;
}
.theme-btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.theme-btn.light {
background-color: #f5f5f5;
color: #333;
}
.theme-btn.dark {
background-color: #333;
color: #fff;
}
.theme-btn.blue {
background-color: #1976d2;
color: #fff;
}
/* Theme Definitions */
.light-theme {
--bg-color: #f5f5f5;
--card-bg: #ffffff;
--text-color: #333333;
background-color: var(--bg-color);
}
.dark-theme {
--bg-color: #333333;
--card-bg: #424242;
--text-color: #f5f5f5;
background-color: var(--bg-color);
}
.blue-theme {
--bg-color: #e3f2fd;
--card-bg: #bbdefb;
--text-color: #0d47a1;
background-color: var(--bg-color);
}
`]
})
export class ThemeSwitcherComponent {
currentTheme: string = 'light-theme';
setTheme(theme: string) {
this.currentTheme = theme;
}
}
Best Practices for Angular Component Styling
-
Keep Component Styles Focused: Each component should only style elements that it's responsible for.
-
Use Host Selectors: Target the component's host element with
:host
selector:css:host {
display: block;
margin: 10px;
}
:host(.active) {
border-left: 3px solid blue;
} -
Use CSS Variables for Themes: Define reusable values as variables:
css:root {
--primary-color: #3f51b5;
--accent-color: #ff4081;
}
.button {
background-color: var(--primary-color);
} -
Take Advantage of ngClass and ngStyle: Use these directives for dynamic styling based on component state.
-
Consider Using SCSS/SASS: For larger components, SCSS features like nesting and variables can make styles more maintainable.
-
Be Careful with ViewEncapsulation.None: Only use it when you specifically need styles to affect other components.
Summary
Angular provides flexible options for styling components to suit different needs:
- Component-scoped styles with
styleUrls
orstyles
- Style encapsulation modes to control style boundaries
- Dynamic styling with
ngClass
andngStyle
directives - Support for CSS preprocessors like SCSS/SASS
- Integration with external CSS libraries
By understanding these various styling approaches, you can create well-organized and maintainable components with clean separation of concerns.
Additional Resources
- Angular Official Documentation on Component Styles
- Using SASS with Angular
- Angular Material - A UI component library using Angular's styling capabilities
Exercises
-
Create a component with a button that changes its style based on different states (normal, hover, active, disabled).
-
Build a card component that supports multiple themes (light, dark, colorful) using CSS variables.
-
Implement a responsive navigation menu that changes layout on different screen sizes.
-
Create a component that uses SCSS nesting and variables to style a form with different types of inputs.
-
Build a theme switching service that can change the theme of your entire Angular application.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)