본문으로 건너뛰기

주축과 교차축

HTML·CSS 목차한 줄로 나란히: flex레슨 65 / 93

목차

flex에서 항목이 늘어서는 방향을 주축(main axis), 그와 직각인 방향을 교차축(cross axis)이라고 부릅니다. flex-direction으로 늘어서는 방향을 바꾸면 두 축이 함께 돌고, 축을 따라 자리를 정하는 정렬 속성의 방향도 함께 바뀝니다.

라벨과 입력 칸은 가로보다 위아래로 놓는 편이 읽기 쉽습니다. flex로 항목을 세로로 세울 수 있는데, 그다음 가운데로 모으려고 하면 엉뚱한 방향으로 움직이기 쉽습니다. 정렬 속성은 가로 · 세로가 아니라 축을 맡기 때문입니다. 이 레슨에서는 늘어서는 방향을 정하는 flex-direction, 정렬 속성이 맡는 축, 보이는 차례만 바꾸는 값을 봅니다.

그림 준비 중

1주축은 항목이 늘어서는 방향 — flex-direction

flex-direction을 적지 않으면 처음 값 row라, 항목이 왼쪽에서 오른쪽으로 늘어섭니다. column이면 위에서 아래로 늘어섭니다.

<div class="box">
  <div>가</div>
  <div>나</div>
  <div>다</div>
</div>
.box {
  display: flex;
  flex-direction: column;
}

.box div {
  width: 40px;
  height: 40px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .box의 flex-directioncolumn
  • .box의 줄 수3

세 항목이 세 줄로 섰습니다. 블록이 쌓인 것과 모양은 같지만, 이제 셋은 flex 항목이라 주축을 따라 자리를 나눠 받습니다.

flex-direction늘어서는 방향주축교차축
row(처음 값)왼쪽 → 오른쪽가로세로
column위 → 아래세로가로
row-reverse오른쪽 → 왼쪽가로세로
column-reverse아래 → 위세로가로

row-reverse · column-reverse는 보이는 차례만 거꾸로 그립니다. 항목 하나의 자리를 옮기는 order도 같습니다. 요소 나무의 차례는 그대로라, 화면 읽기 프로그램이 읽는 차례와 Tab이 옮겨 가는 차례도 HTML 차례 그대로입니다(키보드로 다니기). 그래서 이 과목은 보이는 차례가 필요하면 HTML 차례부터 맞춥니다.

2정렬 이름은 축을 따라간다

정렬 속성 둘은 저마다 한 축을 맡습니다. justify-content는 주축, align-items는 교차축에서 항목의 자리를 정합니다. 값은 다음 두 레슨에서 하나씩 보고, 여기서는 center(가운데)만 씁니다.

속성맡는 축rowcolumn
justify-content주축가로세로
align-items교차축세로가로

column으로 세운 항목을 가로 가운데로 모으려면, 가로가 교차축이니 align-items를 씁니다.

<div class="box">
  <div>가</div>
  <div>나</div>
  <div>다</div>
</div>
.box {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 200px;
  height: 160px;
}

.box div {
  width: 40px;
  height: 40px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .box div의 왼쪽 자리88px
  • .box div의 위 자리8px

'가'가 너비 200px 상자의 가로 가운데(왼쪽에서 80px)로 왔고, 위 자리는 그대로입니다. 같은 자리에 justify-content: center⁠를 쓰면 주축인 세로로 움직입니다.

주축으로 움직이려면 그 방향에 남는 자리가 있어야 합니다. 이 상자는 높이가 160px이고 항목 셋이 120px이라 세로로 40px이 남습니다. 높이를 정하지 않으면 상자가 항목 높이만큼만 커져 세로로 남는 자리가 없습니다.

예제

후기 폼의 이름 칸입니다. 라벨 아래에 입력 칸이 오도록 묶음 .field를 column으로 세웠습니다.

<div class="field">
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nick"
  />
</div>
.field {
  display: flex;
  flex-direction: column;
  width: 240px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .field의 줄 수2
  • label의 displayblock
  • input의 너비240px

라벨과 입력 칸이 두 줄로 섰습니다. 입력 칸은 너비를 적지 않았는데 묶음 너비 240px만큼 늘었습니다 — column에서는 가로가 교차축이고, 교차축 정렬의 처음 값이 항목을 그 축으로 늘이기 때문입니다. 이 늘이기는 교차축 정렬에서 봅니다.

자주 틀리는 곳

틀린 생각: justify-content는 가로, align-items는 세로를 맡는다.

row에서 늘 그렇게 쓰다 보면, 이름 자체가 가로 · 세로를 뜻한다고 외우게 됩니다.

<nav>
  <a href="index.html">
    레시피 목록
  </a>
  <a href="kimchi.html">
    김치볶음밥
  </a>
</nav>
nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 120px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • nav a의 위 자리8px

세로 가운데로 내리려고 align-items: center를 줬는데, 링크는 위 끝(8px)에 그대로이고 가로 가운데로 갔습니다.

맞는 규칙: 정렬 속성은 축을 맡습니다 — justify-content는 주축, align-items는 교차축. column이면 주축이 세로라, 세로 가운데는 justify-content: center⁠입니다(브라우저 규칙 7).

틀린 생각: column에서 justify-content: center⁠를 주면 언제나 세로 가운데로 온다.

예제의 이름 칸에 justify-content: center⁠를 더해 봅니다.

<div class="field">
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nick"
  />
</div>
.field {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 240px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • label의 위 자리8px

라벨은 맨 위(8px) 그대로입니다. 묶음 높이를 정하지 않아 묶음이 두 항목 높이만큼만 커졌고, 세로로 나눌 자리가 없습니다.

맞는 규칙: 정렬은 남는 자리를 옮기는 일입니다. column에서 세로로 움직이려면 부모에 항목보다 큰 높이가 있어야 합니다.

틀린 생각: row-reverse로 뒤집으면 HTML 차례도 바뀐다.

화면에 '다음'이 왼쪽, '이전'이 오른쪽으로 보이니, 키보드도 그 차례로 옮겨 갈 것 같습니다.

<div class="pager">
  <a href="japchae.html">이전</a>
  <a href="kimchi.html">다음</a>
</div>
.pager {
  display: flex;
  flex-direction: row-reverse;
  width: 200px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .pager a의 오른쪽 끝208px
  • 지금 포커스의 읽는 이름이전

'이전'은 상자 오른쪽 끝(208px)에 그려졌지만, Tab을 한 번 누르면 '이전'으로 갑니다. 눈은 왼쪽에서 오른쪽으로 '다음 → 이전'을 읽는데, 포커스는 '이전'에서 '다음'으로 — 오른쪽에서 왼쪽으로 거꾸로 움직입니다.

맞는 규칙: row-reverse · column-reverse · order는 그리는 차례만 바꿉니다. 읽는 차례와 Tab 차례는 나무의 차례(HTML 차례) 그대로라, 보이는 차례가 필요하면 HTML 차례를 바꿉니다(브라우저 규칙 2 · 3).

확인 문제

1. 예제 CSS에서 .field의 width: 240px을 width: 160px로 바꿨습니다. 입력 칸의 너비는 얼마가 될까요?

<div class="field">
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nick"
  />
</div>
.field {
  display: flex;
  flex-direction: column;
  width: 160px;
}
  • ① 160px
  • ② 240px 그대로
  • ③ 라벨의 너비만큼
힌트

column에서 교차축은 어느 방향인지 먼저 적고, 입력 칸이 그 방향으로 무엇에 맞춰 늘었는지 봅니다.

정답

① 160px

결과 화면
잰 값개발자 도구에서 본 값
  • input의 너비160px
  • column에서 교차축은 가로입니다. 입력 칸은 처음 값의 늘이기로 교차축, 곧 가로로 묶음 너비만큼 늘어납니다. 묶음이 160px이면 입력 칸도 160px입니다(브라우저 규칙 7).
  • ②는 240px이 입력 칸에 적힌 값이라고 본 것입니다. 240px은 묶음의 너비였습니다.
  • ③은 라벨과 같은 줄에 맞춰진다고 본 것입니다. 라벨과 입력 칸은 다른 줄의 항목이고, 둘 다 묶음 너비에 맞춰집니다.

2. 후기 폼의 별점 칸도 라벨 아래에 고르는 칸이 오게 하려 합니다. ____ 자리에 알맞은 값을 쓰세요.

<div class="field">
  <label for="star">별점</label>
  <select id="star" name="star">
    <option>5</option>
    <option>4</option>
  </select>
</div>
.field {
  display: flex;
  flex-direction: ____;
}
힌트

항목이 늘어설 방향을 먼저 정하고, 그 방향의 값 이름을 표에서 찾습니다.

정답

column

.field {
  display: flex;
  flex-direction: column;
}

위에서 아래로 늘어서는 값은 column입니다. row(처음 값)면 라벨 옆에 고르는 칸이 섭니다.

3. 여행 일정 링크 셋을 이렇게 놓았습니다. 결과 화면에서 왼쪽부터 무엇이 보이고, Tab을 처음 누르면 어느 링크로 갈까요?

<div class="trip">
  <a href="day1.html">1일</a>
  <a href="day2.html">2일</a>
  <a href="day3.html">3일</a>
</div>
.trip {
  display: flex;
  flex-direction: row-reverse;
  width: 200px;
}
  • ① '3일 2일 1일'로 보이고, Tab은 '1일'로 간다
  • ② '3일 2일 1일'로 보이고, Tab은 '3일'로 간다
  • ③ '1일 2일 3일'로 보이고, Tab은 '1일'로 간다
힌트

그리는 차례와 나무의 차례를 따로 적고, Tab이 둘 가운데 어느 차례를 따르는지 봅니다.

정답

① — 화면은 '3일 2일 1일'이고, Tab은 '1일'로 갑니다.

결과 화면
잰 값개발자 도구에서 본 값
  • .trip a의 오른쪽 끝208px
  • 지금 포커스의 읽는 이름1일
  • row-reverse는 오른쪽에서 왼쪽으로 늘어서게 그려, HTML 첫 링크 '1일'이 상자 오른쪽 끝(208px)에 놓입니다.
  • Tab 차례는 나무의 차례라 HTML 첫 링크 '1일'부터입니다(브라우저 규칙 2 · 3).
  • ②는 Tab도 보이는 차례를 따른다고 본 것입니다. ③은 row-reverse가 차례를 바꾸지 않는다고 본 것입니다 — 그리는 차례는 바뀝니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. hello.html의 body 안을 2절 상자 코드로, style 요소 안을 2절 CSS로 바꿔 저장 · 새로고침합니다. flex-direction: column⁠을 지워 처음 값 row로 돌아가면, 같은 align-items: center가 이번에는 세 항목을 상자의 세로 가운데로 옮깁니다. 축이 돌자 같은 속성이 맡는 방향이 바뀐 것입니다. 파일을 만들고 여는 법은 준비: VS Code와 작업 폴더에 있습니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

HTML·CSS 목차로