CSS

HTML5 멀티미디어 & CSS3 선택자 & 플렉스 박스

웹과 멀티미디어

HTML5 이전에는 웹에서 멀티미디어 콘텐츠를 재생하기 위해 플러그인(Plug-in)의 도움이 필요했다. <object>와 <embed>가 바로 그런 역할을 하는 태그였다.

  • <object>: 오디오, 비디오, PDF, Java 애플릿 등 다양한 외부 콘텐츠를 삽입할 때 사용하던 범용적인 태그

  • <embed>: 주로 플래시(Flash)와 같은 특정 플러그인 콘텐츠를 삽입할 때 사용

HTML5의 등장 이후, 오디오와 비디오는 아래에 설명할 <audio>, <video> 태그를 사용하는 것이 표준이 되었다. 현재 <object>와 <embed>는 PDF 뷰어 등 특수한 외부 콘텐츠를 삽입하는 경우에 제한적으로 사용된다.


오디오 & 비디오 재생하기

HTML5에서는 플러그인 없이도 웹 브라우저 자체적으로 오디오와 비디오를 재생할 수 있는 표준 태그를 제공한다.

<audio>와 <video> 태그

  • <audio>: 오디오 파일을 재생한다.

  • <video>: 비디오 파일을 재생한다.

주요 속성

  • src: 재생할 미디어 파일의 경로를 지정한다.

  • controls: 재생, 정지, 볼륨 조절 등 제어 막대를 표시한다.

  • autoplay: 페이지 로딩 시 자동으로 재생한다. (최근 브라우저에서는 muted 속성과 함께 사용해야 동작하는 경우가 많다.)

  • muted: 음소거 상태로 재생한다.

  • loop: 재생이 끝나면 자동으로 다시 시작한다.

  • poster: (video 전용) 비디오가 재생되기 전에 표시될 이미지(썸네일) 경로를 지정한다.

<source>와 <track> 태그

  • <source>: 브라우저별로 지원하는 미디어 포맷이 다를 수 있기 때문에, 이 태그를 사용해 여러 형식의 파일을 제공할 수 있다. 브라우저는 위에서부터 순서대로 지원 가능한 첫 번째 파일을 재생한다. type 속성을 지정하면 브라우저가 파일을 다운로드하기 전에 지원 여부를 판단해 대역폭을 절약한다.

  • <track>: 비디오에 자막, 캡션 등 시간 기반 텍스트 트랙을 추가할 때 사용한다.

예시 코드

<audio controls>
    <source src="music.mp3" type="audio/mpeg">
    <source src="music.ogg" type="audio/ogg">
    브라우저가 audio 태그를 지원하지 않습니다.
</audio>

<video controls poster="thumbnail.jpg" width="600">
    <source src="movie.mp4" type="video/mp4">
    <source src="movie.webm" type="video/webm">
    <track kind="subtitles" src="subtitles_ko.vtt" srclang="ko" label="한국어">
    <track kind="subtitles" src="subtitles_en.vtt" srclang="en" label="English">
    브라우저가 video 태그를 지원하지 않습니다.
</video>

controls 속성을 주면 브라우저가 아래처럼 재생·정지·볼륨 막대를 자동으로 만들어 준다. (오디오 파일은 연결되어 있지 않아 재생되지는 않는다)

<audio controls>

<video controls poster="..."> — poster가 재생 전 썸네일


다재다능한 CSS3 선택자

기본 선택자보다 더 정교하게 요소를 선택할 수 있는 강력한 선택자들이다.

선택자

이름

설명

예시

A B

하위

A 요소 안에 있는 모든 B 요소

div p { color: blue; }

A > B

자식

A 요소의 직계 자식인 B 요소만

ul > li { font-weight: bold; }

A + B

인접 형제

A 요소 바로 다음에 오는 형제 B 요소 하나만

h1 + p { margin-top: 0; }

A ~ B

형제

A 요소 다음에 오는 모든 형제 B 요소

h2 ~ p { color: gray; }

[attr]

속성

특정 속성을 가진 모든 요소

a[target] { background: yellow; }

[attr=val]

속성=값

속성 값이 정확히 일치하는 요소

input[type="text"] { ... }

[attr~=val]

속성~=값

속성 값에 특정 단어가 포함된 요소

p[class~="important"] { ... }

[attr^=val]

속성^=값

속성 값이 특정 문자열로 시작하는 요소

a[href^="https://"] { ... }

[attr$=val]

속성$=값

속성 값이 특정 문자열로 끝나는 요소

img[src$=".png"] { ... }

[attr*=val]

속성*=값

속성 값에 특정 문자열이 포함된 요소

a[href*="google"] { ... }


가상 클래스와 가상 요소

가상 클래스 (Pseudo-classes): 요소의 특정 상태에 따라 스타일을 적용한다. (: 한 개 사용)

  • :hover: 마우스 커서를 올렸을 때

  • :active: 마우스로 클릭하고 있는 동안

  • :focus: <input> 등이 포커스를 받았을 때

  • :first-child: 형제 요소 중 첫 번째 요소

  • :last-child: 형제 요소 중 마지막 요소

  • :nth-child(n): 형제 요소 중 n번째 요소 (예: li:nth-child(2n)은 짝수 번째 li 선택)

  • :not(selector): 괄호 안 선택자에 해당하지 않는 요소 (예: li:not(.active)는 active 클래스가 아닌 li)

  • :disabled / :checked / :required / :placeholder-shown: 폼 요소의 상태에 따라 스타일을 적용. 비활성화된 입력 연한 색, 체크된 항목 강조, 필수 필드 표시 등에 활용.

가상 요소 (Pseudo-elements): 요소의 특정 부분에 스타일을 적용한다. (CSS3부터 :: 두 개 사용 권장)

  • ::before: 요소의 콘텐츠 시작 부분에 새로운 콘텐츠를 추가한다. (content 속성 필수)

  • ::after: 요소의 콘텐츠 끝 부분에 새로운 콘텐츠를 추가한다. (content 속성 필수)

  • ::first-letter: 단락의 첫 글자에 스타일을 적용한다.

  • ::first-line: 단락의 첫 줄에 스타일을 적용한다.

  • ::selection: 사용자가 드래그하여 선택한 텍스트에 스타일을 적용한다.

/* 링크에 마우스를 올리면 밑줄이 생김 */
a:hover {
    text-decoration: underline;
}

/* 리스트의 홀수 번째 항목 배경색 변경 */
li:nth-child(odd) {
    background-color: #f2f2f2;
}

/* 모든 p 태그 앞에 '참고: ' 라는 텍스트 추가 */
p::before {
    content: "참고: ";
    font-weight: bold;
    color: blue;
}

li:nth-child(odd) — 홀수 줄 배경색

  • 첫째 줄 (홀수)

  • 둘째 줄

  • 셋째 줄 (홀수)

  • 넷째 줄

p::before { content: "참고: " }

참고: 가상 요소로 앞에 글자를 붙였습니다.

p::first-letter — 첫 글자만 크게

멋진 첫 글자 강조 효과입니다. 잡지 본문에서 자주 보이는 스타일입니다.


플렉스 박스 레이아웃 (Flexbox)

Flexbox는 복잡한 레이아웃을 쉽고 유연하게 구현하기 위한 1차원 레이아웃 모델이다. 가로 또는 세로 방향 중 한쪽 방향으로 아이템들을 정렬하고 배치하는 데 매우 강력하다.

  • Flex Container: display: flex;가 적용된 부모 요소

  • Flex Items: Flex Container의 자식 요소들

주요 Container 속성

  • flex-direction: 아이템이 정렬될 주축(main-axis)의 방향을 결정한다.

    • row (기본값): 가로 (왼쪽에서 오른쪽)

    • row-reverse: 가로 역순

    • column: 세로 (위에서 아래)

    • column-reverse: 세로 역순

  • flex-wrap: 아이템들이 한 줄에 모이지 않을 때 어떻게 할지 결정한다.

    • nowrap (기본값): 강제로 한 줄에 들어감 (아이템이 좁아질 수 있음)

    • wrap: 공간이 부족하면 다음 줄로 넘어감

  • justify-content: 주축(main-axis) 방향으로 아이템들을 정렬하는 방법을 결정한다.

    • flex-start (기본값): 시작점으로 정렬

    • flex-end: 끝점으로 정렬

    • center: 가운데 정렬

    • space-between: 첫 아이템은 시작점, 마지막 아이템은 끝점에 붙고 나머지는 균등한 간격으로 정렬

    • space-around: 모든 아이템 둘레에 균등한 간격을 만듦

    • space-evenly: 아이템 사이와 양 끝 여백을 완전히 균등하게 만듦

  • align-items: 교차축(cross-axis) 방향으로 아이템들을 정렬하는 방법을 결정한다.

    • stretch (기본값): 아이템들이 교차축 방향으로 컨테이너를 가득 채우도록 늘어남

    • flex-start: 시작점으로 정렬

    • flex-end: 끝점으로 정렬

    • center: 가운데 정렬

    • baseline: 텍스트의 기준선(baseline)으로 정렬

  • gap: 아이템 사이의 간격을 지정한다. 과거에는 margin으로 처리했지만 현재는 gap이 표준.

주요 Item 속성

  • flex: flex-grow flex-shrink flex-basis를 한 번에 지정하는 단축 속성. flex: 1로 쓰면 아이템들이 남은 공간을 동등하게 나눠 가진다.

  • align-self: 개별 아이템에만 align-items를 재정의한다 (auto, flex-start, center 등).

  • order: 아이템의 표시 순서를 변경한다 (HTML 마크업을 수정하지 않고).

.container {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    height: 200px;
    background-color: lightgray;
}

flex-direction — 주축 방향

row (기본)

1

2

3

column

1

2

3

justify-content — 주축(가로) 정렬

flex-startABC

centerABC

flex-endABC

space-betweenABC

space-aroundABC

space-evenlyABC

align-items — 교차축(세로) 정렬

flex-start

AB

center

AB

flex-end

AB

stretch

AB

가운데 정렬의 정석

justify-content: center + align-items: center를 함께 쓰면 자식을 가로·세로 정중앙에 놓을 수 있다. 가장 많이 쓰는 Flexbox 패턴이다.


반응형 웹 기초 및 미디어 쿼리 맛보기

  • 반응형 웹 디자인(Responsive Web Design, RWD)은 데스크톱, 태블릿, 모바일 등 다양한 디바이스의 화면 크기에 맞춰 웹 페이지의 레이아웃과 콘텐츠가 최적화되어 보이도록 하는 웹 디자인 기법이다.

  • 미디어 쿼리(Media Query)는 반응형 웹을 구현하는 핵심 기술로, 특정 조건(예: 화면 너비)에 따라 다른 CSS 스타일을 적용하게 해준다.

같은 콘텐츠라도 화면 너비에 따라 카드 배치가 아래처럼 달라진다.

📱 모바일
(~767px) 1열

카드

카드

카드

📲 태블릿
(768~991px) 2열

카드

카드

카드

💻 데스크톱
(992px~) 3열

카드

카드

카드

@media 규칙

@media (조건) { /* 조건이 참일 때 적용될 CSS */ } 형식으로 사용한다.

모바일 우선 vs 데스크탑 우선 전략

  • min-width: 768px는 모바일 우선(mobile-first) 전략으로, 기본 스타일은 모바일용으로 작성하고 점점 큰 화면을 대응.

  • max-width: 767px는 데스크탑 우선(desktop-first) 전략으로, 기본 스타일은 데스크탑용으로 작성하고 작은 화면을 대응.

  • 최근에는 모바일 우선이 권장됨.

반응형 웹의 필수 코드

HTML <head>에 아래 viewport 메타 태그를 추가해야 디바이스의 화면 너비를 기준으로 페이지가 올바르게 표시된다.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

예시 코드

.container {
    display: flex;
}

.item {
    flex: 1;
    padding: 20px;
}

/* 화면 너비가 768px 이하일 때 적용될 스타일 */
@media (max-width: 768px) {
    .container {
        /* 가로 정렬을 세로 정렬로 변경 */
        flex-direction: column;
    }
}

aspect-ratio 활용

반응형 카드에서 세로/가로 비율을 유지하고 싶을 때 aspect-ratio 속성이 유용하다. 예: .thumbnail { aspect-ratio: 16 / 9; }는 너비가 바뀌어도 16:9 비율을 자동으로 유지한다. 프로필 이미지, 동영상 영역, 제품 카드 등에 활용.


종합 실습: 반응형 카드 레이아웃 만들기

Flexbox와 미디어 쿼리를 사용하여 화면 크기에 따라 유연하게 변하는 카드 UI 레이아웃을 만들어 본다.

요구사항

  1. 여러 개의 카드를 담는 Flex Container를 만든다.

  2. 데스크톱 화면 (992px 이상)에서는 한 줄에 3개의 카드가 표시된다.

  3. 태블릿 화면 (768px ~ 991px)에서는 한 줄에 2개의 카드가 표시된다.

  4. 모바일 화면 (767px 이하)에서는 한 줄에 1개의 카드만 표시된다.

  5. 카드에 마우스를 올리면(:hover) 그림자 효과가 진해지는 효과를 준다.

  6. PDF 파일 링크([href$=".pdf"])에 특별한 아이콘을 ::before 가상 요소를 이용해 추가한다.

완성 코드

index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>반응형 카드 레이아웃</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Our Services</h1>
    <div class="card-container">
        <div class="card">
            <h2>웹 개발</h2>
            <p>최신 기술을 사용한 반응형 웹사이트를 제작합니다.</p>
            <a href="service-web.pdf">소개서 다운로드</a>
        </div>
        <div class="card">
            <h2>앱 개발</h2>
            <p>iOS와 Android 앱을 위한 솔루션을 제공합니다.</p>
            <a href="#">자세히 보기</a>
        </div>
        <div class="card">
            <h2>디자인</h2>
            <p>사용자 중심의 직관적인 UI/UX를 디자인합니다.</p>
            <a href="#">자세히 보기</a>
        </div>
    </div>
</body>
</html>

style.css

body {
    font-family: sans-serif;
    margin: 0;
    background-color: #f4f4f4;
}

h1 {
    text-align: center;
    margin: 40px 0;
}

/* Flex Container */
.card-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 20px;
    padding: 20px;
}

.card {
    background-color: white;
    border-radius: 8px;
    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    padding: 20px;
    transition: box-shadow 0.3s ease;
}

/* :hover 효과 */
.card:hover {
    box-shadow: 0 8px 12px rgba(0,0,0,0.2);
}

.card h2 {
    margin-top: 0;
}

/* 속성 선택자 + 가상 요소 */
.card a[href$=".pdf"]::before {
    content: "📄 ";
}

/* --- 미디어 쿼리 --- */

/* 데스크톱 화면 (3열) */
@media (min-width: 992px) {
    .card {
        width: calc(33.333% - 40px);
    }
}

/* 태블릿 화면 (2열) */
@media (min-width: 768px) and (max-width: 991px) {
    .card {
        width: calc(50% - 40px);
    }
}

/* 모바일 화면 (1열) */
@media (max-width: 767px) {
    .card {
        width: 100%;
    }
}

데스크톱 화면에서의 완성 모습 (마우스를 올리면 그림자가 진해지고, PDF 링크 앞에는 📄 아이콘이 붙는다):

웹 개발

최신 기술을 사용한 반응형 웹사이트를 제작합니다.

📄 소개서 다운로드

앱 개발

iOS와 Android 앱을 위한 솔루션을 제공합니다.

자세히 보기

디자인

사용자 중심의 직관적인 UI/UX를 디자인합니다.

자세히 보기

↑ 세 번째 카드는 :hover 상태(그림자 진함)를 예시로 표현

마지막 수정 2026년 10월 22일