0%

Angular-class-and-style-binding-Style 綁定 和 css style優先序

起源

接續 動態綁定 class 系列 的文章。

學習點

記錄為目標元素動態增減 style 的方法。

綁定單一個 stlye

綁定單一的 style 到指定元素上,其寫法為在要加入的 CSS 樣式前面加上 style 的前綴詞,再用 dot 將它們連在一起。

另外,你也可以指定單位(e.g.: px, em)到要加入的 CSS style,但是,輸入的設定值就必須要是數字。

<p [style.color]="'red'" [style.font-size.px]="'40'”>paragraph</p>

有 hyphen 的 css style 寫法
另外,像是 background-color 這種 css style,你可以選擇用 hyphen 寫法,也可以用 camelCase 寫法

<div [style.background-color]="'red'">background red<div> (hyphen)

或者

<div [style.backgroundColor]="'red'">background red<div> (camelCase)

綁定多個 style

同時綁定多個 style 到一個元素裡面,有以下兩種寫法

1. 綁定一個字串
這個寫法,就是將你要加入的 style 直接都寫在這個字串裡面

1
2
3
4
5
6
7
@Component({
selector: 'app-root',
template: `<div [style]="styleStr"> a string style </div>`
})
export class AppComponent {
styleStr = 'background-color: red; font-size: 40px;'
}

2. 綁定一個物件 - 注意含有 hyphen 的 style 的成員屬性名稱設定方法
這個物件的成員屬性名稱就是 style 的名稱,它的值就是該 style 的值。

1
2
3
4
5
6
7
8
9
10
11
@Component({
selector: 'app-root',
template: `<div [stlye]="styleObj">a string style</div>`
})
export class AppComponent {
styleObj = {
'background-color': 'red', // 有 hyphen 的 style 的成員屬性要加單引號包起來
backgroundColor: 'red', // 上面的屬性,也可以選擇用 camelCase 的寫法
border: '2px solid #000'
}
}

上面的範例,就是示範了當 style 的名稱有 hyphen 在裡面的話,其屬性名稱的撰寫方式,可以用 camelCase 或者 用單引號包起來 來做撰寫,而一般的 css style 的屬性名稱,就可以直接當作成員屬性的名稱。

Style Precedence

當某個 html 元素上,有加入相同的 class 或者 相同的 style 的時候,Angular 會有它自有的規則來判斷哪一個方法加入的 class 或 style 的順位是最高的。

判定的規則如下:
1. 直接在 template 上面寫綁定,順位最高
1-1 直接在 template 上,寫的 class 或 style 綁定指定的樣式 順位最高

1
2
3
--- app.component.html --
<div [class.specific]="hasFoo"></div>
<div [style.specific]="color"></div>

1-2 直接在 template 上寫的 generic class or style 綁定順位比 1-1 低

1
2
3
--- app.component.html ---
<div [class]="classObj"></div>
<div [style]="styleObj"></div>

1-3 直接在 template 上寫單純的 class 或 style 比上面 1-1 和 1-2 還低

1
2
3
--- app.component.html ---
<div class="modal"></div>
<div style="background-color: red;"></div>

把 1-1 ~ 1-3 的順位整合在同一元素,判斷一下是哪一個 style 會勝出

1
2
3
4
5
6
7
8
9
10
11
--- app.component.html ---
<p
[style.background-color]="'#fa0'"
[style]="styleObj"
style="background-color: blue;"
> This is paragraph</p>

--- app.component.scss ---
.styleObj {
background-color: red;
}

依照上面寫的規則,最後,p段落的背景色會是 #fa0

2. 在 directive 寫的 host binding,順位第二高
在 directive 裡,利用 @HostBinding 所綁定的 style 或 class 的順位會是第二高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--- button-decorator.directive.ts ---
@Directive({
selector: '[appButtonDecorator]'
})
export class ButtonDecoratorDirective {
@HostBinding('class.decoratorClass') hasValue = true;
@HostBinding('style.color') color = 'red';
}


--- app.component.html ---
<button
type="button"
appButtonDecorator
>Change Button</button>

3. 在 component 寫的 @HostBinding,順位最低

1
2
3
4
5
6
7
8
9
10
11
12
--- child.component.ts---
@Component({
selector: 'child-comp',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent {
@HostBinding('style') style = 'color: red;';
}

--- app.component.html ---
<child-comp [style.color]="blue">This is a paragraph</child-comp>

以上範例的 @HostBinding 加入的 color: red 會被直接加在元素上的 [class.color]="'blue'" 給蓋掉。

以下,我把 class binding 和 style biding 的優先序整理成下面這張圖
style precedence

Conclusion

  1. 藉由這系列文章的規則歸納,我們就知道如何動態地為目標元素加入指定的 class 或 style,以此來變換該元素的樣式。
  2. 得知用不同方法加入的 class 或 style 之間是有優先順序之分的。

Appendix

Style Precedence - includes component inline style
以上這系列的文章,都是特別針對加諸在單一元素上的 style 優先序做紀錄,
在最後,我要把 @Component 自身的 inline style 的部分也納入 style Priority 的排序

以下是納入 @Component inline style 的優先序,由高到低

  1. @Component.styles
    這個是代表寫在 @Component 區塊的 styles 屬性裡的 css 樣式
  2. @Component.styleUrls
    這個是代表寫在 @Component 區塊的 styleUrls 屬性裡,引用指定路徑的檔案的 css 樣式
  3. [class.specific] && [style.specific]
  4. generic style: [class] && [style]
  5. inline style: class && style
  6. Directive style
  7. Component @HostBinding style

Reference

  1. Angular Style Priority
  2. Angular Official Introduction of style binding