intro
이번 게시물은 저번시간에 학습했던 css flexbox를 활용해서
항공편 조회사이트를 css로 제작해보는 실습을 하는 과정을 적어보겠습니다.
원래 학습 실습에 대한것은 많이 올리지 않으려했는데,
이번 실습은 포스팅을 하면 css복습에 도움이 될것 같아서 올려봅니다.
start~
저번 학습에 대한 글 참고
CSS Layout - flexbox
intro저번 포스팅에 이어 이번에는 css layout에 대한 정리를 해보겠습니다.두번째 글도 힘내서 포스팅해볼게요 ✏️플렉스박스란? css에서 한 줄의 레이아웃을 유연하게 배치하기 위한 css레이아웃
noeyh66.tistory.com
✏️실습설명
전체 예시 페이지

html과 css코드를 제공해주었고, 위 코드를 이용해서 리디자인을 하는 코드였다. html과 css파일은 바로 아래에 첨부해두었다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Codeit Airline</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&family=Titillium+Web:wght@300;600&display=swap"
rel="stylesheet"
>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<div class="container">
<img id="logo" src="images/logo.png">
</div>
</div>
<div class="content">
<div class="container">
<div class="trip">
<div class="trip-route">
<div class="trip-title">
<img
class="trip-depart-icon"
src="images/fa-solid_plane-departure.svg"
>
출국
</div>
<div class="trip-airports">ICN → YYZ</div>
</div>
<span class="trip-date">일요일, 4월 20일, 2025</span>
</div>
<div class="flights-header">
<div class="flights-header-result">120개의 결과</div>
<div class="flights-header-col">
<div class="order-by">추천순</div>
<div>
₩439,400<br>
평균 3시간 40분
</div>
</div>
<div class="flights-header-col active">
<div class="order-by">최저가</div>
<div>
₩113,060<br>
평균 4시간 35분
</div>
</div>
<div class="flights-header-col">
<div class="order-by">최단 시간</div>
<div>
₩863,200<br>
평균 2시간 33분
</div>
</div>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 01</h2>
<div class="content">
<div class="departure-arrival">
<h3 class="label">출발</h3>
<div>오전 10:30</div>
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
<h3 class="label">도착</h3>
<div>오후 2:29</div>
</div>
<h3 class="label">운행 항공편</h3>
<div>CL117, CL2402</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">100석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout-soon">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">1석 남음</p>
<button class="reserve">예약하기</button>
</div>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 02</h2>
<div class="content">
<div class="departure-arrival">
<h3 class="label">출발</h3>
<div>오전 11:30</div>
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
<h3 class="label">도착</h3>
<div>오후 3:29</div>
</div>
<h3 class="label">운행 항공편</h3>
<div>CL118, CL2403</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">42석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
</div>
<div class="ad">
<h3>이 항공편이 마음에 드셨나요?</h3>
<p>항공편의 가격이 오르거나 내려가면 알려드릴게요.</p>
<button>알림 받기</button>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 03</h2>
<div class="content">
<div class="departure-arrival">
<h3 class="label">출발</h3>
<div>오후 12:30</div>
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
<h3 class="label">도착</h3>
<div>오후 4:29</div>
</div>
<h3 class="label">운행 항공편</h3>
<div>CL119, CL2404</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">120석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout-soon">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">1석 남음</p>
<button class="reserve">예약하기</button>
</div>
</div>
</div>
</div>
</body>
</html>
* {
box-sizing: border-box;
}
body {
margin: 0;
background: #f7f8fd;
color: #0b1f66;
font-family: 'Noto Sans KR', sans-serif;
}
button {
padding: 8px 16px;
border: none;
border-radius: 8px;
background-color: #16bf97;
box-shadow: 0px 4px 15px rgba(18, 23, 42, 0.03);
color: #ffffff;
font-weight: 700;
}
button:disabled {
background-color: #f5f6f9;
color: #b6bfd3;
}
.container {
margin: 0 auto;
padding: 0 24px;
width: 100%;
max-width: 880px;
}
.header {
position: sticky;
top: 0;
padding: 18px 0;
background-color: #2a3251;
color: #ffffff;
}
#logo {
height: 24px;
}
.header > .divider {
color: #3b4252;
}
.trip {
margin: 40px 0 24px;
padding: 24px 32px;
border-radius: 8px;
background: #ebeff8;
display: flex;
justify-content: space-between;
align-items: center;
}
.trip-title {
color: #b3bdd5;
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.trip-depart-icon {
margin-right: 8px;
height: 12px;
}
.trip-airports {
margin: 8px 0;
color: #000000;
font-weight: 600;
font-style: normal;
font-size: 32px;
font-family: 'Titillium Web';
line-height: 32px;
}
.trip-date {
display: inline-block;
margin: 16px 0;
padding: 8px 24px;
border-radius: 4px;
background: #ffffff;
color: #000000;
}
.flights-header {
margin-bottom: 40px;
}
.flights-header-result,
.flights-header-col {
padding-bottom: 18px;
border-bottom: 1px solid #d6dbe8;
}
.flights-header-col {
width: 147px;
padding: 18px;
color: #b1bac9;
}
.flights-header-col.active {
border-bottom: 3px solid #2a3251;
color: #2a3251;
}
.order-by {
margin-bottom: 8px;
font-weight: 700;
}
.flight-card {
margin: 24px 0;
border-radius: 8px;
background: #ffffff;
box-shadow: 0px 4px 15px rgba(18, 23, 42, 0.1);
}
.flight-card > .cabin {
width: 147px;
border-left: 1px solid #e5e9f3;
}
.ticket-label {
margin: 0;
padding: 8px 24px;
background-image: url('images/bg_ticket_label.svg');
background-position: 0 0;
background-size: contain;
background-repeat: no-repeat;
color: #16bf97;
font-size: 12px;
font-family: 'Titillium Web';
line-height: 18px;
}
.flight-card .content {
padding: 24px 24px 32px;
color: #1a345e;
font-weight: 700;
}
.flight-card .label {
margin-bottom: 8px;
color: #b6bfd3;
font-weight: 500;
font-size: 12px;
line-height: 17px;
}
.flight-card .departure-arrival {
font-weight: 700;
}
.cabin .name,
.cabin .price,
.cabin .left {
margin: 0;
}
.cabin .name {
font-weight: 500;
font-size: 16px;
line-height: 23px;
}
.cabin .price {
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.cabin .left {
font-weight: 500;
font-size: 12px;
line-height: 17px;
}
.cabin .reserve {
margin-top: 23px;
}
.soldout.cabin .left {
color: #b6bfd3;
}
.soldout-soon.cabin .left {
color: #dc534a;
}
.ad {
padding: 47px;
border-radius: 8px;
background-color: #ebeff8;
}
.ad > h3 {
margin: 0;
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.ad > p {
margin: 0;
color: #b6bfd3;
font-size: 12px;
line-height: 17px;
}
아무래도 사이트 한 면에 대한 코드를 다 올리다 보니 가독성이 좋지 못한것 같다.. 따라서 코드 설명과 정리를 하려고 하는데,
해당 사이트에서 어떤 디자인이 적용되었는지 적용이 되지 않았는지 로컬 서버를 따로 돌리며 진행해야 실습하기에 수월할 것 같다.
실습하며 헷갈렸던 부분을 정리해보았다.
1. .flights-header에 안에 있는 요소들이 모두 몰려있는 관계로, 교차축 방향으로 정렬을 해주는 align-items: flex-end 적용
.flights-header {
margin-bottom: 40px;
align-items: flex-end;
}
2. .flights-header-result 클래스의 영역을 늘리고 꽉 차게 배치하기 위해서, flex-grow:1 사용, 나머지 영역들은 크기가 변하지 않도록 flex-shrink:0을 지정
.flights-header {
display: flex;
align-items: flex-end;
margin-bottom: 40px;
}
.flights-header-result,
.flights-header-col {
padding-bottom: 18px;
border-bottom: 1px solid #d6dbe8;
}
.flights-header-result {
flex-grow: 1;
}
.flights-header-col {
flex-shrink: 0;
width: 147px;
padding: 18px;
color: #b1bac9;
}
.flights-header-col.active {
border-bottom: 3px solid #2a3251;
color: #2a3251;
}
✏️해답
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Codeit Airline</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&family=Titillium+Web:wght@300;600&display=swap"
rel="stylesheet"
>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<div class="container">
<img id="logo" src="images/logo.png">
</div>
</div>
<div class="content">
<div class="container">
<div class="trip">
<div class="trip-route">
<div class="trip-title">
<img
class="trip-depart-icon"
src="images/fa-solid_plane-departure.svg"
>
출국
</div>
<div class="trip-airports">ICN → YYZ</div>
</div>
<span class="trip-date">일요일, 4월 20일, 2025</span>
</div>
<div class="flights-header">
<div class="flights-header-result">120개의 결과</div>
<div class="flights-header-col">
<div class="order-by">추천순</div>
<div>
₩439,400<br>
평균 3시간 40분
</div>
</div>
<div class="flights-header-col active">
<div class="order-by">최저가</div>
<div>
₩113,060<br>
평균 4시간 35분
</div>
</div>
<div class="flights-header-col">
<div class="order-by">최단 시간</div>
<div>
₩863,200<br>
평균 2시간 33분
</div>
</div>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 01</h2>
<div class="content">
<div class="departure-arrival">
<div class="departure">
<h3 class="label">출발</h3>
<div>오전 10:30</div>
</div>
<div class="journey">
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
</div>
<div class="arrival">
<h3 class="label">도착</h3>
<div>오후 2:29</div>
</div>
</div>
<div class="planes">
<h3 class="label">운행 항공편</h3>
<div>CL117, CL2402</div>
</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">100석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout-soon">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">1석 남음</p>
<button class="reserve">예약하기</button>
</div>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 02</h2>
<div class="content">
<div class="departure-arrival">
<div class="departure">
<h3 class="label">출발</h3>
<div>오전 11:30</div>
</div>
<div class="journey">
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
</div>
<div class="arrival">
<h3 class="label">도착</h3>
<div>오후 3:29</div>
</div>
</div>
<div class="planes">
<h3 class="label">운행 항공편</h3>
<div>CL118, CL2403</div>
</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">42석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
</div>
<div class="ad">
<h3>이 항공편이 마음에 드셨나요?</h3>
<p>항공편의 가격이 오르거나 내려가면 알려드릴게요.</p>
<button>알림 받기</button>
</div>
<div class="flight-card">
<div class="ticket">
<h2 class="ticket-label">AIR TICKET 03</h2>
<div class="content">
<div class="departure-arrival">
<div class="departure">
<h3 class="label">출발</h3>
<div>오후 12:30</div>
</div>
<div class="journey">
<h3 class="label">04h 15m</h3>
<img class="flight-icon" src="images/img_journey.svg">
</div>
<div class="arrival">
<h3 class="label">도착</h3>
<div>오후 4:29</div>
</div>
</div>
<div class="planes">
<h3 class="label">운행 항공편</h3>
<div>CL119, CL2404</div>
</div>
</div>
</div>
<div class="cabin">
<h3 class="name">일반</h3>
<p class="price">₩129,000</p>
<p class="left">120석 남음</p>
<button class="reserve">예약하기</button>
</div>
<div class="cabin soldout">
<h3 class="name">비즈니스</h3>
<p class="price">₩419,000</p>
<p class="left">0석 남음</p>
<button class="reserve" disabled>매진</button>
</div>
<div class="cabin soldout-soon">
<h3 class="name">퍼스트</h3>
<p class="price">₩699,000</p>
<p class="left">1석 남음</p>
<button class="reserve">예약하기</button>
</div>
</div>
</div>
</div>
</body>
</html>
* {
box-sizing: border-box;
}
body {
margin: 0;
background: #f7f8fd;
color: #0b1f66;
font-family: 'Noto Sans KR', sans-serif;
}
button {
padding: 8px 16px;
border: none;
border-radius: 8px;
background-color: #16bf97;
box-shadow: 0px 4px 15px rgba(18, 23, 42, 0.03);
color: #ffffff;
font-weight: 700;
}
button:disabled {
background-color: #f5f6f9;
color: #b6bfd3;
}
.container {
margin: 0 auto;
width: 880px;
}
.header {
position: sticky;
top: 0;
padding: 18px 0;
background-color: #2a3251;
color: #ffffff;
}
#logo {
height: 24px;
}
.header > .divider {
color: #3b4252;
}
.trip {
display: flex;
align-items: center;
justify-content: space-between;
margin: 40px 0 24px;
padding: 24px 32px;
border-radius: 8px;
background: #ebeff8;
}
.trip-title {
color: #b3bdd5;
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.trip-depart-icon {
margin-right: 8px;
height: 12px;
}
.trip-airports {
margin: 8px 0;
color: #000000;
font-weight: 600;
font-style: normal;
font-size: 32px;
font-family: 'Titillium Web';
line-height: 32px;
}
.trip-date {
display: inline-block;
margin: 16px 0;
padding: 8px 24px;
border-radius: 4px;
background: #ffffff;
color: #000000;
}
.flights-header {
display: flex;
align-items: flex-end;
margin-bottom: 40px;
}
.flights-header-result,
.flights-header-col {
padding-bottom: 18px;
border-bottom: 1px solid #d6dbe8;
}
.flights-header-result {
flex: 1 1 auto;
}
.flights-header-col {
flex: 0 0 147px;
padding: 18px;
color: #b1bac9;
}
.flights-header-col.active {
border-bottom: 3px solid #2a3251;
color: #2a3251;
}
.order-by {
margin-bottom: 8px;
font-weight: 700;
}
.flight-card {
display: flex;
margin: 24px 0;
border-radius: 8px;
background: #ffffff;
box-shadow: 0px 4px 15px rgba(18, 23, 42, 0.1);
}
.flight-card > .ticket {
flex: 1 1 auto;
}
.flight-card > .cabin {
flex: 0 0 147px;
border-left: 1px solid #e5e9f3;
}
.ticket-label {
margin: 0;
padding: 8px 24px;
background-image: url('images/bg_ticket_label.svg');
background-position: 0 0;
background-size: contain;
background-repeat: no-repeat;
color: #16bf97;
font-size: 12px;
font-family: 'Titillium Web';
line-height: 18px;
}
.flight-card .content {
display: flex;
flex-direction: column;
justify-content: center;
padding: 24px 24px 32px;
color: #1a345e;
font-weight: 700;
gap: 16px;
}
.flight-card .label {
margin-bottom: 8px;
color: #b6bfd3;
font-weight: 500;
font-size: 12px;
line-height: 17px;
}
.flight-card .departure-arrival {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 700;
}
.flight-card .journey {
text-align: center;
}
.cabin {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.cabin .name,
.cabin .price,
.cabin .left {
margin: 0;
}
.cabin .name {
font-weight: 500;
font-size: 16px;
line-height: 23px;
}
.cabin .price {
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.cabin .left {
font-weight: 500;
font-size: 12px;
line-height: 17px;
}
.cabin .reserve {
margin-top: 23px;
}
.soldout.cabin .left {
color: #b6bfd3;
}
.soldout-soon.cabin .left {
color: #dc534a;
}
.ad {
position: relative;
z-index: -1;
display: flex;
align-items: center;
flex-direction: column;
margin-top: -40px;
padding: 47px;
border-radius: 8px;
background-color: #ebeff8;
}
.ad > h3 {
margin: 0 0 8px;
font-weight: 700;
font-size: 16px;
line-height: 23px;
}
.ad > p {
margin: 0 0 16px;
color: #b6bfd3;
font-size: 12px;
line-height: 17px;
}'web > css' 카테고리의 다른 글
| Tailwind가 대세가 된 이유에 관한 고찰 (0) | 2026.02.26 |
|---|---|
| CSS Layout - flexbox (1) | 2026.01.12 |
| CSS Layout - Position (1) | 2026.01.10 |