填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫Home

元件樣式

Component styles

Angular 應用使用標準的 CSS 來設定樣式。這意味著你可以把關於 CSS 的那些知識和技能直接用於 Angular 程式中,例如:樣式表、選擇器、規則以及媒體查詢等。

Angular applications are styled with standard CSS. That means you can apply everything you know about CSS stylesheets, selectors, rules, and media queries directly to Angular applications.

另外,Angular 還能把元件樣式捆綁在元件上,以實現比標準樣式表更加模組化的設計。

Additionally, Angular can bundle component styles with components, enabling a more modular design than regular stylesheets.

本章將會講解如何載入和使用這些元件樣式

This page describes how to load and apply these component styles.

你可以執行現場演練 / 下載範例,在 Stackblitz 中試用並下載本頁的程式碼。

You can run the現場演練 / 下載範例in Stackblitz and download the code from there.

使用元件樣式

Using component styles

對你編寫的每個 Angular 元件來說,除了定義 HTML 範本之外,還要定義用於範本的 CSS 樣式、 指定任意的選擇器、規則和媒體查詢。

For every Angular component you write, you may define not only an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules, and media queries that you need.

實現方式之一,是在元件的元資料中設定 styles 屬性。 styles 屬性可以接受一個包含 CSS 程式碼的字串陣列。 通常你只給它一個字串就行了,如同下例:

One way to do this is to set the styles property in the component metadata. The styles property takes an array of strings that contain CSS code. Usually you give it one string, as in the following example:

src/app/hero-app.component.ts
      
      @Component({
  selector: 'app-root',
  template: `
    <h1>Tour of Heroes</h1>
    <app-hero-main [hero]="hero"></app-hero-main>
  `,
  styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}
    

範圍化的樣式

Style scope

@Component 的元資料中指定的樣式只會對該元件的範本生效。

The styles specified in @Component metadata apply only within the template of that component.

它們既不會被範本中嵌入的元件繼承,也不會被透過內容投影(如 ng-content)嵌進來的元件繼承。

They are not inherited by any components nested within the template nor by any content projected into the component.

在這個例子中,h1 的樣式只對 HeroAppComponent 生效,既不會作用於內嵌的 HeroMainComponent,也不會作用於應用中其它任何地方的 <h1> 標籤。

In this example, the h1 style applies only to the HeroAppComponent, not to the nested HeroMainComponent nor to <h1> tags anywhere else in the application.

這種範圍限制就是所謂的樣式模組化特性

This scoping restriction is a styling modularity feature.

  • 可以使用對每個元件最有意義的 CSS 類別名稱和選擇器。

    You can use the CSS class names and selectors that make the most sense in the context of each component.

  • 類別名稱和選擇器是侷限於該元件的,它不會和應用中其它地方的類別名稱和選擇器衝突。

    Class names and selectors are local to the component and don't collide with classes and selectors used elsewhere in the application.

  • 元件的樣式不會因為別的地方修改了樣式而被意外改變。

    Changes to styles elsewhere in the application don't affect the component's styles.

  • 你可以讓每個元件的 CSS 程式碼和它的 TypeScript、HTML 程式碼放在一起,這將促成清爽整潔的專案結構。

    You can co-locate the CSS code of each component with the TypeScript and HTML code of the component, which leads to a neat and tidy project structure.

  • 將來你可以修改或移除元件的 CSS 程式碼,而不用遍歷整個應用來看它有沒有在別處用到。

    You can change or remove component CSS code without searching through the whole application to find where else the code is used.

特殊的選擇器

Special selectors

元件樣式中有一些從影子(Shadow) DOM 樣式範圍領域(記錄在W3CCSS Scoping Module Level 1中) 引入的特殊選擇器

Component styles have a few special selectors from the world of shadow DOM style scoping (described in the CSS Scoping Module Level 1 page on the W3C site). The following sections describe these selectors.

:host

使用 :host 偽類別選擇器,用來選擇元件宿主元素中的元素(相對於元件範本內部的元素)。

Use the :host pseudo-class selector to target styles in the element that hosts the component (as opposed to targeting elements inside the component's template).

src/app/hero-details.component.css
      
      :host {
  display: block;
  border: 1px solid black;
}
    

:host 選擇是是把宿主元素作為目標的唯一方式。除此之外,你將沒辦法指定它, 因為宿主不是元件自身範本的一部分,而是父元件範本的一部分。

The :host selector is the only way to target the host element. You can't reach the host element from inside the component with other selectors because it's not part of the component's own template. The host element is in a parent component's template.

要把宿主樣式作為條件,就要像函式一樣把其它選擇器放在 :host 後面的括號中。

Use the function form to apply host styles conditionally by including another selector inside parentheses after :host.

下一個例子再次把宿主元素作為目標,但是只有當它同時帶有 active CSS 類別的時候才會生效。

The next example targets the host element again, but only when it also has the active CSS class.

src/app/hero-details.component.css
      
      :host(.active) {
  border-width: 3px;
}
    

:host 選擇器也可以與其他選擇器組合使用。在 :host 後面新增選擇器以選擇子元素,例如,使用 :host h2 定位元件檢視內的 <h2>

The :host selector can also be combined with other selectors. Add selectors behind the :host to select child elements, for example using :host h2 to target all <h2> elements inside a component's view.

不應該在 :host 選擇器前面新增除 :host-context 之外的選擇器來試圖基於元件檢視的外部上下文為本元件設定樣式。因為此類別選擇器的作用域不會限於元件的檢視,而是會選擇外部上下文,但這不是自然的行為。請改用 :host-context 選擇器。

You should not add selectors (other than :host-context) in front of the :host selector to style a component based on the outer context of the component's view. Such selectors are not scoped to a component's view and will select the outer context, but it's not native behavior. Use :host-context selector for that purpose instead.

:host-context

有時候,基於某些來自元件檢視外部的條件應用樣式是很有用的。 例如,在文件的 <body> 元素上可能有一個用於表示樣式主題 (theme) 的 CSS 類別,你應當基於它來決定元件的樣式。

Sometimes it's useful to apply styles based on some condition outside of a component's view. For example, a CSS theme class could be applied to the document <body> element, and you want to change how your component looks based on that.

這時可以使用 :host-context() 偽類別選擇器。它也以類似 :host() 形式使用。它在當前元件宿主元素的祖先節點中查詢 CSS 類別, 直到文件的根節點為止。在與其它選擇器組合使用時,它非常有用。

Use the :host-context() pseudo-class selector, which works just like the function form of :host(). The :host-context() selector looks for a CSS class in any ancestor of the component host element, up to the document root. The :host-context() selector is useful when combined with another selector.

在下面的例子中,只有當某個祖先元素有 CSS 類別 theme-light 時,才會把 background-color 樣式應用到元件內部的所有 <h2> 元素中。

The following example applies a background-color style to all <h2> elements inside the component, only if some ancestor element has the CSS class theme-light.

src/app/hero-details.component.css
      
      :host-context(.theme-light) h2 {
  background-color: #eef;
}
    

已棄用 /deep/>>>::ng-deep

(deprecated) /deep/, >>>, and ::ng-deep

元件樣式通常只會作用於元件自身的 HTML 上。

Component styles normally apply only to the HTML in the component's own template.

把偽類別 ::ng-deep 應用到任何一條 CSS 規則上就會完全禁止對那條規則的檢視包裝。任何帶有 ::ng-deep 的樣式都會變成全域性樣式。為了把指定的樣式限定在當前元件及其下級元件中,請確保在 ::ng-deep 之前帶上 :host 選擇器。如果 ::ng-deep 組合器在 :host 偽類別之外使用,該樣式就會汙染其它元件。

Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components.

這個例子以所有的 <h3> 元素為目標,從宿主元素到當前元素再到 DOM 中的所有子元素:

The following example targets all <h3> elements, from the host element down through this component to all of its child elements in the DOM.

src/app/hero-details.component.css
      
      :host ::ng-deep h3 {
  font-style: italic;
}
    

/deep/ 組合器還有兩個別名:>>>::ng-deep

The /deep/ combinator also has the aliases >>>, and ::ng-deep.

/deep/>>> 選擇器只能被用在模擬 (emulated) 模式下。 這種方式是預設值,也是用得最多的方式。 更多資訊,見控制檢視封裝模式一節。

Use /deep/, >>> and ::ng-deep only with emulated view encapsulation. Emulated is the default and most commonly used view encapsulation. For more information, see the View Encapsulation section.

CSS 標準中用於 "刺穿 Shadow DOM" 的組合器已經被棄用,並將這個特性從主流瀏覽器和工具中移除。 因此,我們也將在 Angular 中移除對它們的支援(包括 /deep/>>>::ng-deep)。 目前,建議先統一使用 ::ng-deep,以便相容將來的工具。

The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.

把樣式載入進元件中

Loading component styles

有幾種方式把樣式加入元件:

There are several ways to add styles to a component:

  • 設定 stylesstyleUrls 元資料

    By setting styles or styleUrls metadata.

  • 內聯在範本的 HTML 中

    Inline in the template HTML.

  • 透過 CSS 檔案匯入

    With CSS imports.

上述作用域規則對所有這些載入模式都適用。

The scoping rules outlined earlier apply to each of these loading patterns.

元資料中的樣式

Styles in component metadata

你可以給 @Component 裝飾器新增一個 styles 陣列型屬性。

You can add a styles array property to the @Component decorator.

這個陣列中的每一個字串(通常也只有一個)定義一份 CSS。

Each string in the array defines some CSS for this component.

src/app/hero-app.component.ts (CSS inline)
      
      @Component({
  selector: 'app-root',
  template: `
    <h1>Tour of Heroes</h1>
    <app-hero-main [hero]="hero"></app-hero-main>
  `,
  styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}
    

注意:這些樣式只對當前元件生效。 它們既不會作用於範本中嵌入的任何元件,也不會作用於投影進來的元件(如 ng-content )。

Reminder: these styles apply only to this component. They are not inherited by any components nested within the template nor by any content projected into the component.

當使用 --inline-styles 標識建立元件時,Angular CLI 的 ng generate component命令就會定義一個空的 styles 陣列

The Angular CLI command ng generate componentdefines an empty styles array when you create the component with the --inline-style flag.

      
      ng generate component hero-app --inline-style
    

元件元資料中的樣式檔案

Style files in component metadata

你可以透過把外部 CSS 檔案新增到 @ComponentstyleUrls 屬性中來載入外部樣式。

You can load styles from external CSS files by adding a styleUrls property to a component's @Component decorator:

      
      @Component({
  selector: 'app-root',
  template: `
    <h1>Tour of Heroes</h1>
    <app-hero-main [hero]="hero"></app-hero-main>
  `,
  styleUrls: ['./hero-app.component.css']
})
export class HeroAppComponent {
/* . . . */
}
    

注意:這些樣式只對當前元件生效。 它們既不會作用於範本中嵌入的任何元件,也不會作用於投影進來的元件(如 ng-content )。

Reminder: the styles in the style file apply only to this component. They are not inherited by any components nested within the template nor by any content projected into the component.

你可以指定多個樣式檔案,甚至可以組合使用 stylestyleUrls 方式。

You can specify more than one styles file or even a combination of styles and styleUrls.

當你使用 Angular CLI 的 ng generate component命令但不帶 --inline-style 標誌時,CLI 會為你建立一個空白的樣式表文件,並且在所產生元件的 styleUrls 中參考該檔案。

When you use the Angular CLI command ng generate componentwithout the --inline-style flag, it creates an empty styles file for you and references that file in the component's generated styleUrls.

      
      ng generate component hero-app
    

範本內聯樣式

Template inline styles

你也可以直接在元件的 HTML 範本中寫 <style> 標籤來內嵌 CSS 樣式。

You can embed CSS styles directly into the HTML template by putting them inside <style> tags.

src/app/hero-controls.component.ts
      
      @Component({
  selector: 'app-hero-controls',
  template: `
    <style>
      button {
        background-color: white;
        border: 1px solid #777;
      }
    </style>
    <h3>Controls</h3>
    <button (click)="activate()">Activate</button>
  `
})
    

你也可以在元件的 HTML 範本中寫 <link> 標籤。

You can also write <link> tags into the component's HTML template.

src/app/hero-team.component.ts
      
      @Component({
  selector: 'app-hero-team',
  template: `
    <!-- We must use a relative URL so that the AOT compiler can find the stylesheet -->
    <link rel="stylesheet" href="../assets/hero-team.component.css">
    <h3>Team</h3>
    <ul>
      <li *ngFor="let member of hero.team">
        {{member}}
      </li>
    </ul>`
})
    

當使用 CLI 進行建構時,要確保這個連結到的樣式表文件被複制到了伺服器上。參閱資產檔案配置指南

When building with the CLI, be sure to include the linked style file among the assets to be copied to the server as described in the Assets configuration guide.

只要參考過,CLI 就會計入這個樣式表,無論這個 link 標籤的 href 指向的 URL 是相對於應用根目錄的還是相對於元件檔案的。

Once included, the CLI will include the stylesheet, whether the link tag's href URL is relative to the application root or the component file.

CSS @imports 語法

CSS @imports

你還可以利用標準的 CSS @import 規則來把其它 CSS 檔案匯入到 CSS 檔案中。

You can also import CSS files into the CSS files using the standard CSS @import rule. For details, see @importon the MDN site.

這種情況下,URL 是相對於你正在匯入的 CSS 檔案的。

In this case, the URL is relative to the CSS file into which you're importing.

src/app/hero-details.component.css (excerpt)
      
      /* The AOT compiler needs the `./` to show that this is local */
@import './hero-details-box.css';
    

外部以及全域性樣式檔案

External and global style files

當使用 CLI 進行建構時,你必須配置 angular.json 檔案,使其包含所有外部資源(包括外部的樣式表文件)。

When building with the CLI, you must configure the angular.json to include all external assets, including external style files.

在它的 styles 區註冊這些全域性樣式檔案,預設情況下,它會有一個預先配置的全域性 styles.css 檔案。

Register global style files in the styles section which, by default, is pre-configured with the global styles.css file.

要了解更多,參閱 樣式配置指南

See the Styles configuration guide to learn more.

非 CSS 樣式檔案

Non-CSS style files

如果使用 CLI 進行建構,那麼你可以用 sasslessstylus 來編寫樣式,並使用相應的副檔名(.scss.less.styl)把它們指定到 @Component.styleUrls 元資料中。例子如下:

If you're building with the CLI, you can write style files in sass, less, or stylus and specify those files in the @Component.styleUrls metadata with the appropriate extensions (.scss, .less, .styl) as in the following example:

      
      @Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
...
    

CLI 的建構過程會執行相關的前處理器。

The CLI build process runs the pertinent CSS preprocessor.

當使用 ng generate component 命令產生元件檔案時,CLI 會預設產生一個空白的 CSS 樣式檔案(.css)。 你可以配置 CLI,讓它預設使用你喜歡的 CSS 前處理器,參閱工作區配置指南中的解釋。

When generating a component file with ng generate component, the CLI emits an empty CSS styles file (.css) by default. You can configure the CLI to default to your preferred CSS preprocessor as explained in the Workspace configuration guide.

新增到 @Component.styles 陣列中的字串必須寫成 CSS,因為 CLI 沒法對這些內聯的樣式使用任何 CSS 前處理器。

Style strings added to the @Component.styles array must be written in CSS because the CLI cannot apply a preprocessor to inline styles.