2025. 4. 17. 21:41ㆍCSS
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
리액트를 쓰다 보면 간혹 스타일이 “왜 안 먹지?” 싶은 경험을 하게 됩니다. 최근 작업 중 실제로 겪은 사례를 정리해 보겠습니다.
이런 코드, 왜 CSS가 적용이 안 될까?
다음과 같은 구조의 React 컴포넌트가 있다고 가정해 보겠습니다
<div className={cx(styles.shortsArea)}>
<Flag type={"shutter"} />
<Thumbnail src={thumUrl} alt={""} />
<div className={cx(styles.videoBox)}>
<video ...></video>
</div>
<div className={cx(styles.desc)}>{description}</div>
</div>
여기서 Thumbnail에 스타일을 적용하고 싶은데, 아래처럼 작성한 CSS가 전혀 먹히지 않았습니다.
.thumbnail {
bottom: 40px;
}
그런데 신기하게도 다음과 같이 수정하면 스타일이 정상적으로 적용됩니다.
.shortsArea {
[class*="thumbnail"] {
bottom: 40px;
}
}
왜 이걸 쓰는 경우가 생기냐면…
Thumbnail 컴포넌트가 외부에서 className을 전달받지 않도록 만들어져 있을 때가 있습니다. 혹은 외부 라이브러리에서 제공하는 컴포넌트라 우리가 내부 코드를 수정할 수 없는 경우도 있죠. 또 어떤 경우엔 단순히 컴포넌트를 열어 className을 추가하는 게 번거롭거나, 프로젝트 구조상 컴포넌트 내부를 직접 건드리는 걸 피하고 싶을 때도 있습니다. 이런 상황에서는 어쩔 수 없이 트릭성 방법을 쓰게 되는데, 이 포스트에서 다룬 [class*="thumbnail"] 같은 CSS 선택자가 바로 그런 경우에 사용되는 방법입니다.
스타일이 안 먹는 진짜 이유
예를 들어 React 컴포넌트 Thumbnail이 외부에서 className을 전달받지 않도록 아래와 같이 정의되어 있다면, 문제가 발생할 수 있습니다. 이렇게 구성된 경우 실제 HTML로 렌더링 될 때 <img> 태그에는 클래스 속성이 포함되지 않게 되고, 그 결과 .thumbnail로 지정한 CSS도 적용되지 않습니다. 결국 스타일이 적용되지 않았던 이유는 클래스 자체가 HTML에 존재하지 않았기 때문입니다.
interface ThumbnailProps {
src: string;
alt: string;
}
const Thumbnail = ({ src, alt }: ThumbnailProps) => {
return <img src={src} alt={alt} />;
};
그런데 CSS Modules나 styled-components를 사용하면 클래스명이 예를 들어 다음과 같이 자동 생성됩니다.
<img class="Thumbnail_thumbnail__a3Xk2" />
이때 [class*="thumbnail"] 선택자는 "thumbnail"이라는 문자열이 클래스명에 포함돼 있으므로, 우연히 스타일이 적용됩니다.
즉, 이건 엄밀히 말해 트릭입니다. 클래스명이 바뀌거나 컴파일 방식이 바뀌면 언제든지 깨질 수 있습니다.
React에서 스타일 제대로 먹이는 법
정석은 단순합니다: className을 명시적으로 넘기세요.
interface ThumbnailProps {
src: string;
alt: string;
className?: string; // 👈 className 추가
}
const Thumbnail = ({ src, alt, className }: ThumbnailProps) => {
return <img src={src} alt={alt} className={className} />;
};
이렇게 하면 .thumbnail 스타일이 정확하게 적용됩니다.
<Thumbnail src={thumUrl} alt="" className={styles.thumbnail} />
우연에 의존한 스타일 적용은 언젠가 깨질 폭탄입니다.
특히 CSS Modules, styled-components, tailwind 등 자동 클래스명 체계를 사용하는 경우에는 명시적인 className 전달이 필수입니다. 트릭을 알아두는 건 좋지만, 명시적이고 유지보수를 위해 항상 정석을 먼저 고려하세요.
[Terminal] nvm 설치 방법 및 오류 해결 하기
Node.js 버전을 관리하기 위해 많이 사용하는 nvm(Node Version Manager)을 설치하려 했으나, 터미널에서 nvm 명령어를 찾을 수 없다는 메시지가 출력되는 경우가 있습니다. 이번 포스팅에서는 nvm 설치 방
dev-chim.tistory.com
[VSCode] 초보자를 위한 VSCode 단축키 가이드: 빠르고 효율적인 개발을 위해
VSCode는 Microsoft에서 개발한 가벼우면서 강력한 오픈 소스 코드 편집기로, 다양한 플랫폼에서 널리 사용되고 있습니다. 이 글에서는 VSCode의 핵심 기능 중 하나인 단축키 설정하는 방법에 대해 다
dev-chim.tistory.com
Array APIs - indexOf(), lastIndexOf(), includes()
indexOf : 특정한 요소의 위치를 찾을 때 indexOf(searchElement: T, fromIndex?: number): number; /** * Returns the index of the first occurrence of a value in an array. * @param searchElement The value to locate in the array. * @param fromIndex Th
dev-chim.tistory.com
간단하게 Vite로 프로젝트 생성하는 방법
간단하게 Vite로 프로젝트 생성하는 방법에 대해서 알아보겠습니다. https://vitejs-kr.github.io/guide/ Vite Vite, 차세대 프런트엔드 개발 툴 vitejs-kr.github.io 선행 작업으로 node.js가 설치되어 있어야 합니다
dev-chim.tistory.com
[macOS] Mac에서 QuickTime Player로 화면 녹화하는 간단한 가이드 및 팁
Mac OS에서 기본적으로 제공되는 QuickTime Player를 사용하여 화면을 기록하는 방법에 대해 알아보겠습니다. QuickTime Player는 모든 Mac에 무료로 포함되어 있어 사용자들이 간편하게 화면을 녹화하고
dev-chim.tistory.com
'CSS' 카테고리의 다른 글
[CSS/defect] 특정 디바이스에서 터치 하이라이트 오류 수정 (feat. ios) (0) | 2025.05.16 |
---|---|
[CSS/SCSS] React에서 Swiper 스타일이 안 먹힐 때 – .swiper 대신 :global(.swiper)를 써야 하는 이유 (0) | 2025.04.16 |
[CSS] 입력폼에서 readonly와 disabled, 언제 어떻게 쓰고 스타일링할까? (0) | 2025.03.28 |
[CSS] CSS만으로 라디오 버튼 체크 시 요소 보이게 하기 (display: block) (0) | 2025.03.26 |
[CSS] inset과 position으로 완성하는 레이아웃 (0) | 2024.12.07 |