가수면

Vuetify 컴포넌트 자식 요소의 스타일 커스텀하는 방법 본문

Vue

Vuetify 컴포넌트 자식 요소의 스타일 커스텀하는 방법

니비앙 2024. 8. 26. 16:25

vuetify를 이용해 작업하다보면 v-select와 v-autocomplete 등을 사용할 때 input이나  placeholder, 드롭다운 등의 스타일을 커스텀하고 싶은 때가 온다.

이 경우 스타일을 수정하는 데에는 크게 2가지 방법이 있다.

1. 선택자를 사용해 스타일을 수정하는 법

먼저 두 가지 방법이 있다.

전역적으로 적용하는 방법, 컴포넌트 내에서 scoped를 사용해 컴포넌트 단위로 적용하는  방법

 

1. 전역적으로 적용하는 방법

별 거 없이 import된 scss나 css 파일에 클래스를 설정해주면 된다.

클래스는 개발자 도구로 열어서 타게팅할 요소의 클래스를 직접 확인해서 지정해주면 된다.

.v-list-item-title {
  font-size: 14px;
}

or

.custom-selector .v-list-item-title {
  font-size: 14px;
}

2. 컴포넌트 단위로 적용하는 방법

이 경우 :deep을 이용해 api의 하위 클래스를 지정해줘야 선택자가 적용이 된다.

.search-selector {
  width: 175px;
  :deep(input) {
    margin-top: 2px;
    height: 25px;
  }
  :deep(input::placeholder) {
    font-size: 14px;
  }
  :deep(.v-select__selection-text) {
    font-size: 14px;
  }
}

위 방법은 vue3에서 사용하는 방법으로, vue2.x 버전에서는 아래처럼 사용한다.

.filter-wrapper {
  ::v-deep {
    .v-input__slot,
    .v-text-field__slot,
    input,
    input::placeholder,
    .v-autocomplete__selection-text,
    .v-list-item__title {
      font-weight: 600;
    }
  }
}

2. props로 스타일 및 클래스를 부여하는 방법

v-select와 v-autocomplete를 예시로 설명한다.

먼저 v-list나 v-menu같은 api를 사용하는 컴포넌트들은 menu-props, item-props를 통해 자식 요소에 속성을 부여할 수 있다.(item-props의 경우 상위 스타일로 인해 스타일이 안 먹는 경우가 있기 때문에 menu-props를 사용하는 방법이 권장된다. )

공식 문서에 menu-props, item-props로 검색해서 나오는 컴포넌트들은 다 통용되는 방법이다.

          <v-select
            :items="searchSortOptions"
            v-model="searchSort"
            placeholder="정렬"
            variant="solo"
            class="menu-select-filter menu-select-autocomplete search-selector"
            density="compact"
            hide-details
            item-title="label"
            item-value="value"
            :menu-props="{ contentClass: 'search-selector-menu' }"
            :item-props="() => ({ class: 'search-selector-item' })"
          >
          </v-select>

 

포맷은 위와 같은데, 이 경우 menu-props는 드롭다운 최상위 요소에, item-props는 option의 최상위 요소에 속성이 적용된다.

 

이렇게 속성이 부여된 드롭다운이 열리게 되면 아래처럼 렌더링이 된다.

드롭다운이 열렸을 때의 html 요소 예시)

<div class="v-overlay-container">
  <div
    class="v-overlay v-overlay--absolute v-overlay--active v-theme--defaultTheme v-locale--is-ltr v-menu"
    id="v-menu-32"
    style="z-index: 2000;"
  >
    <!---->
    <div
      class="v-overlay__content search-selector-menu"
      style="max-height: 310px; max-width: 1867px; min-width: 175px; --v-overlay-anchor-origin: bottom left; transform-origin: left top; top: 231px; left: 1080px;"
    >
      <div
        class="v-list v-theme--defaultTheme v-list--density-default v-list--one-line"
        tabindex="-1"
        role="listbox"
        aria-live="polite"
      >
        <!---->
        <!---->
        <div class="v-virtual-scroll__spacer" style="padding-top: 0px;"></div>

        <div
          class="v-list-item v-list-item--link v-theme--defaultTheme v-list-item--density-default v-list-item--one-line v-list-item--variant-text search-selector-item"
          tabindex="-2"
          role="option"
        >
          <span class="v-list-item__overlay"></span>
          <span class="v-list-item__underlay"></span>
          <div class="v-list-item__prepend">
            <!---->
            <!---->
            <!---->
            <div class="v-list-item__spacer"></div>
          </div>
          <div class="v-list-item__content" data-no-activator="">
            <div class="v-list-item-title">국가명 오름차순 ▲</div>
            <!---->
            <!---->
          </div>
          <!---->
        </div>

        <div
          class="v-list-item v-list-item--link v-theme--defaultTheme v-list-item--density-default v-list-item--one-line v-list-item--variant-text search-selector-item"
          tabindex="-2"
          role="option"
        >
          <span class="v-list-item__overlay"></span>
          <span class="v-list-item__underlay"></span>
          <div class="v-list-item__prepend">
            <!---->
            <!---->
            <!---->
            <div class="v-list-item__spacer"></div>
          </div>
          <div class="v-list-item__content" data-no-activator="">
            <div class="v-list-item-title">국가명 내림차순 ▼</div>
            <!---->
...

주의할 점은 v-selector나 v-autocomplate 요소의 위치에서 생성되는 것이 아니라, html 최상위 수준에 위치한 v-overlay 요소에 포탈처럼 생성된다는 것이다.

그렇게 때문에 드롭다운은 scoped로 스타일을 수정할 수 없다!!!

 

그렇기 때문에 이 경우는 1번의 전역적으로 스타일을 적용하는 방법을 통해서만 지정이 가능하다.

예시)

.search-selector-menu .v-list-item-title {
  font-size: 14px;
}

'Vue' 카테고리의 다른 글

[Vue] 심화  (0) 2024.05.25
[Vue] 전역 상태 관리  (0) 2024.05.16
[Vue] Router  (0) 2024.05.16
[Vue] Composition API 방식  (0) 2024.05.13
[Vue] 기본  (0) 2024.05.13
Comments