16단원 '움직임과 다크 모드'의 네 레슨에서 9문제를 내고, 9 · 10 · 14단원에서 3문제를 섞었습니다. 앞 단원 문제가 어느 레슨인지는 정답을 펼치면 보입니다. 값이나 고친 줄은 종이에 끝까지 쓴 뒤 정답을 펼치세요. 막히면 정답 앞의 힌트를 먼저 펼칩니다. 점수는 매기지 않습니다.
결과를 묻는 문제의 결과 화면과 잰 값은 정답을 펼치면 보입니다. 결과 화면은 늘 마우스를 올리기 전의 밝은 화면으로 그려집니다 — 마우스를 올린 뒤 · 움직임 줄이기 · 어두운 화면에서의 값은 잰 값 칸으로 봅니다. 컴퓨터가 있으면 문제의 HTML과 CSS를 파일로 저장해 브라우저로 열고, 개발자 도구 Rendering의 흉내(움직임 줄이기 · 어두운 화면)를 켜서 Computed 창의 값을 맞춰 봅니다. 결과는 모두 크롬 기준입니다.
이 단원을 이미 안다면 1 · 2 · 3 · 6 · 7번을 먼저 풀어 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다. 다 맞히면 이 단원은 건너뛰어도 됩니다. 틀린 문제와 힌트를 펴고 맞힌 문제는 정답 끝의 '다시 볼 레슨'으로 갑니다. 끝의 두 문제(11 · 12번)는 직접 만들어 보는 문제라, 건너뛸지 가릴 때는 풀지 않아도 됩니다. 10번까지 풀고 쉬었다가 11번부터 이어 풀어도 됩니다. ⟨컴퓨터⟩가 붙은 문제는 컴퓨터에서 파일을 만들어 풉니다. 폰으로만 본다면 그 문제 끝의 폰 물음 하나로 대신합니다.
문제 1
사진 동아리 공지의 '가입 안내' 링크입니다. 마우스를 올리면 글자색이 빨강으로 바뀝니다. (가) 마우스를 올린 링크 (나) 마우스를 뗀 링크 — 각각 Computed 창의 transition-duration은 몇 초일까요? 숫자만 쓰세요.
<a href="join.html">가입 안내</a>
a {
color: #005bb5;
}
a:hover {
color: #d70015;
transition: color 300ms;
}
힌트
마우스를 올린 뒤와 뗀 뒤에 링크에 닿는 규칙을 각각 적어 보세요.
힌트 둘
이어 그리는 시간은 값이 바뀐 뒤 그 요소에 닿는 transition에서 옵니다.
정답
(가) 0.3 · (나) 0
마우스를 뗀 링크에는 a 규칙만 닿습니다.
a의transition-duration0s
마우스를 올린 링크에는 a:hover 규칙까지 닿습니다.
<a href="join.html">
가입 안내
</a>
a {
color: #005bb5;
}
a:hover {
color: #d70015;
transition: color 300ms;
}a의transition-duration0.3sa의 글자색rgb(215, 0, 21)
- 마우스를 올릴 때는
:hover까지 닿은 상태가 '바뀐 뒤'라 0.3초 동안 빨강으로 이어집니다. 뗄 때는 기본 규칙만 닿은 상태가 '바뀐 뒤'인데, 그 규칙에 전환이 없어 처음 값 0초 — 파랑으로 툭 돌아옵니다. - (나)를 0.3이라고 썼다면 한 번 닿은 전환이 남는다고 본 것입니다. 뗄 때도 이어지게 하려면
transition줄을a규칙으로 옮깁니다. 0.3s·300ms로 써도 같은 답입니다.
다시 볼 레슨: transition
문제 2
플로우 카페 메뉴판의 메뉴 칸입니다. 마우스를 올리면 테두리 색과 바탕색이 바뀝니다. 두 색은 어떻게 바뀔까요? 움직임이라 그림 대신 글 보기에서 고르세요.
<p class="menu">
레몬에이드 5000
</p>
.menu {
border: 2px solid #d2d2d7;
transition:
color 300ms ease,
border-color 300ms ease;
}
.menu:hover {
border-color: #005bb5;
background-color: #e8f3ff;
}- ① 테두리 색과 바탕색이 함께 0.3초 동안 이어 바뀐다
- ② 테두리 색과 바탕색이 함께 한순간에 바뀐다
- ③ 테두리 색은 0.3초 동안 이어 바뀌고, 바탕색은 한순간에 바뀐다
힌트
:hover 규칙이 바꾸는 속성을 하나씩 적어 보세요.
힌트 둘
적은 속성을 transition의 목록과 견줘 보세요. 목록에 없는 속성은 바뀌는 과정을 정한 선언이 없습니다.
정답
③입니다. 아래 잰 값은 마우스를 올리고 전환이 끝난 뒤의 값입니다.
<p class="menu">
레몬에이드 5000
</p>
.menu {
border: 2px solid #d2d2d7;
transition:
color 300ms ease,
border-color 300ms ease;
}
.menu:hover {
border-color: #005bb5;
background-color: #e8f3ff;
}.menu의transition-propertycolor, border-color.menu의border-top-colorrgb(0, 91, 181).menu의background-colorrgb(232, 243, 255)
- 전환은 적은 속성의 값이 바뀔 때만 이어 그립니다.
border-color는 목록에 있어 0.3초 동안 이어지고,background-color는 목록에 없어 한순간에 바뀝니다.color는 글자색이라 바탕색과 다른 속성이고, 이 칸에서는 글자색이 바뀌지 않아 하는 일이 없습니다. - ①은
transition을 적으면 바뀌는 값이 모두 이어진다고, 또는color가 바탕색까지 정한다고 본 것입니다. 바탕색도 잇고 싶으면 목록의color를background-color로 바꿉니다. - ②는 기본 규칙의 전환은 마우스를 뗄 때만 쓰인다고 본 것입니다. 기본 규칙은
:hover상태에도 그대로 닿아, 올릴 때와 뗄 때 모두 쓰입니다.
다시 볼 레슨: transition
문제 3
여행 일정 페이지의 날짜 줄입니다. 짝마다 두 코드의 화면이 같은지 다른지 쓰세요. 다르면 어디가 다른지도 한 줄로 쓰세요. 셋 모두 같은 답이 나와도 됩니다.
(가)
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
transform: translateX(12px);
}
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
position: relative;
left: 12px;
}
(나)
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
transform: translateX(12px);
}
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
margin-left: 12px;
}
(다)
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
transform: scale(1.5);
}
<p>1일 <span>2일</span> 3일</p>
span {
display: inline-block;
background-color: #e8f3ff;
font-size: 1.5em;
}
힌트
짝마다 두 코드에서 다른 줄을 찾고, '2일'과 '3일'이 어디에 놓일지 종이에 그려 보세요.
힌트 둘
짝마다 다른 줄이 배치를 바꾸는지, 그리기만 바꾸는지 나눠 보세요. transform은 배치가 끝난 뒤 그려진 모습만 바꾸고, relative 상자는 옮겨 놓아도 원래 자리를 그대로 차지합니다.
정답
(가) 같다 · (나) 다르다 — 뒤 코드는 '3일'이 오른쪽으로 밀리고 '2일' 앞 틈이 넓다 · (다) 다르다 — 뒤 코드는 줄이 높아지고 '3일'이 오른쪽으로 밀린다
- (가) 두 줄 모두 '2일'의 원래 자리를 남긴 채 그려진 모습만 12px 오른쪽에 둡니다. '3일'은 원래 자리를 보고 놓여 그대로이고, 옮긴 '2일'이 '3일' 앞쪽에 겹칩니다(브라우저 규칙 8).
- (나) 바깥 여백은 배치의 일이라 '2일'과 함께 '3일'도 12px 밀립니다. 겹치지 않습니다.
- (다)
scale(1.5)는 그려진 크기만 키워 이웃 자리는 그대로이고 '2일'이 양옆 글에 겹칩니다. 글자 크기를 키우면 배치가 다시 되어 줄이 높아지고 '3일'이 밀립니다. - (가)를 다르다고 했다면
transform이 상자를 옮겨 이웃이 비켜 준다고 본 것입니다(transform이 배치라는 생각). (나)를 같다고 한 것도 같은 생각입니다. - (다)를 같다고 했다면
scale()이 글자를 키우는 것과 같다고 본 것입니다. 배율로 그리기만 할 뿐 배치는 그대로입니다.
다시 볼 레슨: transform으로 옮기고 키우기 · 일반 흐름과 position
문제 4
여행 일정 페이지의 사진 칸을 0.75배로 줄여 그렸습니다. (가) 사진 칸의 너비(그려진 너비 — 테두리까지) (나) 배치 너비는 각각 몇 px일까요? 숫자만 쓰세요.
<div class="photo">바다 사진</div>
.photo {
width: 200px;
padding: 10px;
border: 2px solid #d2d2d7;
transform: scale(0.75);
}
힌트
먼저 transform이 없을 때 이 칸이 차지하는 너비를 상자 셈으로 적어 보세요.
정답
(가) 168 · (나) 224
.photo의 너비168px.photo의 배치 너비224px.photo의width200px
| 걸음 | 셈 | 값 |
|---|---|---|
| 1. 내용 칸 | width | 200 |
| 2. 안쪽 여백 더하기 | 200 + 10 × 2 | 220 |
| 3. 테두리 더하기 | 220 + 2 × 2 | 224 |
| 4. 바깥 여백은 따로 | 없음 | — |
- 배치 너비는 상자 셈 그대로 224입니다(브라우저 규칙 6).
scale(0.75)는 배치가 끝난 뒤 그 상자를 0.75배로 그려 224 × 0.75 = 168입니다(브라우저 규칙 8). - 150 · 200이라고 썼다면
width가 차지하는 너비라고 본 것입니다(width가 차지하는 너비라는 생각). - (나)를 168이라고 썼다면
scale()이 배치 크기도 줄인다고 본 것입니다(transform이 배치라는 생각). 아래 요소는 224 너비의 원래 자리를 보고 놓입니다.
다시 볼 레슨: 너비와 box-sizing · transform으로 옮기고 키우기
문제 5
플로우 카페 메뉴판의 메뉴 줄입니다. '추천' 표시를 띄우려고 absolute와 top: 0만 줬습니다. 메뉴 줄에도, 그 바깥 어느 요소에도 position을 주지 않았습니다. 화면에 어떻게 보일까요? 보기 셋 가운데 고르세요.
<p class="menu">
바닐라 라테 <b>추천</b>
</p>
b {
position: absolute;
top: 0;
}
힌트
'추천'부터 바깥으로 p · body · html을 나무로 적고, 요소마다 준 position을 옆에 써 보세요.
힌트 둘
기준 상자는 부모가 아니라 바깥으로 찾은 첫 position 조상이고, 없으면 페이지입니다. 적은 칸(top)과 적지 않은 칸(left)도 나눠 보세요.
정답
① — '추천'이 메뉴 이름 뒤에서 페이지 맨 위로 올라가 있습니다.
- 기준 상자는 나무를 따라 바깥으로 찾은 첫
position조상입니다.p·body·html어디에도 없어 페이지가 기준 상자이고,top: 0은 페이지 맨 위입니다(브라우저 규칙 8). left를 적지 않아 가로는 원래 있던 자리 — 메뉴 이름 바로 뒤 — 그대로입니다.- ②는 부모
p를 기준 상자로 본 것입니다(부모 기준이라는 생각). 부모가 기준 상자가 되려면 부모에position: relative를 줍니다. - ③은 적지 않은
left도 0이 된다고 본 것입니다.top만 적은 상자는 가로로 원래 자리에 떠 있습니다.
다시 볼 레슨: 기준 상자와 absolute · 일반 흐름과 position
문제 6
레시피 노트 김치볶음밥 페이지의 큰 그림은 마우스를 올리면 1.05배로 커집니다. 움직임 줄이기를 켠 사람에게는 커지지 않게 하려 합니다. ____ 자리에 조건 블록 안에 들어갈 규칙을 쓰세요.
<img
class="dish"
src="images/kimchi.svg"
alt="김치볶음밥"
width="200"
height="150"
>
.dish {
transition:
transform 200ms ease;
}
.dish:hover {
transform: scale(1.05);
}
@media (
prefers-reduced-motion: reduce
) {
____
}
나와야 할 결과는 둘입니다.
- 움직임 줄이기를 켜고 그림에 마우스를 올리면 그림 너비가 200px 그대로다.
- 움직임 줄이기를 켜지 않은 브라우저에서는 마우스를 올리면 그림이 210px로 커진다.
힌트
움직임 줄이기에서 마우스를 올린 그림에 닿는 선언을 기본 규칙 · :hover 규칙 · 조건 블록 순으로 적어 보세요.
힌트 둘
transition: none은 바뀌는 과정만 없앱니다. 끝 모양인 transform은 그대로 닿습니다.
정답
모범 답입니다 — 레슨의 꼴대로 전환과 변형을 둘 다 끕니다.
@media (
prefers-reduced-motion
) {
.dish {
transition: none;
}
.dish:hover {
transform: none;
}
}첫 결과 — 움직임 줄이기를 켜고 마우스를 올린 뒤입니다. 결과 화면은 앞 CSS만 그린 것과 조건 블록까지 그린 것이 차례로 나옵니다.
<img
class="dish"
src="images/kimchi.svg"
alt="김치볶음밥"
width="200"
height="150"
>
.dish {
transition:
transform 200ms ease;
}
.dish:hover {
transform: scale(1.05);
}@media (
prefers-reduced-motion
) {
.dish {
transition: none;
}
.dish:hover {
transform: none;
}
}.dish의 너비200px.dish의transition-duration0s
둘째 결과 — 같은 코드를 움직임 줄이기 없이 마우스를 올린 뒤입니다.
<img
class="dish"
src="images/kimchi.svg"
alt="김치볶음밥"
width="200"
height="150"
>
.dish {
transition:
transform 200ms ease;
}
.dish:hover {
transform: scale(1.05);
}@media (
prefers-reduced-motion
) {
.dish {
transition: none;
}
.dish:hover {
transform: none;
}
}.dish의 너비210px
정답의 코드는 줄 폭 때문에 : reduce를 뺀 꼴로 적었습니다 — 같은 뜻입니다.
다르게 써도 되는 곳:
.dish:hover규칙에transform: none하나만 써도 결과 둘이 맞습니다 — 끝 모양이 그대로면 이어 그릴 것도 없습니다. 레슨의 꼴처럼 전환도 함께 끄면 뒤에:hover에 다른 값을 더해도 움직임 줄이기에서 이어 그리지 않습니다.transform: none대신transform: scale(1)도 원래 크기입니다.
흔한 잘못:
.dish { transition: none; }만 쓰면 첫 결과에서 그림이 한순간에 210px로 커집니다 — 전환만 끄면 순간 이동입니다.- 조건 블록을 기본 규칙 위로 옮기면 나중에 쓴
.dish:hover가 이겨 그대로 커집니다.
다시 볼 레슨: 움직임 줄이기
문제 7
플로우 카페 후기 카드입니다. 어두운 화면 조건 블록에서 면 색 변수만 바꿨습니다. 어두운 화면으로 설정한 브라우저에서 카드와 후기 칸은 어떻게 보일까요? 어두운 화면은 결과 화면이 그리지 않아 글 보기에서 고릅니다.
<div class="card">
<textarea>또 올게요</textarea>
</div>
:root {
--surface: #ffffff;
}
.card {
padding: 16px;
background: var(--surface);
}
@media (
prefers-color-scheme: dark
) {
:root {
--surface: #1d2633;
}
}
- ① 카드도 후기 칸도 밝은 채다
- ② 카드는 어두운 남색이고, 후기 칸은 흰 채다
- ③ 카드도 후기 칸도 어둡다
힌트
어두운 화면에서 --surface의 값을 먼저 정하고, 카드와 후기 칸이 각각 무엇으로 칠해지는지 적어 보세요.
힌트 둘
입력 칸 · 후기 칸은 브라우저가 기본 모양으로 그립니다. 그 모양을 어두운 화면에 맞추는 한 줄이 이 코드에 있는지 보세요.
정답
②입니다. 결과 화면은 밝은 화면으로 그려집니다 — 첫째는 앞 CSS만, 둘째는 조건 블록까지 그린 것이고, 아래 잰 값이 어두운 화면에서 잰 값입니다.
.card의background-colorrgb(29, 38, 51)textarea의background-colorrgb(255, 255, 255)
- 조건이 맞아
--surface가#1d2633이 되고,var(--surface)로 칠한 카드는 규칙을 한 글자도 바꾸지 않았는데 함께 어두워집니다.var()는 지금의 변수 값을 꺼냅니다. - 후기 칸은 우리가 칠하지 않아 브라우저가 기본 모양으로 그립니다.
:root에color-scheme: light dark가 없어 어두운 화면에서도 흰 칸입니다. - ①은
var()가 처음에 꺼낸 값을 한 번 베껴 둔다고 본 것입니다. - ③은 변수를 바꾸면 브라우저가 그리는 칸까지 바뀐다고 본 것입니다. 칸은
color-scheme: light dark를 더해야 어두워집니다(크롬에서는rgb(59, 59, 59)— 칸 모양은 브라우저마다 다릅니다).
다시 볼 레슨: 변수만 바꾸는 다크 모드
문제 8
사진 동아리 공지의 '찾아오는 길' 링크입니다. 어두운 화면에서 읽히게 밝은 파랑을 조건 블록에 따로 적었습니다. 어두운 화면으로 설정한 브라우저에서 '찾아오는 길'의 글자색은 무엇일까요? 코드에 적힌 꼴로 쓰세요.
<p class="notice">
모임 장소
<a href="place.html">
찾아오는 길
</a>
</p>
.notice a {
color: #005bb5;
}
@media (
prefers-color-scheme: dark
) {
a {
color: #9ac7ff;
}
}
힌트
어두운 화면에서 '찾아오는 길'에 닿는 color 선언 둘을 손 점수판에 적어 보세요.
힌트 둘
조건 블록은 그 안 규칙이 닿을지만 정합니다. 닿은 뒤에는 다른 규칙과 같은 차례로 겨룹니다.
정답
받는 답: #005bb5 — 어두운 화면에서도 짙은 파랑 그대로입니다.
a의 글자색rgb(0, 91, 181)
| 속성 | 선언 | 출처 | 명시도 | 차례 | 이긴 값 |
|---|---|---|---|---|---|
color | .notice a · #005bb5 | 우리 CSS | 0-1-1 | 1 | #005bb5 |
a · #9ac7ff | 우리 CSS | 0-0-1 | 2 |
- 어두운 화면에서는 조건이 맞아 블록 안
a규칙도 닿습니다. 그래도 출처가 같아 명시도로 가르고, 클래스 칸에서.notice a가 이깁니다. 조건 블록은 명시도를 올리지 않아 차례 칸까지 가지 않습니다(브라우저 규칙 5). #9ac7ff라고 썼다면 나중에 쓴 쪽이 늘 이긴다고 본 것입니다(뒤가 늘 이긴다는 생각).rgb(0, 91, 181)·rgb(0 91 181)도 같은 답입니다.- 링크 색을
var(--accent)로 꺼내 쓰고 조건 블록에서:root의 변수 값만 바꾸면 이런 겨룸이 생기지 않습니다 — 다크 모드 틀의 하위 목표 2입니다.
다시 볼 레슨: 명시도 · 변수만 바꾸는 다크 모드
문제 9
하고 싶은 일마다 쓸 이름을 떠올려 쓰세요.
- (가) 값이 바뀔 때 앞 값에서 새 값까지를 정한 시간 동안 이어 그리게 하는 CSS 속성
- (나) 요소의 그려진 모습을 옮기거나 키우되, 이웃 요소의 자리는 그대로 두는 CSS 속성
- (다) 사용자가 운영체제의 접근성 설정에서 화면 효과를 줄여 달라고 골랐는지 읽는 미디어 쿼리 조건
- (라) 페이지가 밝은 화면과 어두운 화면을 모두 지원한다고 알려, 입력 칸 같은 브라우저가 그리는 모양을 맞추게 하는 CSS 속성
힌트
(가) · (나)는 영어 낱말 하나이고, (다) · (라)는 낱말 둘 · 셋을 하이픈(-)으로 이은 이름입니다.
정답
받는 답: (가) transition · (나) transform · (다) prefers-reduced-motion · (라) color-scheme
- (다)는
@media (prefers-reduced-motion: reduce)처럼 값reduce까지 쓴 꼴도 같은 답입니다. - (가)와 (나)를 바꿔 쓰기 쉽습니다.
transition은 두 상태 사이를 잇는 과정,transform은 그려진 모습 자체를 바꾸는 일입니다. - (라)를
prefers-color-scheme이라고 썼다면 어두운 화면을 골랐는지 읽는 조건과 헷갈린 것입니다. 조건은 닿을 규칙을 고르고,color-scheme은 브라우저가 그리는 칸 모양을 맞춥니다.
다시 볼 레슨: transition · transform으로 옮기고 키우기 · 움직임 줄이기 · 변수만 바꾸는 다크 모드
문제 10
여행 일정 페이지의 '오늘' 도장을 오른쪽으로 8px, 위로 4px 옮겨 그리려고 두 줄을 썼습니다. 그런데 도장이 위로만 옮겨지고 오른쪽으로는 가지 않았습니다. 개발자 도구에서 도장을 골라 보니 Styles 창의 .stamp 규칙에서 transform: translateX(8px) 줄에 취소선이 그어져 있고, 경고 표시는 없습니다. 이 페이지는 CSS를 HTML 안 style 요소에 썼습니다. 고칠 줄을 골라 고쳐 보세요.
힌트
찾는 차례대로 1번부터 지워 가세요. 취소선은 그 선언이 무엇에 졌다는 표시인지 떠올립니다.
힌트 둘
한 속성에 선언이 둘이면 나중 것이 이깁니다. 옮기기 둘을 함께 하려면 한 선언에 이어 적습니다.
위아래 화살표로 줄을 옮기고 Enter로 고릅니다.
여기서 고친 코드는 저장하지도 보내지도 않습니다. 새로 열면 처음 코드입니다.
정답
받는 답: 7번 줄의 translateY(-4px) 앞에 translateX(8px)을 더해, 두 함수를 한 transform 선언에 잇습니다. 고친 style 요소 안 규칙을 떼어 그리면 이렇습니다.
<div class="stamp">오늘</div>
.stamp {
width: 64px;
height: 32px;
background: #ffe0e0;
transform:
translateX(8px)
translateY(-4px);
}.stamp의 왼쪽 자리16px.stamp의 위 자리4px.stamp의 배치 위 자리8px
찾는 차례 4번에서 찾습니다.
- 1번 — 도장이 위로 4px 옮겨졌으니 규칙은 닿았습니다.
- 2번 — Elements 패널에
div.stamp가 있습니다. - 3번 — Styles 창에
.stamp규칙이 보입니다. - 4번 — 경고 표시가 없으니 두 줄 모두 알아들었습니다. 이겼나를 봅니다.
translateX(8px)줄의 취소선은 같은 속성transform의 다른 선언에 졌다는 표시입니다. 같은 규칙 안이라 나중에 쓴 7번 줄이 이겨 위로만 옮깁니다(브라우저 규칙 5).
두 선언은 합쳐지지 않습니다. 옮기기 둘을 한 선언에 빈칸으로 이어 적으면 둘 다 그려집니다. 도장은 원래 자리(왼쪽 8 · 위 8 — body의 바깥 여백)를 남긴 채 오른쪽으로 8 · 위로 4 옮겨 그려집니다(브라우저 규칙 8).
다르게 고쳐도 되는 곳:
-
6번 줄을 두 함수를 이은 선언으로 고치고 7번 줄을 지워도 같습니다 — 줄 둘을 고쳐야 해서 받는 답으로 두지 않았습니다.
-
두 함수의 차례를 바꿔
translateY()를 먼저 적어도 같은 자리입니다 — 옮기기끼리는 차례가 결과를 바꾸지 않습니다. -
7번 줄을 고친 뒤 6번 줄은 지는 줄로 남습니다. 지워 두면 Styles 창이 깔끔합니다.
-
흔한 오답은 6번 줄에
!important를 붙이는 것입니다. 그러면 오른쪽으로만 옮겨지고 위로는 가지 않습니다 — 이긴 선언이 바뀔 뿐 둘이 합쳐지지 않습니다. -
6번 · 7번 줄의 차례만 바꾸는 것도 흔합니다. 이번에는 오른쪽으로만 옮겨집니다.
다시 볼 레슨: transform으로 옮기고 키우기 · 나중에 쓴 규칙
문제 11 (만들어 보기)
플로우 카페 주문 폼의 CSS입니다. 하위 목표 1(색을 변수로 모으기)은 끝냈습니다.
<form class="order">
<label for="memo">
주문 메모
</label>
<input id="memo">
</form>
/* 1. 색을 변수로 모으기 */
:root {
--surface: #ffffff;
--text: #1d1d1f;
--line: #d2d2d7;
}
.order {
padding: 16px;
border:
1px solid var(--line);
color: var(--text);
background-color:
var(--surface);
}다크 모드 틀의 나머지 하위 목표 둘을 … 자리에 쓰세요. 어두운 값은 --surface #1d2633 · --text #f1f4f8 · --line #3a4552입니다.
/* 2. 어두운 값 */
…
/* 3. color-scheme */
…
나와야 할 결과는 둘입니다.
- 밝은 화면에서는 폼이 채우기 전과 같다 — 흰 바탕 · 짙은 글자 · 회색 선.
- 어두운 화면에서는 폼 바탕 · 글자 · 선이 어두운 값으로 바뀌고, 주문 메모 칸도 어두운 칸 모양으로 그려진다.
힌트
하위 목표 2는 조건 블록 안에 어느 선택자를 두는지, 3은 어느 요소에 한 번 두면 모든 칸이 따르는지 먼저 정하세요.
정답
모범 답입니다.
/* 2. 어두운 값 */
@media (
prefers-color-scheme: dark
) {
:root {
--surface: #1d2633;
--text: #f1f4f8;
--line: #3a4552;
}
}
/* 3. color-scheme */
:root {
color-scheme: light dark;
}첫 결과 — 밝은 화면입니다.
<form class="order">
<label for="memo">
주문 메모
</label>
<input id="memo">
</form>
:root {
--surface: #ffffff;
--text: #1d1d1f;
--line: #d2d2d7;
}
.order {
padding: 16px;
border:
1px solid var(--line);
color: var(--text);
background-color:
var(--surface);
}@media (
prefers-color-scheme: dark
) {
:root {
--surface: #1d2633;
--text: #f1f4f8;
--line: #3a4552;
}
}
:root {
color-scheme: light dark;
}.order의background-colorrgb(255, 255, 255).order의 글자색rgb(29, 29, 31).order의border-top-colorrgb(210, 210, 215)
둘째 결과 — 같은 코드를 어두운 화면에서 잰 값입니다. 결과 화면은 밝은 화면으로 그려집니다.
<form class="order">
<label for="memo">
주문 메모
</label>
<input id="memo">
</form>
:root {
--surface: #ffffff;
--text: #1d1d1f;
--line: #d2d2d7;
}
.order {
padding: 16px;
border:
1px solid var(--line);
color: var(--text);
background-color:
var(--surface);
}@media (
prefers-color-scheme: dark
) {
:root {
--surface: #1d2633;
--text: #f1f4f8;
--line: #3a4552;
}
}
:root {
color-scheme: light dark;
}.order의background-colorrgb(29, 38, 51).order의 글자색rgb(241, 244, 248).order의border-top-colorrgb(58, 69, 82)#memo의color-schemelight dark#memo의background-colorrgb(59, 59, 59)
주문 메모 칸의 rgb(59, 59, 59)는 크롬이 그린 어두운 칸 모양입니다 — 칸 모양은 브라우저마다 다르니, 어두운 칸으로 그려졌는지는 color-scheme이 light dark인지로 봅니다.
확인한 결과가 둘 다 맞으면 맞습니다. 코드가 모범 답과 달라도 됩니다.
다르게 써도 되는 곳:
color-scheme: light dark;를 하위 목표 1의:root끝에 넣어도 같습니다.- 조건 블록 안 세 줄의 차례는 바꿔도 됩니다.
prefers-color-scheme: dark를 한 줄에 써도 같습니다 — 줄 나누기는 줄 폭 때문입니다.
흔한 잘못:
- 조건 블록 안에
.order규칙을 다시 적고 어두운 색을 값으로 쓰면, 이 폼은 어두워져도 다음에 변수를 쓰는 곳을 더할 때마다 블록에 또 적어야 합니다. - 조건 블록을 하위 목표 1의
:root위에 두면 나중에 쓴 밝은 값이 이겨 어두운 화면에서도 밝은 채입니다. - 하위 목표 3을 빠뜨리면 폼은 어두워지는데 주문 메모 칸만 흰 채로 남습니다.
다시 볼 레슨: 변수만 바꾸는 다크 모드
문제 12 (만들어 보기)
레시피 노트의 열다섯째 단계입니다(⟨컴퓨터⟩ · 25분 안팎 · 걸음마다 멈춰도 됩니다). 카드에 마우스를 올리면 살짝 떠오르게 하고, 움직임 줄이기 설정에서는 떠오르지 않게 하고, 어두운 화면 설정에서는 변수 값만 바꿔 어두워지게 합니다. 레시피 노트는 이 단계에서 끝납니다. 15단원 연습 문제의 만들어 보기를 마쳤다면 그 폴더에서 이어 갑니다.
이 단계 시작 파일 — 15단원 끝 상태
recipe-note 폴더에 세 파일을 받아 둡니다.
recipe-note 안에 images 폴더를 만들고 그림 여섯을 받아 둡니다. 앞 단계에서 받았으면 그대로 씁니다.
할 일 — 걸음 넷입니다. 이 단계는 style.css만 고칩니다.
걸음 1 — 카드 떠오르기. 레시피 목록의 카드에 마우스를 올리면 0.18초 동안 위로 4px 떠오르고, 마우스를 떼면 같은 시간 동안 내려오게 합니다. 이웃 카드는 움직이지 않아야 합니다.
걸음 2 — 움직임 줄이기. 운영체제에서 움직임 줄이기를 켠 사람에게는 카드가 떠오르지 않게 합니다. 카드의 글 · 링크 · 배지는 그대로 둡니다.
걸음 3 — 어두운 값. /* 색 */ 구역의 :root 바로 아래에 어두운 화면 조건 블록을 두고, 여섯 변수의 값만 바꿉니다. 카드 · 링크 · 머리글 규칙은 블록 안에 옮겨 적지 않습니다.
| 변수 | 역할 | 어두운 값 |
|---|---|---|
--bg | 페이지 바탕 | #121820 |
--surface | 바탕 위에 올라앉은 면 | #1d2633 |
--text | 글자 | #f1f4f8 |
--muted | 보조 글자 | #a3adb8 |
--line | 선 | #3a4552 |
--accent | 링크 · 강조 · 단추 | #9ac7ff |
걸음 4 — 브라우저가 그리는 모양. 김치볶음밥 페이지 후기 폼의 라디오처럼 우리가 칠하지 않은 칸 모양이 어두운 화면에서 어두운 모양으로 그려지게 :root에 한 줄을 더합니다. 라디오 묶음(fieldset)의 테두리도 다른 선처럼 1px solid와 선 변수 색으로 다시 씁니다 — 기본 테두리는 두 색으로 그려지는 홈 모양이라, 색만 바꾸면 화면에서 선보다 밝게 보입니다.
확인 목록:
- 목록 페이지 카드에 마우스를 올리면 0.18초 동안 떠오르고, 떼면 천천히 내려온다. 아래 · 옆 카드는 그대로다(화면 · 걸음 1).
- 개발자 도구 Rendering에서 움직임 줄이기를 흉내 내고 카드에 마우스를 올리면 카드가 그 자리에 있다 — Computed 창의
transform이none이다(Computed 창 · 걸음 2). - 어두운 화면을 흉내 내면 바탕 · 카드 · 글자 · 링크 · 머리글이 함께 어두운 값으로 바뀐다 —
body의background-color가rgb(18, 24, 32)이다(Computed 창 · 걸음 3). style.css에서#기호로 시작하는 색 값은 두:root의 열두 줄에만 있다(편집기 · 걸음 3).- 어두운 화면에서 후기 폼의 라디오가 어두운 모양이고, 라디오 묶음의 테두리가 표 · 칸의 선과 같은 색 · 같은 굵기다(화면 · 걸음 4).
- 확인이 끝나면 Rendering의 두 흉내를 No emulation으로 되돌린다(네 걸음 끝).
폰으로만 따라왔다면 이 물음 하나로 대신합니다. 걸음 2를 마친 레시피 노트를, 움직임 줄이기를 켠 사람이 보며 카드에 마우스를 올리면 카드는 어떻게 될까요?
- ① 0.18초 동안 4px 떠오른다
- ② 한순간에 4px 떠오른다
- ③ 그 자리에 있다
힌트
걸음마다 그 걸음의 확인 목록을 봅니다. 걸음 2는 끌 것이 전환인지 떠오른 모양인지 둘 다인지 먼저 적고, 걸음 3은 조건 블록 안의 선택자부터 정합니다.
정답
모범 답입니다. 바뀐 곳만 싣습니다 — 다 고친 style.css는 아래 받기 파일과 같습니다(index.html · kimchi.html은 15단원 끝 상태 그대로). 정답의 코드는 줄 폭 때문에 : reduce를 뺀 꼴로 적었습니다 — 받기 파일에는 적혀 있고, 같은 뜻입니다.
/* 색 */
:root {
…
--accent: #005bb5;
color-scheme: light dark;
}@media (
prefers-color-scheme: dark
) {
:root {
--bg: #121820;
--surface: #1d2633;
--text: #f1f4f8;
--muted: #a3adb8;
--line: #3a4552;
--accent: #9ac7ff;
}
}.recipe-card {
…
transition:
transform 180ms ease;
}
.recipe-card:hover {
transform:
translateY(-4px);
}@media (
prefers-reduced-motion
) {
.recipe-card {
transition: none;
}
.recipe-card:hover {
transform: none;
}
}fieldset {
border:
1px solid var(--line);
}카드 하나를 떼어 잰 값입니다. 받기 파일과 같은 선언만 골랐습니다. 결과 화면은 늘 밝은 화면 · 마우스를 올리기 전으로, 앞 CSS만 그린 것과 이어 쓴 CSS까지 그린 것이 차례로 나옵니다.
걸음 3 — 어두운 화면에서 잰 값입니다.
<div class="recipe-card">
<h2>김치볶음밥</h2>
<p>조리 15분</p>
</div>
:root {
--bg: #f5f5f7;
--surface: #ffffff;
}
body {
background: var(--bg);
}
.recipe-card {
background: var(--surface);
}@media (
prefers-color-scheme: dark
) {
:root {
--bg: #121820;
--surface: #1d2633;
}
}body의background-colorrgb(18, 24, 32).recipe-card의background-colorrgb(29, 38, 51)
걸음 2 — 움직임 줄이기에서 카드에 마우스를 올린 뒤 잰 값입니다.
<div class="recipe-card">
김치볶음밥
</div>
.recipe-card {
transition:
transform 180ms ease;
}
.recipe-card:hover {
transform:
translateY(-4px);
}@media (
prefers-reduced-motion
) {
.recipe-card {
transition: none;
}
.recipe-card:hover {
transform: none;
}
}.recipe-card의transformnone.recipe-card의transition-duration0s.recipe-card의 위 자리8px
확인 목록을 다 채웠으면 맞습니다. 코드가 모범 답과 달라도 됩니다.
다르게 써도 되는 곳:
color-scheme: light dark;는 따로:root규칙을 하나 더 두어 적어도 같습니다.- 움직임 줄이기 조건 블록은
.recipe-card:hover규칙 뒤라면 파일 끝에 두어도 됩니다. - 떠오르는 시간은 0.15 ~ 0.25초 안이면 됩니다. 1초를 넘기면 기다리게 됩니다.
흔한 잘못:
- 걸음 1에서
transition을.recipe-card:hover에만 두면, 마우스를 뗄 때 카드가 툭 떨어집니다. - 걸음 1에서
margin-top: -4px로 올리면 아래 카드까지 함께 올라갑니다 — 격자 줄이 흔들립니다. - 걸음 2에서
transition: none만 두면 움직임 줄이기에서 카드가 한순간에 떠오릅니다. - 걸음 3의 조건 블록을
/* 색 */구역의:root위에 두면 나중에 쓴 밝은 값이 이겨 어두운 화면에서도 밝은 채입니다. - 걸음 4를 빠뜨리면 글자 칸 · 별점 칸은 변수로 칠해 어두워져도, 라디오는 밝은 모양으로 남습니다.
- 걸음 4에서
fieldset에border-color만 주면 계산된 색은 선 변수와 같아도, 기본 테두리가 두 색으로 그려지는 홈 모양이라 화면에서는 표 선보다 밝게 보입니다.
폰 물음의 답은 ③입니다. ②는 전환만 끈 꼴, ①은 조건 블록이 없는 꼴입니다.
다시 볼 레슨: transition · transform으로 옮기고 키우기 · 움직임 줄이기 · 변수만 바꾸는 다크 모드