콘텐츠로 이동

CSS specificity와 워드프레스 wpautop 함정

워드프레스 본문에 CSS 박을 때 만나는 두 가지 함정. 2026-05-08 루피엘 고객후기 발행하면서 만난 사건 정리.


1. CSS specificity = 도장 권한 같은 것

비유

회사에서 같은 종이에 여러 도장이 찍혔다. - 사원 도장 (일반 셀렉터, 약함) - 팀장 도장 (specific 셀렉터, 더 강함) - 사장 도장 (!important, 같은 권한 레벨에서 최강)

이때 팀장 도장이 박은 결정을 사원이 자기 도장에 !important 찍는다고 뒤집을 수 없다. 권한 자체가 더 위니까.

CSS도 똑같다. 충돌하는 규칙이 여러 개일 때, 셀렉터가 더 자세할수록(specific) 우선권이 강하다. !important는 같은 specificity 레벨에서만 최강이지, 더 specific한 외부 규칙은 못 이긴다.

실제 사건

medinterior.com 워드프레스 글에서 사진 캡션을 가운데 정렬하려고 했다.

<figcaption style="text-align:center !important;">캡션</figcaption>

안 됨. 캡션이 여전히 좌측 정렬.

이유: 테마 CSS에 이런 게 있었다.

.entry-content figure figcaption {
  text-align: left;
}

이건 figcaption 단독보다 훨씬 specific한 셀렉터(클래스 + 자손 선택자 조합). 그래서 inline !important는 같은 권한 레벨에서만 최강이지, 위 권한이 박은 건 못 덮음.

해결법

같거나 더 specific한 셀렉터로 맞붙는다.

<style>
.entry-content figure figcaption {
  text-align: center !important;
}
</style>

같은 .entry-content figure figcaption 셀렉터에 !important 붙이면 그 위에서 정한 좌측 정렬을 이긴다.

specificity 계산법 (간단 버전)

단위 점수
inline style (style="...") 1000
#id 100
.class, :hover 10
tag, ::before 1

예시: - figcaption = 1점 - .wp-element-caption = 10점 - .entry-content figure figcaption = 10 + 1 + 1 = 12점 - style="..." = 1000점

점수 높은 게 이긴다. 같은 점수면 나중에 선언된 게 이긴다. !important는 같은 점수 레벨에서만 우선.

디버깅 팁

CSS가 안 먹을 때: 1. 크롬 개발자도구(F12) → 해당 요소 선택 → "Computed" 탭 2. 어떤 규칙이 이기고 있는지(취소선 그어진 규칙들) 확인 3. 같은/더 specific한 셀렉터로 룰 만들고 !important 붙이기

→ 다음에 어떤 사이트에서든 CSS 적용 안 될 때 "내가 박은 것보다 더 specific한 룰이 있나?" 가장 먼저 의심.


2. wpautop = 친절하지만 가끔 사고 치는 워드프레스 비서

비유

워드프레스가 "사용자가 단락 태그(<p>) 일일이 안 써도 글이 잘 보이게 해줘야지!" 하고 자동으로 줄바꿈을 단락으로 변환해주는 친절한 비서를 두고 있다. 그게 wpautop() 함수.

사용자 입력:
첫 줄.
둘째 줄.

→ wpautop이 자동 변환:
<p>첫 줄.<br />
둘째 줄.</p>

편의 기능이라 평소엔 좋다. 근데 이 비서가 <style> 블록 안의 CSS까지 손대버린다.

실제 사건

본문에 CSS를 박았다.

<style>
.entry-content figure {
  text-align: center !important;
}
</style>

→ 사용자가 비주얼 에디터에서 글 한 번 편집·저장하면 wpautop이 작동:

<style>
.entry-content figure {<br />
  text-align: center !important;<br />
}<br />
</style>

CSS 안에 <br />가 들어가 문법 자체가 깨짐. 결과적으로 모든 스타일이 무효화되어 캡션이 다시 좌측 정렬로 돌아갔다.

회피법 1: 한 줄 minify

<style> 블록을 줄바꿈 없이 한 줄로 박으면 wpautop이 손 못 댄다.

<style>.entry-content figure { text-align: center !important; } .entry-content figure figcaption { text-align: center !important; }</style>

읽기 어렵지만 안전하다.

회피법 2 (영구 해결, 추천)

본문이 아니라 테마 옵션에 박는다.

워드프레스 관리자 → 외모 → 사용자 정의(Customize) → 추가 CSS

여기 박은 CSS는: - 테마 옵션이라 본문 sanitize 영향 0 - 모든 글에 자동 적용 - 본문 편집해도 안 깨짐 - 한 번만 박으면 끝

본문에 매번 <style> 박지 않아도 됨. 새 글 발행할 때 figure HTML만 잘 짜면 자동으로 가운데 정렬됨.

다른 sanitize 함정도 같이 알아두기

워드프레스가 본문 저장 시 자동으로 처리하는 것들: - 빈 <p></p> 단락 → 제거됨 (빈 줄 띄움이 안 됨) - <p>&nbsp;</p> → 살아남음 (실전에서 빈 줄 띄울 때 이걸 씀) - <p>​</p> (제로폭공백) → 가장 안정적. wpautop 거쳐도 그대로 살아남음 (5/14 검증) - 사용자가 명시한 <p>본문</p>일부 변형됨! REST API로 보내면 인접한 <figure>/<div> 다음의 <p> 태그가 통째로 제거되는 경우 있음. 본문 안에 <p> 직접 박지 말고 텍스트 + 빈 줄(\n\n)로 분리 → wpautop이 자동으로 <p> 박아주는 게 가장 안전 (5/14 책 출간 글 발행 시 발견) - wp-block-spacer div → 살아남음 (큰 여백용) - <style> 블록 → 살아있지만 줄바꿈은 변환됨 (한 줄로!) - <script> 블록 → 권한 따라 제거될 수 있음 (administrator는 살아남음)

5/14 책 출간 글 발행에서 정착된 안전 패턴

# ❌ 안 됨: <p> 직접 박으면 일부 제거됨
content = "<p>안녕하세요.</p>\n<p>오늘은...</p>"

# ✅ 됨: 텍스트 + 빈 줄, wpautop에 맡기기
ZWS = '​'  # zero-width space
content = """안녕하세요.

{ZWS}

오늘은 저희가...

{ZWS}

<figure ...></figure>

{ZWS}

다음 문단..."""

이렇게 박으면 WP가: 1. 텍스트 줄을 <p>...</p>로 자동 변환 2. {ZWS} 한 줄을 <p>​</p>로 변환 → 단락 사이 빈 줄 3. <figure> 같은 블록 요소는 그대로 둠

inline style은 자유롭게 박아도 됨 (figure/figcaption/div). 핵심: 사용자가 <p> 명시를 안 하면 wpautop이 알아서 처리.


핵심 교훈

  1. CSS 안 먹으면 specificity 의심. inline !important도 만능 아님. 더 자세한 셀렉터가 이긴다.
  2. 워드프레스 본문에 CSS 박지 말고 추가 CSS에 박자. wpautop이 안 깬다 + 모든 글에 적용된다 + 본문 편집 영향 0.
  3. 그래도 본문에 박을 거면 한 줄 minify. 줄바꿈 없으면 wpautop이 변환할 게 없음.
  4. 빈 줄 띄움 = &nbsp; 또는 spacer block. 그냥 빈 단락은 자동 제거.

관련 문서

  • 메모리 wp-image-center-style-block.md (실전 CSS 코드)
  • 메모리 wp-youtube-iframe-embed.md (영상 임베드 함정)
  • 메모리 wp-customize-css-pending.md (다음 업로드 시 추가 CSS 안내)
  • 블로그 스킬 C:\Projects\my-skills\blog\SKILL.md 10단계