html_css

css 가상 선택자: 형제 + ~, a[href^="http"] 등

자무카 2023. 1. 9.

1. * : 자식 요소 전체 : 테스트용도. 브라우저 과부하

* {
 margin: 0;
 padding: 0;
}

별표는 페이지에 있는 전체 요소를 대상으로 합니다. 많은 개발자가 margin과 padding 값을 0으로 세팅하려고 이 선택자를 사용합니다. 간단한 테스트 용도로서는 괜찮습니다. 그러나, 저는 여러분에게 이 별표를 실전에서 사용하지 말라고 권합니다. 브라우저에 과부하가 걸리고, 사용하기에 적절하지 않습니다.

#container * {
 border: 1px solid black;
}

이 코드는 #container div의 자식 요소 전체를 대상으로 합니다. 한 번 더 말하지만, 이 선택자를 과다하게 사용하지 마세요.

2. #container 사용은 최소화(←가상클래스). 웬만하면 클래스로

#container {
   width: 960px;
   margin: auto;
}

선택자 앞에 해시(#) 기호를 붙여서 id를 대상으로 삼습니다. 가장 흔하고 쉽게 사용됩니다. 하지만, id 선택자를 사용할 때는 조심스러워야 합니다.

4. li a

li a {
  text-decoration: none;
}

다음으로 가장 많이 언급하는 선택자는 descendant입니다. 선택자를 이용해 더 상세히 작업해야 할 때, 이 선택자를 사용합니다. 가령, 전체 앵커 태그를 대상으로 하기보다 순서를 매기지 않는 목록(unordered list)에 있는 앵커만 대상으로 한다면 어떨까요? 하위 선택자를 사용하면 상세해집니다.

 

8. div#container > ul {  직계 자식만 선택 ( 손자  X )

div#container > ul {
  border: 1px solid black;
}

일반 X Y와 X > Y의 차이점은 후자가 직계 자식만을 선택한다는 것입니다. 가령, 아래 마크업을 생각해 보세요.

   <div id="container">
      <ul>
         <li> List Item
           <ul>
              <li> Child </li>
           </ul>
         </li>
         <li> List Item </li>
         <li> List Item </li>
         <li> List Item </li>
      </ul>
   </div>

#container > ul 선택자는 id가 container인 div의 직계 자손인 ul만 대상으로 삼습니다. 예를 들어 첫 번째 li의 자식인 ul은 대상이 되지 않습니다.

이런 이유로 자식 선택자를 이용해 성능을 향상할 수 있습니다. 사실, 자바스크립트를 기반으로 하는 CSS 선택자 엔진으로 작업할 때 추천합니다.

7. ul + p : ul 바로 뒤의 첫번째 요소만 선택

ul + p {
   color: red;
}

인접 선택자로 부르는 선택자입니다. 앞의 요소 바로 뒤에 있는 요소만 선택합니다. 위 코드에서 각 ul 뒤에 오는 첫 번째 단락의 텍스트만 빨간색이 됩니다.

데모 보기

9. ul ~ p : 모든 형제 선택

ul ~ p {
   color: red;
}

이 형제 선택자는 X + Y와 유사하지만 덜 엄격합니다. 인접 선택자(ul + p)는 앞의 선택자 바로 뒤에 오는 첫 번째 요소만을 선택하지만, 이 선택자는 좀 더 관대합니다. 위의 예를 보면, ul 아래 있는 모든 p 요소를 선택할 것입니다

10. a[title] : 속성 선택자. title 속성이 있는 앵크 태그만 선택

a[title] {
   color: green;
}

*속성 선택자(attributes selector)*라고 말하며, 앞의 예에서 title (마크업태그) 속성이 있는 앵커 태그만을 선택합니다. title이 없는 앵커 태그에는 특정한 스타일이 적용되지 않습니다. 그런데 더 상세히 작업해야 한다면 어떨까요? 음...

데모 보기

11. a[href="google"] →정규식으로 업글

a[href="<https://net.tutsplus.com>"] {
  color: #1f6053; /* nettuts green */
}

위의 코드는 ***https://net.tutsplus.com;***로 연결된 전체 앵커 태그에 스타일을 적용할 것입니다. 우리 브랜드 컬러인 녹색이 적용되겠지요. 그 외의 앵커 태그는 스타일의 영향을 받지 않습니다.

12. X[href="nettuts"]*

a[href*="tuts"] {
  color: #1f6053; /* nettuts green */
}

야아. 우리에게 필요한 선택자네요. 별표는 입력값이 속성값 안 어딘가에 보여야 한다는 것을 표시합니다. 그렇게 이 구문은 nettuts.comnet.tutsplus.com 그리고 tutsplus.com까지도 적용하고 있습니다.

폭넓은 표현이라는 것을 알아 두세요. 만약 앵커 태그의 url에 tuts 문자열이 일부 Evato가 아닌 사이트로 연결되어 있다면 어떨까요? 더 자세히 작성해야 한다면, 문자열의 앞과 뒤에 ^와 $를 붙이세요.

13. a[href^="http"] : ^캐럿(시작)

a[href^="http"] {
   background: url(path/to/external/icon.png) no-repeat;
   padding-left: 10px;
}

14. a[href$=".jpg"]

a[href$=".jpg"] {
   color: red;
}

문자열 끝에 적용하도록 정규 표현식 기호인 $를 한번 더 사용하겠습니다. 이번 경우에는 이미지(나 최소한 .jpg로 끝나는 url)로 링크가 걸린 앵커 전체를 찾을 것입니다. gif와 png는 영향받지 않습니다.

데모 보기

15. a[data-filetype="image"]

a[data-filetype="image"] {
   color: red;
}

8번 내용을 다시 참조합시다. 여러 가지 이미지 형식(png, jpeg, jpg, gif)은 어떻게 적용할 수 있을까요? 다음과 같이 우리는 선택자를 여러 개 만들 수 있습니다.

a[href$=".jpg"],
a[href$=".jpeg"],
a[href$=".png"],
a[href$=".gif"] {
   color: red;
}

그런데, 이 방식은 골치 아프고 비효율적입니다. 커스텀 속성을 사용하는 다른 해결 방식이 있습니다. 이미지로 링크 걸린 앵커마다 data-filetype 속성을 넣으면 어떨까요?

<a href="path/to/image.jpg" **data-filetype="image"**> Image Link </a>

그러면 갈고리(hook) 역할을 이용해 해당 앵커만 대상으로 삼는 일반 속성 선택자를 사용할 수 있습니다.

a**[data-filetype="image"]** {
   color: red;
}

16. a**[data-info~"external]** {}

 a**[data-info~="external"]** {
   color: red;
}

a[data-info~="image"] {
   border: 1px solid black;
}

친구에게 깊은 인상을 남겨줄 특별한 선택자가 있습니다. 이 요령을 알고 있는 사람은 그리 많지 않습니다. 물결표(~)를 이용하면 띄어쓰기로 구분되는 값이 있는 속성을 대상으로 할 수 있습니다.

15번에 있는 커스텀 속성 방식으로 data-info 속성을 만들면 됩니다. 이 속성은 우리가 메모하는 무엇이든지 띄어쓰기로 구분한 목록을 받을 수 있습니다. 이 경우, 외부 링크와 이미지 링크를 메모할 수 있습니다. 단지 예를 들면 말이죠.

"<a href="path/to/image.jpg" data-info="external image"> Click Me, Fool </a>

위의 마크업을 적당한 위치에 쓰면 ~ 속성 선택자 방식을 이용해 두 개의 값 중 하나라도 있는 태그를 대상으로 삼을 수 있습니다.

/* Target data-info attr that contains the value "external" */
a[data-info~="external"] {
   color: red;
}

/* And which contain the value "image" */
a[data-info~="image"] {
  border: 1px solid black;
}

17. input[type=radio]:checked

input[type=radio]:checked {
   border: 1px solid black;
}

18. X:after

before과 after 가상 클래스는 매우 효과적입니다. 사람들이 늘 이 두 클래스를 효과적으로 사용하는 새롭고 창의적인 방법을 찾고 있는 듯합니다. 이 클래스는 선택된 요소 주변에 콘텐츠를 생성합니다.

많은 사람이 clear-fix 핵을 접했을 때 이 클래스를 맨 먼저 도입했었습니다.

.clearfix**:after** {
    content: "";
    display: block;
    clear: both;
    visibility: hidden;
    font-size: 0;
    height: 0;
    }

**.clearfix {**
   *display: inline-block;
   _height: 1%;
}

이 핵은 요소 뒤에 공간을 덧붙이고 float 효과를 제거하는데 :after 가상 클래스를 사용했습니다. 특히 overflow: hidden; 방법이 불가능한 경우 여러분이 사용할 방법 중에 가장 훌륭한 방법입니다.

다른 창의적 방식은 그림자 제작에 관한 간단한 팁을 참조해 보세요.

CSS3 선택자 명세서를 보면, 가상 요소는 엄밀히 말해 두 개의 콜론(::)으로 표현되어야 합니다. 그렇지만, 일관성을 위해 유저 에이전트는 콜론을 하나 사용한 경우도 허용합니다. 사실 현재, 프로젝트에서 콜론이 한 개인 버전을 사용하는 게 더 현명합니다.

19. X:hover

div:hover {
  background: #e3e3e3;
}

에이. 이 선택자는 알고 있겠죠. 공식 용어는 사용자 동작(user action) 가상 클래스랍니다. 혼란스럽겠지만 그렇지는 않습니다. 사용자가 요소 위에 커서를 올릴 때 특정한 스타일을 적용하고 싶나요? 이 선택자로 처리하세요!

알아두세요. 앵커 태그가 아닌 태그에 :hover 가상 클래스를 적용했을 때 인터넷 익스플로러의 하위 버전에서는 반응하지 않습니다.

대부분 hover 상태에서, 가령 앵커 태그에 border-bottom을 적용할 때 이 선택자를 사용합니다.

a:hover {
 **border-bottom: 1px solid black;**
}

꿀팁 - border-bottom: 1px solid black;이 text-decoration: underline;보다 보기 더 좋습니다.

20. X:not(선택자)

div:not(#container) {
   color: blue;
}

negation 가상 클래스는 특히 유용합니다. 제가 모든 div를 선택하고 싶은데, 그중에서 id가 container인 것만 빼고 싶다고 합시다. 위의 코드가 그 작업을 완벽하게 수행합니다.

혹은, (권장하지 않지만) 제가 단락 태그만 제외하고 요소 전체를 선택하고 싶다고 한다면 아래처럼 하면 됩니다.

*:not(p) {
  color: green;
}

21. X::가상 요소

p::first-line {
   font-weight: bold;
   font-size: 1.2em;
}

첫 번째 줄이나 첫 글자와 같이 요소 일부분에 스타일을 적용하는데 가상 요소(::로 표기되는)를 사용할 수 있습니다. 효과를 보려면 이 요소를 반드시 블록 레벨 요소에 적용해야 합니다.

가상 요소는 두 개의 콜론(::)으로 표시됩니다.

단락의 첫 글자

p::first-letter {
   float: left;
   font-size: 2em;
   font-weight: bold;
   font-family: cursive;
   padding-right: 2px;
}

이 코드는 페이지에 있는 단락을 모두 찾은 다음 해당 요소의 첫 글자만을 대상으로 하는 추상 개념입니다.

신문처럼 글의 첫 글자를 스타일로 꾸미는 데 자주 사용됩니다.

단락의 첫 줄

p::first-line {
   font-weight: bold;
   font-size: 1.2em;
}

마찬가지로 ::first-line 가상 요소는 요소의 첫 번째 줄에만 스타일을 적용합니다.

기존 스타일 시트와 일관되도록 유저 에이전트는 CSS 레벨 1과 2 (즉 :first-line, :first-letter, :after)에서 도입한 가상 요소의 이전 표기인 하나의 콜론도 수용해야 합니다. 이 명세서에서 도입된 새 가상 요소에는 호환성이 부족합니다. - 출처

22. X:nth-child(n)

li:nth-child(3) {
   color: red;
}

여러 요소 중에서 특정 요소를 지목하는 방법이 없었던 시절이 기억나나요? 그 문제를 풀어줄 nth-child 가상 클래스가 있답니다!

nth-child는 변숫값을 정수(integer)로 받습니다. 0부터 시작하지는 않습니다. 두 번째 항목을 대상으로 하고 싶다면 li:nth-child(2)로 작성합니다.

자식 요소의 변수 집합을 선택하는 데에도 이 방식을 활용할 수 있습니다. 가령, 항목의 4번째마다 선택하려면 li:nth-child(4n)로 작성하면 됩니다.

23. X:nth-last-child(n)

li:nth-last-child(2) {
   color: red;
}

만약 ul에 항목이 엄청 많고, 여러분은 끝에서 세 번째 항목만 필요하다고 한다면 어떨까요? li:nth-child(397)로 작성하지 말고 nth-last-child 가상 클래스를 쓰면 됩니다.

이 선택자는 16번과 거의 동일합니다. 다만 집합의 끝에서부터 출발하면서 동작한다는 게 다릅니다.

24. X:nth-of-type(n)

ul:nth-of-type(3) {
   border: 1px solid black;
}

child를 선택하지 않고 요소의 type을 선택해야 하는 날이 있을 것입니다.

순서를 정하지 않은 목록 5개가 있는 마크업을 상상해 보세요. 세 번째 ul에만 스타일을 지정하고 싶은데 그것을 지정할 유일한 id가 없다면, nth-of-type(n) 가상 클래스를 이용할 수 있습니다. 위의 코드에서 세 번째 ul에만 테두리 선이 둘려집니다.

25. X:nth-last-of-type(n)

ul:nth-last-of-type(3) {
   border: 1px solid black;
}

일관성을 유지하도록 목록 선택자의 끝부터 출발해 지정한 요소를 대상으로 하는 nth-last-of-type을 사용할 수도 있습니다.

26. X:first-child

ul li:first-child {
   border-top: none;
}

이 구조적 가상 클래스를 이용해 부모 요소의 첫 번째 자식만 대상으로 삼을 수 있습니다. 목록에서 맨 처음과 맨 나중 항목에서 테두리 선을 제거하는데 이 방식을 흔히 사용합니다.

예를 들면, 가로 행 목록이 있다고 합시다. 행마다 border-top과 border-bottom이 적용되어 있습니다. 글쎄요. 그 정렬에서 맨 처음과 마지막 항목이 약간 어색해 보이겠네요.

많은 디자이너가 이를 보완하려고 first와 last 클래스를 적용합니다. 그 대신에 여러분은 이 가상 클래스를 사용하면 됩니다.

27. X:last-child

ul > li:last-child {
   color: green;
}

first-child와 반대로 last-child는 부모 요소의 마지막 항목을 대상으로 합니다.

예제

이 클래스 중에 활용 가능한 사례를 보여주는 간단한 예제를 만들어 봅시다. 스타일이 적용된 항목을 제작하겠습니다.

마크업

  <ul>
     <li> List Item </li>
     <li> List Item </li>
     <li> List Item </li>
  </ul>

그냥 코드입니다. 단순한 목록일 뿐이지요.

CSS

ul {
 width: 200px;
 background: #292929;
 color: white;
 list-style: none;
 padding-left: 0;
}

li {
 padding: 10px;
 border-bottom: 1px solid black;
 border-top: 1px solid #3c3c3c;
}

이 스타일에 배경을 입히고, 브라우저상에서 ul 기본값을 제거하며, 깊이를 약간 주려고 li마다 테두리 선을 주겠습니다.

목록에 깊이를 더하기 위해 각각의 li에 border-bottom을 적용합니다. 이는 그림자가 되거나 li 배경보다 어두운색이 될 것입니다. 다음에 배경보다 더 밝은 값을 border-top에 적용합니다.

단 한 가지 문제점은, 위의 이미지에서 보이듯, 순서에 정해지지 않은 목록의 맨 위와 맨 아래에도 테두리 선이 적용된다는 것입니다. 자연스럽게 보이지 않죠. :first-child와 :last-child 가상 클래스를 사용해 이 문제를 고쳐봅시다.

li:first-child {
    border-top: none;
}

li:last-child {
   border-bottom: none;
}

야아. 고쳐졌군요!

데모 보기

호환성

  • IE9+
  • 파이어폭스
  • 크롬
  • 사파리
  • 오페라

맞아요. IE8은 :first-child를 지원하지만 :last-child를 지원하지 않습니다. 말도 안 되죠.

28. X:only-child

div p:only-child {
   color: red;
}

솔직히 여러분은 아마 only-child 가상 클래스를 거의 사용하지 않을 것입니다. 그렇더라도 쓸 수 있으니 써봐야 하겠죠.

이 선택자는 부모의 단 하나의 자식 요소를 지정할 수 있습니다. 위의 코드를 참조하면, 가령, div의 단 하나의 자식인 문단만 빨간색으로 칠해질 것입니다.

아래의 마크업을 생각해 봅시다.

<div><p> My paragraph here. </p></div>

<div>
   <p> Two paragraphs total. </p>
   <p> Two paragraphs total. </p>
</div>

이 경우, 두 번째 div의 문단은 대상이 되지 않고 오직 첫 번째 div가 대상이 됩니다. 하나 이상의 자식을 요소에 적용하는 순간에 only-child 가상 클래스의 효과는 사라지게 됩니다.

데모 보기

호환성

  • IE9+
  • 파이어폭스
  • 크롬
  • 사파리
  • 오페라

29. X:only-of-type

li:only-of-type {
   font-weight: bold;
}

이 구조상의 가상 클래스는 기발한 방식으로 사용될 수 있습니다. 부모 컨테이너에 형제 요소가 없는 요소를 대상으로 합니다. 예로, 단 하나의 목록 아이템인 ul 전부를 대상으로 삼습니다.

우선, 이 작업을 어떻게 완료할지 자신에게 질문해 보세요. 여러분은 ul li로 하겠지만, 목록 아이템 전체가 대상이 됩니다. 유일한 해결 방법은 only-of-type을 사용하는 것입니다.

ul > li:only-of-type {
   font-weight: bold;
}

데모 보기

호환성

  • IE9+
  • 파이어폭스 3.5+
  • 크롬
  • 사파리
  • 오페라

30. X:first-of-type

first-of-type 가상 클래스로 해당 type의 첫 번째 형제 선택자를 선택할 수 있습니다.

테스트

이해를 돕도록 테스트를 해봅시다. 아래 마크업을 코드 편집기에 복사해 넣으세요.

<div>
   <p> My paragraph here. </p>
   <ul>
      <li> List Item 1 </li>
      <li> List Item 2 </li>
   </ul>

   <ul>
      <li> List Item 3 </li>
      <li> List Item 4 </li>
   </ul>
</div>

다음 내용을 읽기 전에 "List Item 2"만 대상으로 하는 방법을 생각해 보세요. 생각났다면 (혹은 포기했더라도) 다음으로 넘어갑니다.

해결 방법 1

이 테스트를 푸는 방법은 여러 가지입니다. 이 중에서 몇 가지를 살펴보겠습니다. first-of-type을 사용해서 시작해 보지요.

ul:first-of-type > li:nth-child(2) {
   font-weight: bold;
}

이 코드는 기본적으로 "페이지에서 순서를 중요시하지 않는 첫 번째 목록을 찾고 나서 목록 아이템인 직계 자식만 찾아라."라고 이야기합니다. 그다음, 그 결과 세트에서 두 번째 목록 아이템만 걸러냅니다.

해결 방법 2

다른 방법은 인접 선택자를 사용하는 것입니다.

p + ul li:last-child {
   font-weight: bold;
}

이 시나리오에서는 p 태그 바로 뒤에 있는 ul을 찾고 나서 그 요소의 가장 마지막 자식을 찾습니다.

해결 방법 3

이 선택자를 써서 원하는 대로 불쾌해하거나 쾌활해 할 수 있습니다.

ul:first-of-type li:nth-last-child(1) {
   font-weight: bold;
}

이번에는 페이지에 있는 첫 번째 ul을 잡고 나서 가장 첫 번째 목록 아이템을 찾습니다. 바로 아래부터 시작해서요! :)

댓글