CSS Pseudo Element와 svg 태그

부루베릐·2022년 12월 1일
0

TIL

목록 보기
5/18
post-thumbnail

::after와 같은 CSS 의사 요소들은 인라인 svg 요소에 적용시킬 수 없는가?

사용자가 읽지 않은 새 알림을 받았을 때, 다음과 같이 알림 아이콘에서 오른쪽 상단에 빨간색 점을 표시하는 기능이 있다. 기존 코드에서는 밑과 같은 로직으로 새 알림 표시 기능을 구현하였다.

기존에는 fantasticon을 사용하여 아이콘을 생성했다. 때문에 i 태그의 클래스 이름을 사용하고자 하는 아이콘 이름으로 설정하여 아이콘 svg를 가져와 쓸 수 있다.

// javascript
<nuxt-link
  :class="{ 'noti-count': isNotiCheck() }"
  :to="'/notifications'"
>
	<i
	  class="nav-icon"
	  :class="icon-ic_bell" // fantasticon에서 아이콘 사용하는 방식. 
	/>
</nuxt-link>

i 태그에 ::after 의사 요소를 사용하여 빨간색 점 요소를 만들어준다.

// css

.noti-count {
  .nav-icon {
    position: relative;

    &::after {
      content: '';
      position: absolute;
      right: 0;
      top: 0;
      width: 3.75px;
      height: 3.75px;
      background-color: $red40;
      border-radius: 3.75px;
    }
  }
}

로직을 보면 isNotiCheck를 통해 알림이 있을 때 noti-count 클래스를 바인딩하므로, 위의 nav-icon 스타일은 알림이 있을 때에만 적용된다.

문제는 내가 i 태그와 fantasticon을 통한 아이콘 사용을 inline svg 컴포넌트로 변경하였다는 것. fantasticon이 생각보다 완전하지 않아서 일부 구간이 색이 채워진 상태로 나타나는 오류가 있었다. 따라서 지금의 코드는 다음과 같이 인라인 svg 요소를 컴포넌트로 받아서 사용 중이다.

<nuxt-link
  :class="{ 'noti-count': isNotiCheck(to) }"
  :to="nav.to"
>
  <ic-bell class="nav-icon" />
</nuxt-link>

...

import icBell from "@/assets/icons/ic_bell.svg?inline"

그럼 다음과 같이 svg 태그에 ::after 의사 요소가 적용되는데, 문제는 이 스타일이 먹히지 않는다는 것이다.

그 원인은 의사 요소가 적용될 수 있는 조건이 자식 요소를 가질 수 있는 요소들에게로 한정되기 때문이다. divspan를 위시한 대부분 HTML 요소들의 경우에는 자식 요소를 당연히 가질 수 있고, 그렇기 때문에 당연히 의사 요소 역시 가질 수 있다.

그러나 <img />, <video />, <input />의 경우는 자식 요소를 가질 수 없다. 따라서 의사 요소들이 적용되지 못하고, 따라서 svg 역시 마찬가지일 것이라 추측할 수 있다.

CodePen 예시 코드

실제로 div 요소와 input 요소를 비교하였을 때, 전자는 ::after가 적용되지만 후자는 적용되지 않는 것을 볼 수 있다.

실제 코드에서는 svg 태그를 wrapper 역할을 하는 div로 둘러 싸 해당 wrapper에 ::after를 먹여 해결하였다.

<nuxt-link
  :class="{ 'noti-count': isNotiCheck(to) }"
  :to="nav.to"
>
  <div class="nav-icon">
  	<ic-bell />
  </div>
</nuxt-link>

실제로 ::after와 같은 CSS 의사 코드를 사용해본 것이 처음이었다. 아예 새로운 요소를 오로지 CSS를 통해서 구현할 수 있다는 점에서 편리한 점이 있으나, 앞에서 본 것과 같은 예외 케이스 역시 존재한다는 것을 유념하여 사용하면 더 확실하게 사용할 수 있을 듯하다.

참고자료

CSS :before on inline SVG

Pseudo-elements

0개의 댓글