티스토리 뷰

예제이미지.zip
2.02MB

Section 01. 조합 선택자

  • 예제 html
    <div>
        <h2>조합선택자</h2>
        <article class="content-card">
            <a href=#><img src="images/music01.jpg" alt="음악 공연 무대"></a>
            <span class="badge">AI MUSIC</span>
            <h3>PNU 감성 <span>플레이리스트</span></h3>
            <p>AI가 만든, 부산대의 오늘 <br>
                <a class="round-button" href="#"><span class="mored">›more</span></a>
            </p>

        </article>
        <article class="content-card">
            <img src="images/music02.jpg" alt="음악 공연 무대">
            <span class="badge">AI MUSIC</span>
            <h3>PNU 감성 플레이리스트</h3>
            <p>AI가 만든, 부산대의 오늘 <br>
                <a class="round-button" href="#"><span class="mored">›more</span></a>
            </p>
        </article>
    </div>
  • css 폴더에 style06.css 외부스타일파일을 만들어서 적용하자.
/* 전체 선택자 */
* {
    box-sizing: border-box;
}

body {
    margin: 0; 
    background-color: #eef2f8;
    color: #172550;
}

1. 조합 선택자란?

조합 선택자는 둘 이상의 기본 선택자를 결합하여 HTML 요소의 위치와 관계를 기준으로 대상을 선택하는 방법이다.

다음 HTML 구조를 살펴보자.

        <article class="content-card">
            <a href=#><img src="images/music01.jpg" alt="음악 공연 무대"></a>
            <span class="badge">AI MUSIC</span>

            <p>AI가 만든, 부산대의 오늘 <br>
                <a class="round-button" href="#"><span class="mored">›more</span></a>
            </p>
            <h3>PNU 감성 플레이리스트</h3>
        </article>

이 구조에서 <img>, <span>, <h3>, <p>, <a>는 모두 .content-card 안에 포함되어 있다. 조합 선택자를 사용하면 이러한 부모·자식·형제 관계를 이용하여 요소를 선택할 수 있다.

2. 조합 선택자의 종류

종류 표기 의미
자손 선택자 A B A 안에 있는 모든 B를 선택한다.
자식 선택자 A > B A의 바로 아래 자식 B를 선택한다.
인접 형제 선택자 A + B A 바로 다음에 있는 B를 선택한다.
일반 형제 선택자 A ~ B A 뒤에 있는 모든 형제 B를 선택한다.

3. 자손 선택자

자손 선택자는 선택자 사이를 공백으로 구분한다.

.content-card h3 {
    color: #111a43;
    font-size: 16px;
}

.content-card 안에 있는 모든 <h3> 요소를 선택한다.

.content-card h3
       ↓       ↓
   조상 요소   내부의 h3

 

.content-card h3 span{font-weight:bold;color:red;}

첫 번째 선택자는 .content-card 내부의 모든 <h3>을 선택한다. 두 번째 선택자는 .content-card 내부의 <h3> 안에 있는 <span>을 선택한다.


4. 자식 선택자

자식 선택자는 > 기호를 사용한다. 특정 요소의 바로 아래 단계에 있는 자식만 선택한다.

.content-card > a {border:2px solid grey;}

다음 구조에서 <a>는 .content-card의 직접적인 자식이다.

.content-card의 바로 아래에 있는 <a>만 선택한다. 더 깊은 단계에 있는 <a>은 선택하지 않는다.

자손 선택자와 자식 선택자의 차이

/* header 안의 모든 a를 선택한다. */
header a {
    color: navy;
}

/* header 바로 아래에 있는 a만 선택한다. */
header > a {
    color: red;
}

기존 소스에서 <a>는 <header> 바로 아래에 있지 않고 <div>와 <nav> 안에 있다. 따라서 header > a로는 선택되지 않는다.


5. 인접 형제 선택자

인접 형제 선택자는 + 기호를 사용한다. 특정 요소 바로 다음에 있는 형제 요소 하나를 선택한다.

.badge + h3 {
    margin-top: 8px;
    color: #172550;
}

HTML 구조는 다음과 같다.

<span class="badge">AI MUSIC</span>
<h3>PNU 감성 플레이리스트</h3>

<h3>가 .badge 바로 다음에 있으므로 선택된다.

HTML 순서가 다음과 같이 변경되면 선택되지 않는다.

<span class="badge">AI MUSIC</span>
<p>새로운 설명</p>
<h3>PNU 감성 플레이리스트</h3>

<h3>가 .badge 바로 다음 요소가 아니기 때문이다.


6. 일반 형제 선택자

일반 형제 선택자는 ~ 기호를 사용한다. 특정 요소 뒤에 나오는 같은 부모의 모든 형제 요소를 선택한다.

.badge ~ p {
    color: #747a8a;
}

다음 구조에서 <p>는 .badge 뒤에 있는 형제 요소이므로 선택된다.

<span class="badge">AI MUSIC</span>
<h3>PNU 감성 플레이리스트</h3>
<p>AI가 만든, 부산대의 오늘</p>

<p>가 .badge 바로 다음에 있을 필요는 없다. 같은 부모를 가지면서 .badge 뒤에 있으면 선택된다.


Section 02. 가상 클래스 선택자

연습 html

<div class="menu">
        <h2>가상클래스</h2>
        <p>별도의 class를 추가하지 않고도 특정 상태를 선택할 수 있는 장점</p>
        <ul>
            <li><a href="httP://www.naver.com" target="_blank" class="btn01">:link</a></li>
            <li><a href=# class="btn01">:visited</a></li>
            <li><a href=# class="btn01">:hover</a></li>
            <li><a href=# class="btn01">:active</a></li>
            <li><a href=# class="btn01">:focus</a></li>
        </ul>
    </div>

1. 가상 클래스란?

가상 클래스는 요소의 상태나 구조적 위치를 기준으로 요소를 선택한다. 가상 클래스 이름 앞에는 콜론 :을 작성한다.

선택자:가상클래스 {
    속성: 값;
}

예를 들어 사용자가 링크 위에 마우스를 올렸을 때 스타일을 변경하려면 :hover를 사용한다.

a:hover {
    color: purple;
}

가상 클래스는 HTML에 별도의 class를 추가하지 않고도 특정 상태를 선택할 수 있다는 장점이 있다.

2. 링크와 사용자 동작 가상 클래스

:link 아직 방문하지 않은 링크이다.
:visited 방문한 적이 있는 링크이다.
:hover 마우스 포인터가 올라간 상태이다.
:active 마우스로 누르고 있는 상태이다.
:focus 키보드나 마우스로 초점을 받은 상태이다.

3. :hover — 마우스를 올린 상태

카테고리 메뉴

.category-menu a:hover {
    background-color: #5f3ed6;
    color: white;
}

마우스를 카테고리 메뉴에 올리면 배경색과 글자색이 변경된다.

콘텐츠 카드

.content-card:hover {
    border-color: #6546dc;
    background-color: #faf9ff;
}

마우스를 카드 위에 올리면 카드의 테두리와 배경색이 변경된다.

원형 버튼

.round-button:hover {
    background-color: #6240d8;
    color: white;
}

4. :active — 누르고 있는 상태

.category-menu a:active {
    background-color: #2f1a86;
    color: white;
}

사용자가 메뉴를 마우스로 누르고 있는 짧은 순간에 적용된다.

.round-button:active {
    background-color: #291477;
}

hover는 마우스를 올려놓은 상태이고, active는 마우스 버튼으로 요소를 누르고 있는 상태이다.

5. :focus — 초점을 받은 상태

링크는 Tab 키를 이용하여 선택할 수 있다. 키보드로 선택된 요소는 초점 상태가 된다.

a:focus {
    outline: 3px solid #ffbd2e;
    outline-offset: 3px;
}

outline은 요소 바깥쪽에 강조선을 표시한다. 이는 키보드 사용자가 현재 어느 요소를 선택하였는지 확인할 수 있게 하는 중요한 접근성 기능이다.

초점 표시를 단순히 제거하는 다음 코드는 사용하지 않는 것이 좋다.

/* 접근성 문제가 발생할 수 있다. */
a:focus {
    outline: none;
}

6. 링크 가상 클래스 작성 순서

링크 가상 클래스는 다음 순서로 작성하는 것이 일반적이다.

a:link {
    color: #172550;
}

a:visited {
    color: #584978;
}

a:hover {
    color: #6546dc;
}

a:active {
    color: red;
}
:link → :visited → :hover → :active

이를 LVHA 순서라고 기억할 수 있다.

다만 현재 종합예제에는 버튼 형태의 링크가 많으므로 전체 a 요소보다 특정 영역의 링크에 적용하는 것이 안전하다.

.user-menu a:link {
    color: #172550;
}

.user-menu a:visited {
    color: #172550;
}

.user-menu a:hover {
    color: #6546dc;
}

Section 03. 구조 가상 클래스

구조 가상 클래스는 HTML 문서에서 요소가 위치한 순서와 구조를 기준으로 요소를 선택한다.

<h2>구조가상클래스</h2>

<div class="category-menu">
    <a href="#">♫ MUSIC</a>
    <a href="#">▶ VIDEO</a>
    <a href="#">● ART</a>
    <a href="#">♬ PODCAST</a>
</div>
가상클래스 선택 대상
:first-child 형제 요소 중 첫 번째 요소
:last-child 형제 요소 중 마지막 요소
:nth-child(n) 형제 요소 중 n번째 요소
:nth-child(odd) 홀수 번째 요소
:nth-child(even) 짝수 번째 요소
:nth-last-child(n) 뒤에서 n번째 요소

1. :first-child

형제 요소 중 첫 번째 요소를 선택한다.

.category-menu a:first-child {
    margin-left: 0px;
    background: #d528d2;
}

.category-menu 안에 있는 링크 중 첫 번째 링크인 MUSIC이 선택된다.

<div class="category-menu">
    <a href="#">♫ MUSIC</a>
    <a href="#">▶ VIDEO</a>
    <a href="#">● ART</a>
    <a href="#">♬ PODCAST</a>
</div>

2. :last-child

형제 요소 중 마지막 요소를 선택한다.

.category-menu a:last-child {
    margin-right: 0px;
    background-color: #ffbd2e;
}

네 번째 카드의 오른쪽 여백만 제거한다.

3. :nth-child()

형제 요소 중 특정 순서에 있는 요소를 선택한다.

.category-menu a:nth-child(2) {
    border-bottom: 3px solid rgb(189, 10, 10);
    text-decoration: none;
}

두 번째 콘텐츠 카드를 선택한다.

홀수 번째 카드 선택

.content-card a:nth-child(odd) {
    background-color: #fafaff;
}

짝수 번째 카드 선택

.content-card a:nth-child(even) {
    background-color: #f3f6ff;
}

세 번째 카드 선택

.category-menu a:nth-child(3) {
    border-bottom: 3px solid rgb(189, 10, 10);
    text-decoration: none;
}

처음 두 카드 선택

.category-menu a:nth-child(-n+2){border-top:4px solid red;}

입문 단계에서는 숫자, odd, even을 중심으로 학습하는 것이 적절하다.


📝 예제: 콘텐츠 현황 대시보드

HTML 작성

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PNU 콘텐츠 대시보드</title>
    <link rel="stylesheet" href="css/board.css">
</head>

<body>
    <div id="dashboard">
        <header>
            <div class="title-area">
                <p>PNU CAMPUS PLAY</p>
                <h1>콘텐츠 현황 대시보드</h1>
            </div>
        </header>

        <main>
            <section class="summary">
                <div class="summary-card">
                    <span>전체 콘텐츠</span>
                    <strong>128</strong>
                </div>

                <div class="summary-card">
                    <span>이번 달 등록</span>
                    <strong>24</strong>
                </div>

                <div class="summary-card">
                    <span>전체 조회수</span>
                    <strong>48,320</strong>
                </div>

                <div class="summary-card">
                    <span>인기 콘텐츠</span>
                    <strong>12</strong>
                </div>
            </section>

            <section class="table-section">
                <div class="section-title">
                    <h2>🔥 인기 콘텐츠 순위</h2>
                    <a href="#">전체 보기</a>
                </div>

                <table>
                    <caption>
                        PNU CAMPUS PLAY 콘텐츠별 조회 현황
                    </caption>

                    <thead>
                        <tr>
                            <th>순위</th>
                            <th>카테고리</th>
                            <th>콘텐츠 제목</th>
                            <th>등록일</th>
                            <th>조회수</th>
                            <th>상태</th>
                        </tr>
                    </thead>

                    <tbody>
                        <tr>
                            <td>1</td>
                            <td>AI MUSIC</td>
                            <td>PNU 감성 플레이리스트</td>
                            <td>2026.10.01</td>
                            <td>12,580</td>
                            <td><span class="status">인기</span></td>
                        </tr>

                        <tr>
                            <td>2</td>
                            <td>MEDIA ART</td>
                            <td>빛으로 만나는 캠퍼스</td>
                            <td>2026.10.02</td>
                            <td>9,840</td>
                            <td><span class="status">인기</span></td>
                        </tr>

                        <tr>
                            <td>3</td>
                            <td>SHORTS</td>
                            <td>60초로 보는 부산대의 가을</td>
                            <td>2026.10.03</td>
                            <td>8,210</td>
                            <td><span class="status">인기</span></td>
                        </tr>

                        <tr>
                            <td>4</td>
                            <td>PODCAST</td>
                            <td>캠퍼스에서 묻고, 듣다</td>
                            <td>2026.10.04</td>
                            <td>6,940</td>
                            <td><span class="normal">공개</span></td>
                        </tr>

                        <tr>
                            <td>5</td>
                            <td>VIDEO</td>
                            <td>부산대학교 캠퍼스 투어</td>
                            <td>2026.10.05</td>
                            <td>5,720</td>
                            <td><span class="normal">공개</span></td>
                        </tr>

                        <tr>
                            <td>6</td>
                            <td>INTERVIEW</td>
                            <td>오늘의 부산대 사람들</td>
                            <td>2026.10.06</td>
                            <td>4,350</td>
                            <td><span class="normal">공개</span></td>
                        </tr>
                    </tbody>
                </table>
            </section>
        </main>

        <footer>
            <p>© 2026 PNU CAMPUS PLAY</p>
        </footer>
    </div>
</body>

</html>

CSS

/* 전체 선택자 */
* {
    box-sizing: border-box;
}


body {
    margin: 0;
    background-color: #eef2f8;
    color: #172550;
}

a {
    color: inherit;
    text-decoration: none;
}

#dashboard {
    width: 1100px;
    margin: 40px auto;
    background-color: white;
    border: 1px solid #dce2ed;
    border-radius: 16px;
    overflow: hidden;
}

/* 상단 영역 */
header {
    padding: 28px 35px;
    background-color: #172550;
    color: white;
}

.title-area
 {
    display: inline-block;
    vertical-align: middle;
    font-size: 16px;
}

.title-area p {
    margin: 0 0 5px;
    color: #b8c6ff;
    font-size: 13px;
    font-weight: bold;
    letter-spacing: 2px;
}

.title-area h1 {
    margin: 0;
    font-size: 28px;
}


/* 본문 영역 */
main {
    padding: 25px;
}

/* 요약 카드 */
.summary {
    margin-bottom: 25px;
    font-size: 0;
}

.summary-card {
    display: inline-block;
    width: 23.5%;
    margin-right: 2%;
    padding: 20px;
    background-color: #f2f4ff;
    border: 1px solid #e0e4f2;
    border-radius: 12px;
    font-size: 16px;
}

.summary-card:last-child {
    margin-right: 0;
}

.summary-card span {
    display: block;
    margin-bottom: 10px;
    color: #6d7486;
    font-size: 14px;
}

.summary-card strong {
    color: #5939ce;
    font-size: 27px;
}

/* 테이블 영역 */
.table-section {
    padding: 22px;
    border: 1px solid #e0e4ec;
    border-radius: 12px;
}

.section-title {
    margin-bottom: 16px;
    font-size: 0;
}

.section-title h2,
.section-title a {
    display: inline-block;
    vertical-align: middle;
    font-size: 16px;
}

.section-title h2 {
    width: 80%;
    margin: 0;
    font-size: 21px;
}

.section-title a {
    width: 20%;
    color: #6d7486;
    text-align: right;
}

table {
    width: 100%;
    border-collapse: collapse;
}

caption {
    overflow: hidden;
    width: 1px;
    height: 1px;
}

th,
td {
    padding: 14px 12px;
    border-bottom: 1px solid #e1e5ee;
    font-size: 14px;
    text-align: center;
}

th {
    background-color: #6040d5;
    color: white;
}

td {
    color: #4e566a;
}

/* 상태 표시 */
.status,
.normal {
    display: inline-block;
    min-width: 50px;
    padding: 5px 10px;
    border-radius: 14px;
    font-size: 12px;
    font-weight: bold;
}

.status {
    background-color: #ffe1dc;
    color: #d5442f;
}

.normal {
    background-color: #e1f5ec;
    color: #16815e;
}

/* 하단 영역 */
footer {
    padding: 20px;
    background-color: #172550;
    color: #dce3f7;
    text-align: center;
}

footer p {
    margin: 0;
}
/* 첫 번째 열 */
th:first-child,
td:first-child {
    width: 70px;
    font-weight: bold;
}

/* 마지막 열 */
th:last-child,
td:last-child {
    width: 90px;
}

/* 짝수 데이터 행 */
tbody tr:nth-child(even) {
    background-color: #f6f7fb;
}

/* 상위 3개 행 */
tbody tr:nth-child(-n+3) td:first-child {
    color: #6040d5;
    font-size: 18px;
}

/* 첫 번째 순위 */
tbody tr:first-child td:first-child {
    color: #e44c38;
    font-size: 21px;
}

/* 마지막 행의 아래쪽 테두리 제거 */
tbody tr:last-child td {
    border-bottom: none;
}

/* 마우스가 올라간 행 */
tbody tr:hover {
    background-color: #e9e5ff;
}

 

 :first-child로 첫 번째 열 강조하기

테이블에서 각 행의 첫 번째 셀은 순위를 나타낸다. :first-child를 사용하면 모든 행의 첫 번째 열을 선택할 수 있다.

th:first-child,
td:first-child {
    width: 70px;
    font-weight: bold;
}

th:first-child는 각 행의 첫 번째 <th>를 선택하고, td:first-child는 각 행의 첫 번째 <td>를 선택한다.

1위 행의 순위를 특별히 강조하려면 다음과 같이 작성할 수 있다.

tbody tr:first-child td:first-child {
    color: #e44c38;
    font-size: 20px;
}

선택자의 의미는 다음과 같다.

tbody 안의 첫 번째 tr 안에 있는 첫 번째 td

 :last-child로 마지막 열 강조하기

각 행에서 마지막 셀은 콘텐츠 상태를 나타낸다.

th:last-child,
td:last-child {
    width: 90px;
}

마지막 행의 테두리를 제거할 수도 있다.

tbody tr:last-child td {
    border-bottom: none;
}

이 선택자는 <tbody> 안의 마지막 <tr>에 포함된 모든 <td>를 선택한다.

 :nth-child(even)으로 줄무늬 테이블 만들기

짝수 번째 행에 다른 배경색을 지정하면 행을 구분하기 쉬운 줄무늬 테이블을 만들 수 있다.

tbody tr:nth-child(even) {
    background-color: #f6f7fb;
}

:nth-child(odd)로 홀수 행 선택하기

tbody tr:nth-child(odd) {
    background-color: white;
}

odd는 홀수 번째 요소를 의미한다.

짝수 행과 홀수 행을 함께 지정할 수도 있다.

tbody tr:nth-child(odd) {
    background-color: white;
}

tbody tr:nth-child(even) {
    background-color: #f6f7fb;
}

:nth-child(n)으로 특정 행 선택하기

두 번째 행을 선택하려면 다음과 같이 작성한다.

tbody tr:nth-child(2) {
    color: #4d35bd;
}

세 번째 행의 모든 셀을 강조하려면 다음과 같이 작성한다.

tbody tr:nth-child(3) td {
    font-weight: bold;
}

 

상위 3개 콘텐츠 강조하기

-n+3을 사용하면 첫 번째부터 세 번째 요소까지 선택할 수 있다.

tbody tr:nth-child(-n+3) {
    background-color: #f0edff;
}
-n+3 → 1, 2, 3번째 요소

상위 3개의 순위 셀만 강조하려면 다음과 같이 작성한다.

tbody tr:nth-child(-n+3) td:first-child {
    color: #6040d5;
    font-size: 18px;
}

nth-child()와 first-child를 조합한 선택자이다.

 :nth-last-child()로 뒤에서 선택하기

nth-last-child()는 마지막 요소부터 순서를 계산한다.

tbody tr:nth-last-child(2) {
    color: #7c8290;
}

위 선택자는 뒤에서 두 번째 행을 선택한다.

마지막 두 개의 행을 선택하려면 다음과 같이 작성한다.

tbody tr:nth-last-child(-n+2) {
    color: #8a8f9c;
}

입문 과정에서는 first-child, last-child, nth-child()를 우선 학습하고 nth-last-child()는 확장 내용으로 다루는 것이 적절하다.

마우스 동작 추가하기

:hover는 구조 가상 클래스가 아니라 사용자 동작 가상 클래스이다. 그러나 테이블의 사용성을 높이기 위하여 함께 적용할 수 있다.

tbody tr:hover {
    background-color: #e9e5ff;
}

마우스를 올린 행의 배경색이 변경되므로 사용자가 현재 확인하는 데이터를 쉽게 구분할 수 있다.

링크에 키보드 초점 표시도 추가할 수 있다.

a:focus {
    outline: 3px solid #ffbf3f;
    outline-offset: 3px;
}

구조 가상 클래스 완성 코드

다음 코드를 기존 CSS의 테이블 영역 아래에 추가한다.

/* 첫 번째 열 */
th:first-child,
td:first-child {
    width: 70px;
    font-weight: bold;
}

/* 마지막 열 */
th:last-child,
td:last-child {
    width: 90px;
}

/* 짝수 데이터 행 */
tbody tr:nth-child(even) {
    background-color: #f6f7fb;
}

/* 상위 3개 행 */
tbody tr:nth-child(-n+3) td:first-child {
    color: #6040d5;
    font-size: 18px;
}

/* 첫 번째 순위 */
tbody tr:first-child td:first-child {
    color: #e44c38;
    font-size: 21px;
}

/* 마지막 행의 아래쪽 테두리 제거 */
tbody tr:last-child td {
    border-bottom: none;
}

/* 마우스가 올라간 행 */
tbody tr:hover {
    background-color: #e9e5ff;
}

 


🧩 종합예제

첨부 화면을 참고하여 전체 HTML과 CSS를 작성 해 보자.

 

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/10   »
일 월 화 수 목 금 토
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함