Cet article fait partie de la série d’articles Angular from Scratch.
Angular permet d’appliquer un style CSS sur les éléments des vues des composants. Ce style CSS peut être défini de façon globale pour toute l’application, au niveau d’un composant ou plus spécifiquement à un élément.
Le but de cet article est d’expliciter différentes méthodes pour appliquer un style CSS aux éléments d’un composant. Il est possible d’appliquer un style en utilisant des fichiers Sass, less ou stylus avec les extensions respectivement .scss
, .less
ou .styl
toutefois ces formats de feuille de style ne seront pas traités dans cet article.
Dans un premier temps, on va indiquer comment appliquer un style ou une classe CSS aux éléments d’une application Angular de façon globale, puis à l’échelle d’un composant.
Où définir les styles CSS ?
Appliquer un style globalement
Appliquer un style sur les éléments d’un composant
Encapsulation des styles d’un composant
Comportement avec les composants enfants
Définir les styles CSS
Paramètre styleUrls de @Component()
Paramètre styles de @Component()
Importer des fichiers de style
Supprimer l’isolation des styles aux composants
Comment appliquer des styles sur les éléments d’un composant ?
Appliquer un style ou une classe statiquement
Attribute binding
Property binding
Utiliser des chaines de caractères
Utiliser une expression
Utiliser un object literal
Property binding sur une seule propriété du style
Property binding sur une seule classe CSS
Sélecteurs Angular
Sélecteur :host
Appliquer un style en appliquant une condition sur l’hôte
Sélecteur :host-context
Sélecteur ::ng-deep
Appliquer un style globalement
Appliquer un style à des composants enfant
Appliquer un style dans la classe du composant
Avec @HostBinding()
Avec ElementRef.nativeElement
Priorités d’application des styles et classes CSS
Priorités d’application des styles sur un élément
Priorités d’application des styles sur l’hôte d’un composant
Pour comprendre les différents exemples, on va créer une application Angular en utilisant le CLI Angular:
ng new css-test --skip-tests --no-routing --style css
Cette ligne permet de créer une application nommée css-test
:
- en évitant la génération des fichiers de tests (avec
--skip-tests
), - en évitant d’installer un module de routing (avec
--no-routing
) et - en précisant l’extension des fichiers de style CSS (avec
--style css
)
On supprime tout ce qui se trouve dans le template du composant principal (cf. csstest/src/app/app.component.html
).
Où définir les styles CSS ?
Appliquer un style globalement
Pour définir et appliquer des styles globalement à l’échelle de l’application, il faut indiquer le fichier CSS contenant ces styles dans les paramètres du projet Angular dans angular.json
au niveau du paramètre styles
. Ce paramètre permet d’indiquer le chemin des fichiers de style utilisables dans l’application:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"csstest": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/csstest",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
}
}
}
}
}
Par défaut le fichier src/styles.css
existe et permet de définir des styles, toutefois on peut rajouter d’autres fichiers avec le paramètre styles
dans angular.json
.
Pour illustrer dans l’application d’exemple, on rajoute un composant nommé Parent
en exécutant:
ng g c Parent
Avec l’implémentation suivante:
<h1>Composant parent</h1>
<p>Contenu du composant parent</p>
On modifie le composant principal:
<h1>Composant principal</h1>
<div style="display: block; border: 1px solid black; padding: 10px; background-color: white;">
<app-parent></app-parent>
</div>
<app-parent></app-parent>
correspond au paramètre selector
du composant parent
. Pour plus de précisions sur ce paramètre, voir l’article Les vues des composants Angular.
On modifie le fichier css/src/styles.css
pour préciser un style pour l’élément <h1>
:
h1 {
color: blue;
font-family: arial,sans-serif;
}
.componenttitle {
text-transform: uppercase;
}
A l’exécution, on peut voir que le style défini pour <h1>
est appliqué à l’élément dans le composant principal et dans le composant Parent
, les éléments <h1>
sont en bleu:
On peut aussi appliquer une classe définie dans un fichier global au niveau d’un composant. Par exemple si on modifie le template du composant Parent
pour appliquer la classe componenttitle
:
<h1 class="componenttitle">Composant parent</h1>
La classe est prise en compte, à l’exécution, l’élément <h1>
du composant Parent
est en majuscules:
Si on affiche les outils développeurs du browser dans l’onglet “Editeur de styles” sous Firefox ou “Eléments” et “Styles” dans Chrome, on peut voir que la feuille de style styles.css
contient les styles qui ont été définis pour toute l’application:
Pour afficher l’éditeur de styles:
- Sous Firefox: on peut utiliser la raccourci [Maj] + [F7] ou en allant dans le menu “Outils” ⇒ “Développement web” ⇒ “Editeur de style”.
- Sous Chrome: utiliser le raccourci [F12] (sous MacOS: [⌥] + [⌘] + [C], sous Linux: [Ctrl] + [Maj] + [I]) puis cliquer sur l’onglet “Elements”. A partir du menu, il faut aller dans “Afficher” ⇒ “Options pour les développeurs” ⇒ “Examiner les éléments”.
Appliquer un style sur les éléments d’un composant
Au lieu de définir des styles pour toute l’application, on peut les définir à l’échelle d’un composant seulement pour les éléments se trouvant dans ce composant.
Plusieurs méthodes sont possibles pour définir des styles dans un composant. Cette partie va détailler ces différentes méthodes.
Encapsulation des styles d’un composant
Par défaut, les styles définis dans un composant n’affecte que le composant dans lequel ils sont définis. Les styles des composants sont ainsi isolés et n’affectent pas les autres.
Pour illustrer cette partie, on va créer un 2e composant nommé other
que l’on va placer sous le composant Parent
en exécutant:
ng g c other
Et on modifie le template du composant principale (cf. src/app/app.component.html
):
<h1>Composant principal</h1>
<div style="display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: white;">
<app-parent></app-parent>
</div>
<div style="display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: white;">
<app-other></app-other>
</div>
L’implémentation du composant other
est similaire à celle du composant Parent
:
<h1>Composant other</h1>
<p>Contenu du composant other</p>
Si on modifie le contenu du fichier de style du composant Parent
(cf. src/app/parent/parent.component.css
):
p {
background-color: yellow;
}
On peut voir que seul le composant Parent
est affecté par cette modification. Le contenu du composant other
reste inchangé:
Ce comportement s’explique par le fait que le style des composants est isolé. Si on affiche l’onglet “Elements” des outils développeurs, on peut voir un code similaire au code suivant:
<app-root _nghost-thd-c19 ng-version="11.2.4">
<h1 _ngcontent-thd-c19>Composant principal</h1>
<div _ngcontent-thd-c19 style="display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: white;">
<app-parent _ngcontent-thd-c19 _nghost-thd-c16>
<h1 _ngcontent-thd-c16 class="componenttitle">Composant parent</h1>
<p _ngcontent-thd-c16>Contenu du composant parent</p>
</app-parent>
</div>
<div _ngcontent-thd-c19 style="display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: white;">
<app-other _ngcontent-thd-c19 _nghost-thd-c18>
<h1 _ngcontent-thd-c18 >Composant other</h1>
<p _ngcontent-thd-c18>Contenu du composant other</p>
</app-other>
</div>
</app-root>
Ainsi des identifiants ont été rajoutés (parties en gras). Si on affiche le style de l’élément <p>
en jaune du composant Parent
, on peut voir:
p[_ngcontent-thd-c16] {
background-color: yellow;
}
Le style n’est pas défini de façon globale mais il est limité aux éléments contenant un attribut _ngcontent-thd-c16
. Le seul élément <p>
avec un attribut _ngcontent-thd-c16
est celui du composant Parent
et non celui du composant other
(qui est _ngcontent-thd-c18
).
Ainsi, c’est en utilisant des attributs _nghost
et _ngcontent
spécifiques à un composant et en limitant la définition des styles aux éléments ayant certains attributs qu’Angular isole les styles pour le composant dans lequel ils ont été définis.
Comportement avec les composants enfants
L’encapsulation du style des vues implique que, par défaut, le style est strictement limité à la vue d’un composant. Le style défini dans un composant n’aura pas de conséquence sur des composants enfant et sur du contenu projeté. Seuls les éléments se trouvant dans le composant où le style est défini seront impactés.
Par exemple, si on considère 2 composants Parent
et Child
tels que Child
est un composant enfant de Parent
:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)@Component({ selector: 'app-child', template: './child.component.html' }) export class ChildComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <app-child></app-child>
Feuille CSS
(parent.component.css)p { background-color: cadetblue; }
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
On peut voir que seul l’élément se trouvant dans le composant Parent
est impacté par le style défini dans la feuille de style parent.component.css
:
Si on modifie le code des composants de cette façon:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)@Component({ selector: '[app-child]', template: './child.component.html' }) export class ChildComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <p app-child></p>
Feuille CSS
(parent.component.css)p { background-color: cadetblue; }
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
Le paramètre selector
du composant Child
est [app-child]
, ainsi pour afficher le composant Child
dans la vue du composant Parent
, il faut indiquer le selector
sous forme d’attribut:
<p app-child></p>
On peut voir que le style s’applique aussi à l’élément <p app-child></p>
. On pourrait penser que le style défini dans le composant Parent
s’applique au composant imbriqué Child
toutefois ce n’est pas tout à fait le cas. En réalité, le style s’applique à l’élément hôte <p>
du composant enfant qui se trouve dans le composant Parent
:
Pour appliquer un style à des composants enfant, il faut utiliser le sélecteur :host ::ng-deep
.
Définir les styles CSS
Paramètre styleUrls de @Component()
Par défaut, les styles CSS d’un composant sont définis dans un fichier séparé du template et de la classe du composant. Le chemin de ce fichier est indiqué en utilisant le paramètre styleUrls
dans le décorateur @Component()
du composant:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent {
constructor() { }
}
styleUrls
est un tableau et permet d’indiquer plusieurs fichiers:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./file1.css', './file2.css', './file3.css' ]
})
export class ExampleComponent {
constructor() { }
}
Paramètre styles de @Component()
Utiliser un fichier séparé pour définir les styles CSS n’est pas obligatoire, on peut définir des styles directement dans la classe du composant en utilisant le paramètre styles
du décorateur @Component()
, par exemple:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styles: [
'div { display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: cadetblue; color: white }',
'h1 { text-transform: uppercase; color: blue }'
]
})
export class ExampleComponent {
constructor() { }
}
Le paramètre styles
permet d’indiquer un tableau de façon à pouvoir définir plusieurs styles.
Avec le CLI Angular, on peut créer un composant directement avec le paramètre styles plutôt que le paramètre par défaut styleUrls
en uilisant l’option --inline-style
:
ng g c <nom du composant> --inline-style
Avec cette option, un fichier séparé contenant les styles ne sera pas créé.
Importer des fichiers de style
Comme pour les fichiers CSS classiques, il est possible d’importer des fichiers CSS dans les fichiers de styles des composants. L’intérêt est de profiter de l’encapsulation des vues de composant sans dupliquer le code des feuilles de style.
Pour importer un fichier CSS, il suffit d’indiquer le chemin relatif du fichier à importer avec la syntaxe suivante:
@import '<chemin relatif du fichier CSS à importer>';
Ou
@import url('<chemin relatif du fichier CSS à importer>');
Par exemple, pour importer un fichier CSS dans src/app/commonStyle.css
dans le composant src/app/parent/parent.component.ts
, il faut indiquer dans le fichier src/app/parent/parent.component.css
:
@import url('../commonStyle.css');
L’intérêt est de pouvoir partager ce fichier pour plusieurs composants sans modifier le paramètre ViewEncapsulation
et sans devoir dupliquer les styles.
Si le fichier à importer se trouve dans le même répertoire, il faut faire précéder le nom du fichier par './'
, par exemple:
@import './commonStyle.css';
Supprimer l’isolation des styles aux composants
On peut paramétrer un comportement différent concernant l’isolation des éléments de style définis dans un composant. Ce paramétrage se fait au niveau du paramètre encapsulation
dans le décorateur @Component()
:
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
...
encapsulation: ViewEncapsulation.Emulated
})
export class CustomComponent {
...
}
Les valeurs possibles de ViewEncapsulation
sont:
ViewEncapsulation.Emulated
(valeur par défaut): cette valeur isole les styles dans les composants par émulation. Angular effectue cette émulation en ajoutant des attributs_nghost
et_ngcontent
sur les éléments et des sélecteurs d’attributs sur les styles définis dans les composants. C’est le comportement décrit plus haut.ViewEncapsulation.ShadowDom
: avec ce paramètre les styles définis dans les composants sont aussi isolés dans le composant (comme pourViewEncapsulation.Emulated
). La différence est que ce n’est pas Angular qui va émuler ce comportement en rajoutant des attributs. Il va se servir de la fonctionnalité Shadow DOM du browser pour effectuer cette isolation.Ainsi pour utiliser la fonctionnalité Shadow DOM, Angular crée un Shadowing tree pour chaque composant de façon à séparer la structure et le style de ces composants du DOM.
Si on reprend l’exemple précédent en affectant le paramètre
ViewEncapsulation.ShadowDom
au composantParent
, on peut voir qu’il n’y a plus de sélecteur de style pour l’élément<p>
toutefois le style est toujours limité au composantParent
:p { background-color: yellow; }
ViewEncapsulation.None
: ce paramétrage consiste à ne pas isoler les styles au composant dans lesquels ils sont définis. En affectant ce paramètre sur un composant, le style sera défini de façon globale à toute l’application.Par exemple, si on considère 2 composants
First
etSecond
que l’on place directement dans le composant principal. Si on applique le paramètreViewEncapsulation.None
pour le composantFirst
:- Template du composant principal (cf.
src/app/app.component.html
):<h1>Composant principal</h1> <div style="display: block; border: 1px solid black; padding: 10px; margin-bottom: 10px; background-color: white;"> <app-first></app-first> <app-second></app-second> </div>
- Composant
First
:
Template
(first.component.html)<h1>Composant First</h1> <p>Contenu composant Child</p>
Feuille CSS
(first.component.css)p { background-color: yellow; }
Classe
(first.component.ts)@Component({ selector: 'app-first', template: './first.component.html', styleUrls: [ './first.component.css' ], encapsulation: ViewEncapsulation.None }) export class FirstComponent { }
- Composant
Second
:
Template
(second.component.html)<h1>Composant Second</h1> <p>Contenu composant Second</p>
Classe
(second.component.ts)@Component({ selector: 'app-second', template: './second.component.html' }) export class SecondComponent { }
On peut voir que les éléments
<p>
des composantFirst
etSecond
sont affectés par le style (la propriétébackground-color
des éléments<p>
estyellow
):
- Template du composant principal (cf.
Si la vue d’un composant avec le paramètre encapsulation: ViewEncapsulation.None
n’est pas affichée, le style défini dans ce composant ne sera pas appliqué de façon globale.
encapsulation
Avec le CLI Angular, on peut créer des composants directement en précisant la valeur du paramètre encapsulation
par exemple en exécutant la commande:
ng g c <nom du composant> --view-encapsulation None
Les valeurs possibles sont Emulated
, None
ou ShadowDom
.
Comment appliquer des styles sur les éléments d’un composant ?
Plusieurs méthodes sont possibles pour définir et appliquer un style ou une classe CSS à un élément d’un composant:
- Statiquement en définissant les styles ou en appliquant les classes CSS de façon inline directement dans l’élément en utilisant les attributs
style
etclass
. - Par attribute binding avec un attribut de type
[attr.style]
pour définir un style ou[attr.class]
pour appliquer une classe CSS. - Par property binding avec un attribut de type
[style]
pour définir un style ou[class]
pour appliquer une classe CSS. - En utilisant les objets
ngStyle
oungClass
.
Appliquer un style ou une classe statiquement
Appliquer un style ou une classe sur un élément revient à utiliser les attributs style
ou class
directement comme pour une page HMTL classique, par exemple:
<div style="background-color: yellow">
...
</div>
Ou
<div class="cssClassName">
...
</div>
Si on prend l’exemple d’un composant dont l’implémentation est:
Template (example.component.html) |
|
Feuille CSS (example.component.css) |
|
Classe (example.component.ts) |
|
Appliquer un style est immédiat:
<h1>Composant Example</h1>
<p style="background-color: cadetblue; color: white">Contenu du composant example</p>
De même pour appliquer des classes:
<h1>Composant Example</h1>
<p class="bluebackground whitetext">Contenu du composant example</p>
Attribute binding
Pour appliquer des styles sur un élément par attribute binding, on peut utiliser directement l’attribut [attr.style]
avec une chaîne de caractères contenant les styles:
<div [attr.style]="definedStyles">
...
</div>
definedStyles
contient les styles sous forme de chaîne de caractères, par exemple:
background-color: cadetblue; color: white;
De même pour appliquer des classes CSS, on peut utiliser l’attribut [attr.class]
avec une chaîne de caractères contenant les classes à appliquer:
<div [attr.class]="definedClasses">
...
</div>
definedClasses
contient les classes sous forme de chaîne de caractères, par exemple:
bluebackground whitetext
Par exemple, une implémentation complête dans un composant pour appliquer un style par attribute binding serait du type:
Template (example.component.html) |
|
Classe (example.component.ts) |
|
En cliquant sur le bouton, on peut voir que le style est ajouté dynamiquement sur l’élément <div>
.
De même pour une classe CSS, on peut appliquer une classe par attribute binding en utilisant attr.class
:
Template (example.component.html) |
|
Feuille CSS (example.component.css) |
|
Classe (example.component.ts) |
|
Property binding
On peut appliquer des styles ou des classes CSS sur des éléments du template en utilisant des property bindings. A la différence de l’attribute binding, le propery binding passe par l’intermédiaire d’une propriété Angular pour effectuer les changements dans le DOM (l’attribute binding intervient plus directement sur l’attribut d’un élément HTML).
Le property binding permet plus de flexibilité en permettant d’affecter des styles ou des classes CSS sous forme d’une chaîne de caractères, d’un tableau de chaînes de caractères, d’une expression ou d’object literal.
Utiliser des chaines de caractères
Pour affecter des styles sous forme de chaînes de caractères, la syntaxe est du type:
<div [style]="definedStyles">
...
</div>
definedStyles
contient les styles sous forme de chaîne de caractères, par exemple:
background-color: cadetblue; color: white;
De même pour appliquer des classes CSS, on peut utiliser l’attribut [class]
avec une chaîne de caractères contenant les classes à appliquer:
<div [class]="definedClasses">
...
</div>
definedClasses
contient les classes sous forme de chaîne de caractères, par exemple:
bluebackground whitetext
Utiliser une expression
On peut utiliser directement une expression pour la valeur des attributs [style]
et [class]
pour affecter respectivement des styles ou une classe CSS:
<div [style]="<expression>">
...
</div>
Par exemple:
Template (example.component.html) |
|
Classe (example.component.ts) |
|
A l’exécution, on peut voir que le style défini sous forme d’une expression "backgroundColorStyle + ';' + whiteTextStyle"
est appliqué sur l’élément <div>
.
Utiliser un object literal
On peut affecter les styles ou les classes CSS en utilisant des object literals. L’intérêt de ce type d’objet est de permettre de les paramétrer plus facilement dans la classe du composant.
L’object literal doit comporter:
- des propriétés dont les noms correspondent aux propriétés du style et
- des valeurs correspondant aux valeurs des styles à appliquer.
{
<propriété de style 1>: '<valeur 1>',
<propriété de style 2>: '<valeur 2>',
...
<propriété de style N>: '<valeur N>'
}
De même pour les classes CSS, l’object literal doit comporter:
- des propriétés dont le nom correspond au nom de la classe CSS et
- des valeurs sont forme de booléen. La valeur
True
indiquant que la classe doit s’appliquer.
{
<nom de la classe CSS 1>: '<true ou false>',
<nom de la classe CSS 2>: '<true ou false>',
...
<nom de la classe CSS N>: '<true ou false>'
}
Exemple pour affecter un style
Par exemple, le composant suivant permet d’affecter un style sous la forme d’un object literal à un élément <div>
:
Template (example.component.html) |
|
Classe (example.component.ts) |
|
Pour que la détection de changement fonctionne et que le changement de valeur de l’object literal soit répercuté dans la vue gràce au property binding, il faut affecter l’object literal entièrement et non modifier seulement la valeur des propriétés.
Le changement de style ne sera pas répercuté dans la vue si on implémente la méthode changeStyle()
de cette façon:
changeStyle(): void {
if (this.styleAsObjectLiteral.backgroundColor === '') {
this.styleAsObjectLiteral.backgroundColor = 'cadetblue';
this.styleAsObjectLiteral.color = 'white';
}
else {
this.styleAsObjectLiteral.backgroundColor = '';
this.styleAsObjectLiteral.color = '';
}
}
Dans cet exemple, l’object literal permet de définir la propriété background-color
et color
de l’élément <div>
:
{
backgroundColor: 'cadetblue',
color: 'white'
}
Cet exemple utilise le Camel case pour nommer les propriétés de l’object literal de façon à paramétrer les propriétés de l’élément HTML qui sont en Kebab case:
backgroundColor
en Camel case permet de paramétrer le stylebackground-color
en Kebab case,color
permet de paramétrer le stylecolor
.
Exemple pour affecter une classe CSS
L’exemple affecte une classe CSS à un élément <div>
en utilisant un object literal:
Template (example.component.html) |
|
Feuille CSS (example.component.css) |
|
Classe (example.component.ts) |
|
Property binding sur une seule propriété du style
Au lieu d’effecter le style complètement, on peut modifier une propriété par property binding. Par exemple, pour appliquer des property bindings seulement sur les propriétés background-color
et color
d’un élément <div>
:
<div [style.background-color]="<membre de type string dans la classe du composant>"
[style.color]="<membre de type string dans la classe du composant>">
...
</div>
Les propriétés de style peuvent être nommées de 2 façons en Camel case et en Kebab case:
- En Kebab case: pour désigner la propriété de style
background-color
, on peut effectuer le property binding avec la propriété du même nom de l’objetstyle
, par exemple<div [style.background-color]="<membre de type string dans la classe>"> ... </div>
- Camel case: pour désigner la propriété de style
background-color
, on peut effectuer le property binding avec la propriétébackgroundColor
de l’objetstyle
, par exemple:<div [style.backgroundColor]="<membre de type string dans la classe>"> ... </div>
L’exemple complet est:
Template (example.component.html) |
|
Classe (example.component.ts) |
|
Property binding sur une seule classe CSS
Au lieu d’affecter toutes les classes CSS en utilisant un object literal, on peut effectuer un property binding pour une seule classe CSS. Par exemple, pour indiquer avec un booléen si on veut appliquer les classes CSS bluebackground
et whitetext
sur un élément <div>
, on peut effectuer des property bindings séparément:
<div [class.bluebackground]="<membre de type booléen dans la classe du composant>"
[class.whitetext]="<membre de type booléen dans la classe du composant>">
...
</div>
L’exemple complet est:
Template (example.component.html) |
|
Feuille CSS (example.component.css) |
|
Classe (example.component.ts) |
|
[ngStyle]
et [ngClass]
Quand on applique des property bindings avec des tableaux ou des object literals, on peut utiliser [ngStyle]
et [ngClass]
à place de, respectivement, [style]
et [class]
pour appliquer des styles ou une classe.
Sélecteurs Angular
Il existe des sélecteurs de style Angular qui permettent d’affiner les conditions d’application des styles et des classes. Après compilation, ces styles n’apparaissent plus dans le code de l’application.
Sélecteur :host
Le sélecteur :host
peut être utilisé dans la déclaration des styles pour désigner l’élément hôte de la vue d’un composant.
Par exemple si on considère 2 composants appelés Parent
et Child
tels que Child
est un composant enfant de Parent
:
L’implémentation est:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)@Component({ selector: 'app-child', template: './child.component.html', styleUrls: [ './child.component.css' ] }) export class ChildComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <app-child></app-child>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html' }) export class ParentComponent { }
Si on souhaite appliquer un style seulement au composant Child
, on pourrait être tenté de définir le style CSS suivant dans le fichier child.component.css
:
/* Ce code ne fonctionne pas */
app-child {
display: block;
background-color: cadetblue;
border: 1px black solid;
font-family: Arial, sans-serif;
}
Cette définition ne fonctionne pas, pour appliquer un style sur le composant, il faut utiliser le sélecteur :host
à la place de app-child
:
:host {
display: block;
background-color: cadetblue;
border: 1px black solid;
font-family: Arial, sans-serif;
padding: 10px;
}
Le résultat est:
Dans l’exemple précédent, le composant Child
était directement l’élément affiché dans le composant Parent
, le code HTML était du type:
<app-parent>
<h1>Composant Parent</h1>
<p>Contenu composant Parent</p>
<app-child>
<h1>Composant Child</h1>
<p>Contenu composant Child</p>
</app-child>
</app-parent>
Au lieu d’être directement l’élément affiché, le composant enfant peut se trouver dans un élément hôte, par exemple si on définit le composant Child
de cette façon:
Template (child.component.html) |
|
Classe (child.component.ts) |
|
Pour l’afficher dans le composant Parent
, on modifie le template de cette façon:
Composant Parent
:
<h1>Composant Parent</h1>
<p>Contenu composant Parent</p>
<p app-child></p>
L’élément hôte de la vue du composant Child
est désormais un élément <p>
:
<app-parent>
<h1>Composant Parent</h1>
<p>Contenu composant Parent</p>
<p app-child>
<h1>Composant Child</h1>
<p>Contenu composant Child</p>
</p>
</app-parent>
Le sélecteur :host
s’applique à l’hôte du composant quel qu’il soit. Ainsi même si l’élément hôte a changé, le style est toujours appliqué. Le résultat est le même que précédemment.
Appliquer un style en appliquant une condition sur l’hôte
On peut restreindre l’application du style en appliquant une condition sur l’hôte du composant.
Par exemple si on veut appliquer le style si l’hôte est un élément <p>
:
:host(p) {
...
}
Si on veut appliquer le style si la classe redtext
est appliquée sur l’hôte:
.host(.redtext) {
...
}
On peut restreindre davantage les conditions en rajoutant d’autres conditions après :host()
. Par exemple, si on veut appliquer un style:
- Si l’hôte du composant est un élément
<p>
- Seulement sur les éléments
<h1>
se trouvant dans le composant
On définit le style de cette façon:
:host(p) h1 {
...
}
Si considère les composants Parent
et Child
tels que Child
est un composant enfant de Parent
:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)@Component({ selector: '[app-child]', template: './child.component.html', styleUrls: [ './child.component.css' ] }) export class ChildComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <p app-child></p> <span app-child></span>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html' }) export class ParentComponent { }
Pour appliquer un style sur l’hôte du composant Child
seulement si l’hôte est un élément <p>
, on ajoute dans le fichier child.component.css
:
:host(p) {
display: block;
background-color: cadetblue;
border: 1px black solid;
font-family: Arial, sans-serif;
padding: 10px;
}
Dans cet exemple, on voit que le style n’est pas appliqué pour la ligne <span app-child></span>
:
Sélecteur :host-context
Le sélecteur :host-context
permet de désigner un antécédent du composant courant. On peut ainsi appliquer un style si un antécédent respecte une condition particulière.
Par exemple si on veut appliquer un style si un antécédent du composant est un élément <p>
, on peut définir le style de cette façon:
:host-context(p) {
...
}
Si on veut appliquer un style si la classe redtext
est appliquée sur un antécédent du composant, on peut définir le style de cette façon:
:host-context(.redtext) {
...
}
On peut restreindre l’application du style en rajoutant d’autres conditions après :host-context()
. Par exemple, si on veut appliquer un style:
- Si un antécédent du composant est un élément
<p>
- Seulement sur les éléments
<h1>
du composant.
On peut définir le style de cette façon:
:host-context(p) h1 {
...
}
Si on considère 3 composants Parent
, Middle
et Child
tels que:
Middle
est un composant enfant deParent
etChild
est un composant enfant deMiddle
.
L’implémentation est:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)@Component({ selector: '[app-child]', template: './child.component.html', styleUrls: [ './child.component.css' ] }) export class ChildComponent { }
- Composant
Middle
:
Template
(middle.component.html)<h1>Composant Middle</h1> <p>Contenu composant Middle</p> <span app-child></span>
Classe
(middle.component.ts)@Component({ selector: '[app-middle]', template: './middle.component.html', styleUrls: [ './middle.component.css' ] }) export class MiddleComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <p app-middle></p>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
Pour appliquer un style sur l’hôte du composant Child
seulement si un antécédent de Child
est un élément <p>
, on ajoute dans le fichier child.component.css
:
:host-context(p) {
display: block;
background-color: cadetblue;
border: 1px black solid;
font-family: Arial, sans-serif;
padding: 10px;
}
Le résultat est:
Dans cet exemple, même si l’hôte du composant Child
est un élément span
, le style est appliqué car l’hôte du composant Middle
dans lequel se trouve Child
est un élément <p>
.
Pour appliquer un style seulement sur les éléments <h1>
du composant Child
si l’hôte d’un antécédent de ce composant est un élément <p>
(dans child.component.css
):
:host-context(p) h1 {
color: greenyellow;
}
Le résultat est:
Sélecteur ::ng-deep
La documentation indique que ce sélecteur doit être décomissioné dans les futures versions d’Angular toutefois dans la version 11, il est toujours supporté.
Il sert à appliquer un style ou une classe globalement et en particulier à des composants enfant. L’intérêt de ce sélecteur est d’appliquer un style sur des composants enfant pour lesquels on ne peut pas modifier le code.
Concernant la syntaxe, il faut placer ::ng-deep
devant les autres sélecteurs de style nécessitant une application globale:
::ng-deep <autres sélecteurs de style>
Par exemple:
::ng-deep p {}
permet d’appliquer un style sur tous les éléments<p>
de l’application.::ng-deep .bluebackground {}
permet d’appliquer un style à tous les éléments pour lesquels la classe CSSbluebackground
est utilisée.::ng-deep p.bluebackground {}
applique un style sur tous les éléments<p>
utilisant la classe CSS bluebackground.span ::ng-deep p {}
applique le même style sur les éléments<span>
du composant et sur tous les éléments<p>
de l’application. Il faut placer::ng-deep
devant les sélecteurs pour lesquels on veut une application globale.
Les sélecteurs /deep/
et >>>
ont les mêmes fonctions que ::ng-deep
toutefois il est déconseillé de les utiliser. La syntaxe est la même:
/deep/ <autres sélecteurs de style>
Ou
>>> <autres sélecteurs de style>
::ng-deep
doit être utilisé avec ViewEncapsulation.Emulated
Il faut utiliser le sélecteur ::ng-deep
avec le paramètre ViewEncapsulation.Emulated
. Cette valeur étant la valeur par défaut, il n’est pas obligatoire de la préciser.
Appliquer un style globalement
Si on utilise ::ng-deep
seul, la définition d’un style ou d’une classe devient globale.
Par exemple, si considère les 3 composants First
, Second
et Parent
tels que First
et Second
sont des composants enfant de Parent
:
- Composant
First
:
Template
(first.component.html)<h1>Composant First</h1> <p>Contenu composant First</p>
Classe
(first.component.ts)@Component({ selector: 'app-first', template: './first.component.html', styleUrls: [ './first.component.css' ] }) export class FirstComponent { }
- Composant
Second
:
Template
(second.component.html)<h1>Composant Second</h1> <p>Contenu composant Second</p>
Classe
(second.component.ts)@Component({ selector: 'app-second', template: './second.component.html', styleUrls: [ './second.component.css' ] }) export class SecondComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <app-first></app-first> <app-second></app-second>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
Si on définit le style suivant dans le fichier CSS du composant First
(first.composant.css
):
::ng-deep p {
background-color: cadetblue;
}
On peut voir que le style sera appliqué à tous les éléments <p>
:
Appliquer un style à des composants enfant
Pour appliquer un style à des composants sans l’appliquer globalement, il faut que ::ng-deep
soit précédé de :host
:
:host ::ng-deep <autres sélecteurs de style>
Par exemple, si on reprend l’exemple des composants Child
, Middle
et Parent
tels que:
Child
est un composant enfant deMiddle
etMiddle
est un composant enfant deParent
.
L’implémentation est:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ys)@Component({ selector: 'app-child', template: './child.component.html', styleUrls: [ './child.component.css' ] }) export class ChildComponent { }
- Composant
Middle
:
Template
(middle.component.html)<h1>Composant Middle</h1> <p>Contenu composant Middle</p> <app-child></app-child>
Classe
(middle.component.ts)@Component({ selector: 'app-middle', template: './middle.component.html', styleUrls: [ './middle.component.css' ] }) export class MiddleComponent { }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <app-middle></app-middle>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
Si on définit le style suivant dans le fichier CSS du composant Middle
(cf. Middle.composant.css
):
:host ::ng-deep p {
background-color: cadetblue;
}
On peut voir que le style sera appliqué aux élément <p>
de Middle
et Child
et non celui de Parent
:
:host ::ng-deep
est particulièrement utile si on veut personnaliser des éléments situés sur des composants pour lesquels on ne maitrise pas l’implémentation, par exemple des composants se trouvant dans @angular/material
.
Appliquer un style dans la classe du composant
Jusqu’içi, on a indiqué des méthodes pour appliquer des styles à partir du template ou d’une feuille de style d’un composant. Il existe d’autres méthodes permettant d’appliquer un style par programmation dans le classe du composant en utilisant, par exemple, les décorateurs @HostBinding()
ou @ViewChild()
.
Avec @HostBinding()
Le décorateur @HostBinding()
permet d’effectuer un binding entre un attribut dans la classe d’un composant et une propriété de l’objet du DOM qui est l’hôte du composant. Par exemple, utiliser ce décorateur permet d’accéder directement à des propriétés de style ou de classe.
Par exemple, si on considère les composants Child
et Parent
tels Child
est un composant enfant de Parent
. L’implémentation est:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)import { Component, HostBinding } from '@angular/ core'; @Component({ selector: '[app-child]', template: './child.component.html' }) export class ChildComponent { @HostBinding('style.background-color') backgroundColor: string = 'cadetblue'; }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <p app-child></p>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html' }) export class ParentComponent { }
En utilisant @HostBinding()
dans le composant Child
, on peut modifier la propriété style.background-color
pour appliquer à l’élément hôte du composant la couleur d’arrière plan. La vue du composant Child
est affichée dans le composant Parent
grâce à <p app-child></p>
. Ainsi l’élément hôte de Child
est <p>
, par suite @HostBinding()
s’applique à cet élément <p>
:
L’implémentation est similaire pour appliquer une classe CSS. Il faut au préalable définir la classe dans la feuille CSS du composant Parent
car l’encapsulation des styles limite la portée de la classe à ce composant seulement:
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <p>Contenu composant Child</p>
Classe
(child.component.ts)import { Component, HostBinding } from '@angular/ core'; @Component({ selector: '[app-child]', template: './child.component.html' }) export class ChildComponent { @HostBinding('class.bluebackground') applyBlueBackground: boolean = true; }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p>Contenu composant Parent</p> <p app-child></p>
Feuille CSS
(parent.component.css).bluebackground { background-color: cadetblue; }
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html', styleUrls: [ './parent.component.css' ] }) export class ParentComponent { }
Le résultat est similaire à l’exemple précédent.
Avec ElementRef.nativeElement
On peut appliquer des styles ou des classes CSS en utilisant des objets de type ElementRef
et Renderer2
. Ces objets sont:
ElementRef
: objet Angular permettant d’accéder à l’objet du DOM correspondant à un élément HTML grâce à la propriétéElementRef.nativeElement
.Renderer2
: il s’agit d’un objet Angular permettant d’effectuer des modifications dans les objets du DOM.
La combinaison de ces 2 objets permet d’appliquer des éléments de style ou une classe CSS.
Par exemple, si on considère le composant suivant:
Template (example.component.html) |
|
Feuille CSS (example.component.css) |
|
Classe (example.component.ts) |
|
Dans cet exemple, on utilise les éléments d’implémentation suivant:
- On définit un élément
<p>
dans le template du composant et on l’identifie avec la variable référence#content
. Cette variable référence va permettre d’atteindre cet élément dans la classe du composant. - Dans la classe du composant, on utilise le décorateur
@ViewChild()
pour requêter la vue et accéder à un élément qui y est définit. On identifie l’élément en utlisant la variable référence#content
. L’option{ static: true }
permet d’indiquer qu’il faut effectuer la requête sur le contenu statique de la vue.@ViewChild()
permet d’instancier un objet de typeElementRef
correspondant à un objet wrappant l’objet du DOM correspondant à l’élément HTML<p>
se trouvant dans la vue.Pour plus de détails sur
@ViewChild()
voir l’article Requêter les éléments d’une vue d’un composant Angular. - L’objet
Renderer2
peut être initialisé pour le composant par injection de dépendances.
Grâce aux objets Renderer2
et ElementRef
, on va:
- Appliquer la couleur
cadetblue
à l’arrière plan de l’élément<p>
:this.renderer.setStyle(this.contentElementRef.nativeElement, 'background-color', 'cadetblue');
- Appliquer la classe CSS
redtext
au contenu de l’élément<p>
(cette classe est définie dans la feuille de style du composant):this.renderer.setAttribute(this.contentElementRef.nativeElement, 'class', 'redtext');
Priorités d’application des styles et classes CSS
L’application des styles et des classes CSS se fait suivant un ordre particulier. Cet ordre s’applique de plusieurs façons:
- Pour un élément à l’intérieur d’un composant: si plusieurs styles sont appliqués, la priorité s’exerce en considérant d’abord une définition spécifique:
- Les property bindings s’appliquant sur une propriété spécifique:
[style.background-color]='backgroundColor'
Et:
[class.bluebackground]='canApplyBlueBackground'
- Les property bindings s’appliquant avec
[style]
ou[class]
:[style]='appliedStyles'
Et:
[class]='appliedCssClasses'
- Les styles et classes appliqués statiquement:
style='background-color: cadetblue'
Et:
class='redtext'
- Les property bindings s’appliquant sur une propriété spécifique:
- Si des styles ou classes sont appliqués sur l’hôte d’un composant, la priorité s’exerce à partant du template du composant vers ce qui est définit à l’extérieur du composant:
- Bindings effectués sur l’hôte du composant
- Les host bindings effectués par une directive
- Les host bindings effectués par le composant
Priorités d’application des styles sur un élément
Si on applique des styles sur un élément de plusieurs façons, la priorité d’application des styles s’effectuera en priorité sur les styles définis par:
- Property binding sur une propriété spécifique,
- Property binding en utilisant
[style]
, - Les styles appliqués statiquement.
Par exemple, si on considère le composant suivant:
Template (example.component.html) |
|
Classe (example.component.ts) |
|
On peut voir la priorité d’application des styles:
Priorités d’application des styles sur l’hôte d’un composant
Si on applique des styles sur l’hôte d’un composant, la priorité d’application des styles s’effectuera en priorité sur les styles définis par:
- Bindings effectués sur l’hôte du composant
- Les host bindings effectués par une directive
- Les host bindings effectués par le composant
Par exemple, si on considère 2 composants Child
et Parent
tels que Child
est un composant enfant de Parent
ainsi que la directive applyGreenBackground
. L’implémentation de ces éléments est:
- La directive
applyGreenBackground
:import { Directive, HostBinding } from '@angular/core'; @Directive({ selector: '[applyGreenBackground]' }) export class ApplyGreenBackgroundDirective { @HostBinding('style.background-color') backgroundColor: string = 'lime'; }
- Composant
Child
:
Template
(child.component.html)<h1>Composant Child</h1> <ng-content></ng-content>
Classe
(child.component.ts)import { Component, HostBinding } from '@angular/core'; @Component({ selector: '[app-child]', template: './child.component.html' }) export class ChildComponent { @HostBinding('style.background-color') backgroundColor: string = 'cadetblue'; }
- Composant
Parent
:
Template
(parent.component.html)<h1>Composant Parent</h1> <p app-child applyGreenBackground [style]='appliedStyles'> 1. Binding effectué dans le template </p> <p app-child applyGreenBackground> 2. Host binding effectué par la directive </p> <p app-child> 3. Host binding effectué par le composant </p>
Classe
(parent.component.ts)@Component({ selector: 'app-parent', template: './parent.component.html' }) export class ParentComponent { appliedStyles = 'background-color: yellow'; }
Cet exemple montre 3 applications de styles par bindings sur le composant Child
. Le template du composant Child
contient <ng-content></ng-content>
pour effectuer une projection de contenu (voir content projection pour plus de détails).
Les 3 exemples d’applications de styles sont:
- Un binding effectué dans le template du composant
Parent
:<p app-child applyGreenBackground [style]='appliedStyles'>1. Binding effectué dans le template</p>
Cet exemple montre que ce binding est le plus prioritaire.
- Un host binding effectué par une directive:
<p app-child applyGreenBackground>2. Host binding effectué par la directive</p>
La directive
ApplyGreenBackgroundDirective
modifie l’arrière-plan de son élément hôte avec le décorateur@HostBinding()
. - Un host binding efectué par le composant
Child
:<p app-child>3. Host binding effectué par le composant</p>
Le composant
Child
modifie l’arrière-plan de son élément hôte avec le décorateur@HostBinding()
.
On peut voir la priorité d’application des styles:
Pour résumer…
Dans une application Angular, on peut définir des styles ou des classes CSS de plusieurs façons:
- Globalement pour toute l’application, au niveau d’un ou plusieurs fichiers indiqué dans
angular.json
au niveau du paramètre styles:{ "projects": { "<nom du projet>": { "architect": { "build": { "options": { "styles": [ "src/styles.css" ] } } } } } }
- Plus spécifiquement aux éléments affichés dans la vue d’un composant en définissant les styles ou les classes:
- Dans des fichiers de style
.css
référencés au niveau du paramètrestyleUrls
du décorateur@Component()
du composant:@Component({ styleUrls: [ './<nom du composant>.component.css' ] })
- Directement dans la classe du composant en utilisant le paramètre style du décorateur
@Component()
:@Component({ styles: [ '<styles CSS>' ] })
- Dans des fichiers de style
Dans un fichier .css
, il est possibe d’importer un autre fichier CSS en indiquant directement son chemin relatif:
@import url('<chemin relatif du fichier CSS à importer>');
Par défaut, les styles définis dans un composant sont limités aux éléments de la vue de ce composant. On peut supprimer cette isolation en utilisant le paramètre encapsulation
du décorateur @Component()
:
@Component({
...
encapsulation: ViewEncapsulation.Emulated
})
Les différentes valeurs possibles de ce paramètre sont:
ViewEncapsulation.Emulated
(valeur par défaut): le style est isolé au composant. Angular effectue cette isolation en rajoutant des attributs_nghost
et_ngcontent
aux éléments HTML au moment de la compilation.ViewEncapsulation.ShadowDom
: le style est isolé au composant en utilisant la fonctionnalité Shadow DOM du browser.ViewEncapsulation.None
: le style n’est pas isolé au composant. Il sera appliqué à tous les éléments affichés à condition que la vue du composant soit affichée.
Appliquer un style ou une classe sur un élément d’un composant
Plusieurs méthodes sont possibles:
- Statiquement en utilisant les attributs
style
etclass
sur l’élément du template:<div style="background-color: yellow"> ... </div>
Ou
<div class="cssClassName"> ... </div>
- Par attribute binding:
<div [attr.style]="definedStyles"> ... </div>
definedStyles
est un membre de la classe contenant la chaîne de caractères avec le style.
Ou<div [attr.class]="definedClasses"> ... </div>
definedClasses
contient les classes sous forme de chaînes de caractères séparées par des espaces. - Par Property binding:
<div [style]="definedStyles"> ... </div>
definedStyles
peut être:- Une chaîne de caractères contenant les styles,
- Un tableau de chaînes de caractères contenant les styles,
- Une expression,
- Un object literal dont le nom des propriétés correspond au nom du style à appliquer. Le nom de la propriété doit être en Camel case.
Ou
<div [class]="definedClasses"> ... </div>
definedClasses
peut être:- Une chaîne de caractères contenant les noms de classe séparés par un espace,
- Un tableau de chaînes de caractères contenant les noms de classe,
- Un object literal dont le nom des propriétés correspond au nom de la classe, la valeur étant un booléan (
True
indique que la classe doit être appliquée,False
indique que la classe ne doit pas être appliquée).
On peut appliquer une seule propriété de style en utilisant les syntaxes:
- En Kebab case:
<div [style.background-color]="<membre de type string dans la classe du composant>"> ... </div>
- En Camel case:
<div [style.backgroundColor]="<membre de type string dans la classe du composant>"> ... </div>
De même on peut appliquer une seule classe avec la syntaxe:
<div [class.bluebackground]="<membre de type booléen dans la classe du composant>" ... </div>
Sélecteurs Angular
Angular permet d’utiliser les sélecteurs spécifiques pour affiner l’application des styles:
:host
applique un style à l’élément hôte de la vue d’un composant::host { /* Styles CSS */ }
Pour appliquer le style si le type de l’hôte est
<p>
::host(p) { /* Styles CSS */ }
Pour appliquer le style si la classe
redtest
est appliquée à l’hôte:.host(.redtext) { /* Styles CSS */ }
Pour appliquer le style si l’hôte est
<p>
sur les éléments<h1>
du composant::host(p) h1 { /* Styles CSS */ }
:host-context
permet d’appliquer un style suivant une condition sur un antécédent du composant::host-context(p) { /* Styles CSS */ }
Ce style est appliqué si un antécédent de la vue du composant est un élément
<p>
.Pour appliquer un style si la classe
redtest
est appliquée à un antécédent du composant::host-context(.redtext) { /* Styles CSS */ }
Pour appliquer un style si un antécédent est un élément
<p>
en limitant aux éléments<h1>
de la vue du composant::host-context(p) h1 { /* Styles CSS */ }
::ng-deep
permet d’appliquer un style ou une classe globalement. Le sélecteur::ng-deep
doit être utilisé avec le paramètreViewEncapsulation.Emulated
. Il faut placer::ng-deep
devant les sélecteurs pour lesquels on veut une application globale:::ng-deep p { /* Styles CSS */ }
Cette définition applique le style sur tous les éléments
<p>
.Pour appliquer un style si la classe
bluebackground
est appliquée sur un élément:::ng-deep .bluebackground { /* Styles CSS */ }
Pour appliquer un style sur les éléments
<p>
sur lesquels la classebluebackground
est appliquée:::ng-deep p.bluebackground { /* Styles CSS */ }
Dans l’exemple suivant, le style est appliquée spécifiquement aux éléments
<span>
du composant et globalement à tous les éléments<p>
:span ::ng-deep p { /* Styles CSS */ }
:host ::ng-deep
permet d’appliquer un style aux composants enfant::host ::ng-deep p { /* Styles CSS */ }
Le style sera appliqué aux éléments
<p>
du composant et de ses enfants.
Appliquer un style dans la classe d’un composant
@HostBinding()
: ce décorateur effectue un binding entre un membre de la classe et une propriété de l’objet du DOM qui est l’hôte du composant.export class ExampleComponent { @HostBinding('style.background-color') backgroundColor: string = 'cadetblue'; }
Cette implémentation permet d’appliquer la couleur
cadetblue
à la propriétébackground-color
de l’élément hôte du composantExample
.export class ExampleComponent { @HostBinding('class.bluebackground') applyBlueBackground: boolean = true; }
Cet exemple permet d’appliquer le classe
bluebackground
à l’élément hôte du composantExample
.ElementRef.nativeElement
: permet de s’interfacer avec l’objet du DOM d’un élément affiché sur la vue d’un composant. On peut appliquer un style ou une classe en passant par cet objet, par exemple:export class ExampleComponent implements OnInit { @ViewChild('content', { static: true }) contentElementRef !: ElementRef; constructor(private renderer: Renderer2) {} ngOnInit(): void { this.renderer.setStyle(this.contentElementRef.nativeElement, 'background-color', 'cadetblue'); this.renderer.setAttribute(this.contentElementRef.nativeElement, 'class', 'redtext'); } }
Dans cet exemple:
- On effectue une requête sur la vue du composant pour récupérer un objet identifié par une variable référence
#content
. - On affecte la couleur
cadetblue
à la propriété de stylebackground-color
de l’élément requêté. - On applique la classe
redtext
à cet élément requêté.
- On effectue une requête sur la vue du composant pour récupérer un objet identifié par une variable référence
Priorités d’application des styles sur un élément
Si des styles sont appliqués de façon concurrente sur un élément, la priorité d’application de ces styles se fait dans cet ordre:
- Property binding sur une propriété spécifique,
- Property binding en utilisant
[style]
, - Les styles appliqués statiquement.
Priorités d’application des styles sur l’hôte d’un composant
Si des styles sont appliqués de façon concurrente sur l’hôte d’un composant, la prorité d’application de ces styles se fait dans cet ordre:
- Bindings effectués sur l’hôte du composant
- Les host bindings effectués par une directive
- Les host bindings effectués par le composant
- What’s the difference between [style] and [ngStyle] in Angular?: https://blog.angulartraining.com/whats-the-difference-between-style-and-ngstyle-in-angular-68a3301c2ae6
- Component styles: https://angular.io/guide/component-styles
- Attribute, class, and style bindings: https://angular.io/guide/attribute-binding
- Style Precedence: https://angular.io/guide/style-precedence
- What to use in place of ::ng-deep: https://stackoverflow.com/questions/47024236/what-to-use-in-place-of-ng-deep/49308475#49308475
- How and where to use ::ng-deep?: https://stackoverflow.com/questions/46786986/how-and-where-to-use-ng-deep
- Setting Styles to DOM Element through Directive using Renderer2 in Angular8: https://medium.com/@anup.bangale/adding-styles-to-dom-element-through-angular-directive-1d8e4b10108f
- Angular NgStyle: How To Style Components In Angular 11/10: https://appdividend.com/2019/02/11/angular-7-ngstyle-tutorial-with-example-angular-ngstyle/
- @import: https://developer.mozilla.org/en-US/docs/Web/CSS/@import
- Using shadow DOM: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
- :host-context(): https://developer.mozilla.org/fr/docs/Web/CSS/:host-context()