Skip to content

5. 컴포넌트 스타일


Angular 애플리케이션의 스타일은 표준 CSS를 사용해서 지정한다. 따라서 기존에 사용하고 있는 CSS 스타일시트, 셀렉터, 룰, 미디어 쿼리도 Angular 애플리케이션에 그대로 사용할 수 있다.


Angular는 여기에 추가로 개별 컴포넌트에 컴포넌트 스타일을 적용할 수 있으며, CSS 스타일 외에 다른 스타일 도구도 활용할 수 있다.


이 문서는 컴포넌트 스타일을 어떻게 불러오거나 지정할 수 있는지 안내한다.


이 문서에서 다루는 예제는 라이브 예제 링크 / 다운로드 링크에서 확인하거나 다운받을 수 있다.


1. 컴포넌트 스타일 사용하기

개발자가 만드는 모든 Angular 컴포넌트는 HTML 템플릿 외에 CSS 스타일도 지정할 수 있다. 이 스타일 설정에는 기존에 사용하던 셀렉터, 룰, 미디어 쿼리도 그대로 사용할 수 있다.


가장 간단한 방법은 컴포넌트 메타데이터에 styles 프로퍼티를 사용하는 것이다. styles 프로퍼티에는 CSS 코드를 문자열 배열 형태로 지정하며, 다음과 같이 문자열 하나로도 간단하게 지정할 수 있다:


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 {
  /* . . . */
}


2. 스타일 적용 범위

Note

  • @Component 메타데이터에 지정한 스타일은 그 컴포넌트의 템플릿에만 적용된다.


컴포넌트 스타일은 템플릿 안에 있는 자식 컴포넌트의 템플릿이나 이 컴포넌트에 프로젝트되는 컴포넌트에는 적용되지 않는다.


이 예제로 보면 h1 엘리먼트 스타일은 HeroAppComponent에만 적용되며, 자식 컴포넌트 HeroMainComponent나 컴포넌트 외부에 있는 <h1> 태그에는 적용되지 않는다.


그래서 컴포넌트에 적용되는 스타일은 다음과 같은 스타일 모듈 규칙을 따른다.


  • 컴포넌트를 구분하기 위해 적절한 CSS 클래스 이름과 셀렉터를 사용할 수 있다.
  • 클래스 이름과 셀렉터는 컴포넌트 안에서만 유효하며, 컴포넌트 밖에 있는 클래스와 셀렉터에는 적용되지 않는다.
  • 컴포넌트 밖에서 스타일이 동적으로 변경되어도 컴포넌트에는 적용되지 않는다.
  • 프로젝트 규모가 작거나 간단하게 테스트 하려면 CSS 코드를 TypeScript 코드나 HTML에 작성할 수 있다.
  • 컴포넌트에 적용되는 CSS 코드는 컴포넌트 외부에 적용되지 않기 때문에 걱정없이 변경하거나 제거할 수 있다.


3. Angular 전용 셀렉터

컴포넌트에 스타일 문법에는 섀도우 DOM에 적용할 수 있는 특별한 셀렉터 몇 가지를 사용할 수 있다. 이 셀렉터들은 W3C  사이트의 CSS Scoping Module Level 1에서 정의하는 표준 셀렉터이다.


1) :host

컴포넌트는 컴포넌트 셀렉터와 같은 이름의 엘리먼트 안에 구성된다. 이 엘리먼트는 이후에 템플릿에 렌더링되는데, 이 엘리먼트가 렌더링되는 위치를 호스트 엘리먼트(host element)라고 한다. :host 가상 클래스 셀렉터는 이 호스트 엘리먼트를 가리킨다. 대상 엘리먼트(targeting elements)는 호스트 엘리먼트 안에 들어가는 엘리먼트로, 호스트 엘리먼트와는 반대 개념이다.


src/app/host-selector-example.component.ts
@Component({
  selector: "app-main",
  template: `
    <h1>It Works!</h1>
    <div>Start editing to see some magic happen :)</div>
  `,
})
export class HostSelectorExampleComponent {}


컴포넌트의 호스트 엘리먼트에 스타일을 지정해 보자. :host 셀렉터를 붙여 지정하는 규칙은 호스트 엘리먼트와 그 자식 엘리먼트에 영향을 미친다.


:host 셀렉터는 컴포넌트의 호스트 엘리먼트만 대상으로 지정할 수 있다. 그래서 :host 블록 안에 선언한 스타일은 모두 부모 컴포넌트에 영향을 미치지 않는다.


아래 예제처럼 구현하면 호스트 엘리먼트에 active CSS 클래스가 지정되었을 때 텍스트를 굵게 표시한다.


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

:host(.active) {
  font-weight: bold;
}


:host 셀렉터는 다른 셀렉터와 조합해서 사용할 수 있다. 그래서 :host h2와 같이 작성하면 모든 컴포넌트 뷰에 있는 엘리먼트 중에서 모든 <h2>를 대상으로 지정할 수 있다.


Note

  • :host 셀렉터 앞에는 다른 셀렉터(:host-context 제외)를 사용할 수 없다.
  • :host 셀렉터는 컴포넌트의 뷰를 대상으로 하기 때문에 외부 컨텍스트를 지정할 수 없다.
  • 외부 컨텍스트와 연동하려면 :host-context 셀렉터를 사용해야 한다.


2) :host-context

때로는 호스트 엘리먼트의 부모 엘리먼트의 조건에 따라 컴포넌트 템플릿의 스타일을 적용해야 하는 경우가 있다. HTML 문서의 <body> 엘리먼트에 CSS 테마 관련 클래스가 지정된다면 이 조건에 따라 컴포넌트의 모습을 변형하는 경우가 그렇다.


이 때 :host-context 가상 클래스 셀렉터를 사용하면 :host()를 사용할 때와 비슷하게 컴포넌트 밖에 있는 엘리먼트를 가리킬 수 있다. :host-context() 셀렉터는 컴포넌트가 위치하는 호스트 엘리먼트의 부모 엘리먼트로부터 HTML 문서의 루트 노드까지 적용된다. 이 셀렉터는 다른 셀렉터와 마찬가지로 조합해서 사용할 수도 있다.


아래 예제 코드는 호스트 엘리먼트의 부모 엘리먼트 중에 active CSS 클래스가 지정되었을 때 텍스트에 이탤릭 스타일을 지정하는 예제 코드이다.


src/app/hero-details.component.css
:host-context(.active) {
  font-style: italic;
}


호스트 엘리먼트와 그 자식 엘리먼트만 영향을 받는다는 것이 중요하다. active 클래스가 지정된 호스트 엘리먼트의 부모 엘리먼트는 영향을 받지 않는다.


4. 컴포넌트 스타일 지정하기

컴포넌트에 스타일을 지정하려면 다음과 같은 방법을 활용할 수 있다.


  • 컴포넌트 메타데이터에 style이나 styleUrls 사용하기
  • 템플릿 HTML에 인라인으로 지정하기
  • 외부 CSS 파일 불러오기


1) 컴포넌트 메타데이터로 스타일 지정하기

@Component 데코레이터에는 styles 프로퍼티를 지정할 수 있다.


이 프로퍼티는 문자열 배열을 사용하는데, 컴포넌트에 지정될 CSS 스타일을 문자열로 각각 지정한다.


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 {
  /* . . . */
}


Note

  • 이 방법으로 지정하는 스타일은 이 컴포넌트에만 적용된다.
  • 템플릿 안에 있는 자식 컴포넌트나, 이 컴포넌트에 프로젝트되는 다른 컨텐츠에도 적용되지 않는다.


Angular CLI로 ng generate component 명령을 실행할 때 --inline-style 플래그를 지정하면 styles 배열이 비어있는 상태에서 컴포넌트 코드 개발을 시작할 수 있다.


ng generate component hero-app --inline-style


2) 컴포넌트 메타데이터에 외부 스타일 파일 불러오기

컴포넌트의 @Component 데코레이터에 styleUrls 프로퍼티를 사용하면 컴포넌트 외부에 있는 CSS 파일을 불러와서 컴포넌트에 적용할 수 있다.


@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 {
  /* . . . */
}
h1 {
  font-weight: normal;
}


Note

  • 이 방법으로 지정하는 스타일은 이 컴포넌트에만 적용된다.
  • 템플릿 안에 있는 자식 컴포넌트나, 이 컴포넌트에 프로젝트되는 다른 컨텐츠에도 적용되지 않는다.
  • styles이나 styleUrls 프로퍼티에는 한 번에 여러 스타일을 지정하거나 여러 파일을 지정할 수 있다.


Angular CLI로 ng generate component 명령을 실행할 때 --inline-style 플래그를 지정하지 않으면 컴포넌트 이름으로 스타일 파일을 만들고 컴포넌트 메타데이터의 styleUrls에서 이 파일을 참조한다.


ng generate component hero-app


3) 템플릿 인라인 스타일

CSS 스타일은 <style> 태그를 사용해서 HTML 템플릿 안에 지정할 수도 있다.


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> 태그를 사용할 수도 있다.


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>`
})


Note

  • Angular CLI가 애플리케이션을 빌드할 때 링크로 연결된 스타일 파일이 assets 폴더에 있고 빌드 결과에 제대로 포함되는지 꼭 확인한다.
  • 스타일 파일이 assets 폴더에 있다면 CLI가 이 스타일 파일을 빌드 결과물에 포함시키며, 컴포넌트에서는 애플리케이션 최상위 경로나 컴포넌트 파일의 상대 경로로 이 스타일 파일을 참조할 수 있다.


5) CSS @imports

외부 CSS 파일을 불러올 때는 CSS 표준인 @import를 사용하는 방법도 있다.


Note

  • 이 문법에 대해 자세하게 알아보려면 MDN 사이트의 @import문서를 참고한다.


이 경우에는 CSS 파일을 로드하는 컴포넌트에서 시작하는 상대 경로로 외부 CSS 파일의 URL을 지정한다.


src/app/hero-details.component.css (excerpt)
/* AOT 컴파일러를 사용한다면 이 파일이 로컬에 있다는 것을 지정하기 위해 주소가 `./`로 시작되어야 합니다. */
@import "./hero-details-box.css";


6) 전역 스타일 파일

Angular CLI로 애플리케이션의 빌드 설정 파일인 angular.json 파일은 빌드에 포함될 모든 외부 자원을 지정하는데, 이 때 외부 스타일 파일을 지정할 수도 있다.


이 때 styles 항목을 활용하면 전역으로 지정될 스타일 파일을 지정할 수 있으며, CLI로 생성한 프로젝트라면 styles.css 파일이 초기값으로 지정된다.


7) CSS 이외의 스타일 파일

Angular CLI를 사용한다면 sass나 less를 사용할 수도 있으며, 이렇게 만든 스타일 파일은 @Component.styleUrls 메타데이터에 다음과 같이 지정할 수 있다:


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


그러면 Angular CLI에 정의된 CSS 프리프로세서를 통해 최종 결과물에는 CSS 스타일로 변환된다.


ng generate component 명령으로 컴포넌트를 생성하면 비어있는 CSS 파일(.css)이 기본으로 생성된다.


Note

  • @Component.styles에 문자열로 지정하는 스타일은 반드시 CSS 문법으로 지정해야 한다.
  • Angular CLI는 인라인 스타일을 처리할 때 CSS 프리프로세서를 별도로 사용하지 않는다.

References