본문으로 건너뛰기

.sr-only 한 줄씩

HTML·CSS 목차겹치고 고정하기: position레슨 80 / 93

목차

.sr-only 규칙의 여섯 선언은 라벨을 흐름에서 빼고(absolute), 1 × 1 크기로 줄이고, 그 밖과 안을 잘라(overflow · clip-path) 화면에서만 숨깁니다. 그리기는 하니 칸의 읽는 이름은 그대로 남습니다.

7단원 글자 없는 단추와 숨긴 라벨에서는 여섯 줄을 뜻을 묻지 않고 복사해 두었습니다. 이제 이 단원에서 배운 흐름 밖 상자 · 원래 자리 · 자르기로 한 줄씩 읽을 수 있습니다. 줄마다 하는 일을 알면, 한 줄이 빠져 라벨이 보이거나 칸이 밀릴 때 어느 줄인지 바로 찾습니다.

그림 준비 중

1흐름에서 빼기 — position: absolute

레시피 목록의 검색 칸입니다. 라벨 '검색할 요리'를 화면에서만 숨겼습니다.

<label
  for="recipe-search"
  class="sr-only"
>
  검색할 요리
</label>
<input id="recipe-search" />
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
결과 화면
잰 값개발자 도구에서 본 값
  • input의 읽는 이름검색할 요리
  • label의 너비1px
  • label의 높이1px
  • label의 위 자리8px
  • input의 왼쪽 자리8px
  • label의 displayblock

첫 줄 position: absolute는 라벨을 흐름에서 뺍니다. 라벨이 줄에서 자리를 비워, 칸이 줄 맨 앞(왼쪽 8)으로 옵니다. top 등이 없으니 라벨은 기준 상자를 찾아가지 않고 원래 있던 자리(위 8 · 왼쪽 8)에 1 × 1로 떠 있습니다(브라우저 규칙 8).

absolute에는 또 하나의 일이 있습니다. label은 인라인이라 그대로는 width · height가 쓰이지 않는데, 흐름에서 빠진 상자는 블록처럼 그려져(잰 값 display가 block) 다음 두 줄의 크기가 쓰입니다.

2줄이고 자르기 — 나머지 다섯 줄

선언하는 일
width: 1px · height: 1px라벨 상자를 1 × 1로 줄입니다
overflow: hidden1 × 1 밖으로 넘친 글을 자릅니다
clip-path: inset(50%)네 변에서 절반씩 안으로 들어간 사각형만 보이게 해, 남은 1 × 1마저 지웁니다
white-space: nowrap글이 줄을 꺾지 않고 한 줄로 이어진 채 잘리게 합니다

1 × 1로 줄이기만 하면 글은 상자 밖으로 넘쳐 그대로 보입니다. 1px 폭이라 '검색할 요리'가 한 글자씩 꺾여 세로로 쌓이기도 합니다 — 그릴 때 줄을 꺾는 것은 빈칸뿐 아니라 한글 글자 사이도 됩니다(브라우저 규칙 2). overflow: hidden이 넘친 글을 자르고, clip-path가 남은 한 점까지 지우며, nowrap이 글을 한 줄로 둡니다. clip-path의 inset()은 자르는 사각형의 모양이고, 덮개를 놓을 때 쓴 위치 속성 inset과는 다른 것입니다.

여섯 줄이 다 지운 것은 화면에 그려진 모습뿐입니다. 라벨은 나무에 그대로 있고 그려지기도 하니, 칸의 읽는 이름은 처음부터 끝까지 '검색할 요리'입니다(브라우저 규칙 3). 자료에 따라 clip-path 자리에 clip: rect(0, 0, 0, 0)⁠을 쓴 옛 꼴도 보입니다. 흐름에서 빠진 상자(absolute · fixed)만 자르는 옛 속성으로, 하는 일은 같고 지금은 clip-path를 씁니다.

예제

할 일 화면의 입력 줄

할 일 화면의 폼은 라벨 · 입력 칸 · 단추를 flex 한 줄로 놓습니다. 결과 화면을 펴기 전에, 숨긴 라벨이 flex 줄에서 자리를 차지할지 먼저 적어 보세요.

<form id="todo-form">
  <label
    for="todo-input"
    class="sr-only"
  >
    할 일
  </label>
  <input
    id="todo-input"
    placeholder="예: 장보기"
  />
  <button type="submit">
    추가
  </button>
</form>
#todo-form {
  display: flex;
  gap: 8px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
결과 화면 보기
결과 화면
잰 값개발자 도구에서 본 값
  • input의 읽는 이름할 일
  • input의 왼쪽 자리8px
  • label의 너비1px
  • 흐름에서 빠진 라벨은 flex 항목이 아닙니다. 줄의 첫 항목은 입력 칸이라 칸이 폼 맨 앞(왼쪽 8)에서 시작하고, 라벨 몫의 gap도 생기지 않습니다.
  • 칸의 읽는 이름은 숨긴 라벨의 '할 일'입니다. placeholder '예: 장보기'는 보기 글일 뿐 이름이 아닙니다.

예상과 다르면 그곳이 배울 곳입니다.

자주 틀리는 곳

틀린 생각: class="sr-only"를 붙이고 규칙을 쓰면, 선택자 글자가 조금 달라도 숨는다.

<label
  for="recipe-search"
  class="sr-only"
>
  검색할 요리
</label>
<input id="recipe-search" />
.sronly {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
결과 화면
잰 값개발자 도구에서 본 값
  • label의 positionstatic
  • label의 width 선언(없음)

결과 화면에 '검색할 요리'가 그대로 보입니다. 선택자 .sronly는 HTML의 sr-only와 글자가 달라 라벨을 고르지 못했습니다. 규칙은 오류 없이 아무 데도 닿지 않습니다(브라우저 규칙 4).

맞는 규칙: 라벨이 보이면 먼저 개발자 도구 Styles 창에 .sr-only 규칙이 닿았는지 봅니다. 클래스 이름과 선택자는 한 글자까지 같아야 합니다.

틀린 생각: 더 확실히 숨기려면 .sr-only에 display: none을 더한다.

<label
  for="recipe-search"
  class="sr-only"
>
  검색할 요리
</label>
<input id="recipe-search" />
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  display: none;
}
결과 화면
잰 값개발자 도구에서 본 값
  • input의 읽는 이름(없음)

화면은 같아 보이지만 칸의 읽는 이름이 비었습니다. display: none은 라벨을 아예 그리지 않아 읽는 쪽에서도 지웁니다(브라우저 규칙 3). 여섯 줄이 지키던 이름을 한 줄이 없앴습니다.

맞는 규칙: .sr-only에는 여섯 줄만 둡니다. 화면에서만 숨기는 여섯 줄과 모두에게서 숨기는 display: none · hidden은 일이 다릅니다.

틀린 생각: 칸 아래 도움말도 .sr-only로 숨기면 화면이 깔끔하다.

<label for="recipe-search">
  검색할 요리
</label>
<input id="recipe-search" />
<p class="sr-only">
  한 낱말로 찾습니다
</p>
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
결과 화면
잰 값개발자 도구에서 본 값
  • p의 너비1px

도움말은 듣는 사람에게만 남고, 보는 사람은 '한 낱말로 찾는다'는 것을 모릅니다. .sr-only는 보이지 않아도 되는 글(화면에서는 모양 · 자리로 뜻이 이미 전해지는 글)에만 씁니다.

맞는 규칙: 화면에 보여야 할 글은 숨기지 않습니다. .sr-only는 보는 사람이 이미 아는 것을 듣는 사람에게도 알려 줄 때 씁니다.

확인 문제

1. 예제의 .sr-only에서 width: 1px;과 height: 1px; 두 줄을 지웠습니다. 라벨 '할 일'이 화면에 보일까요, 입력 칸이 밀릴까요?

<form id="todo-form">
  <label
    for="todo-input"
    class="sr-only"
  >
    할 일
  </label>
  <input
    id="todo-input"
    placeholder="예: 장보기"
  />
  <button type="submit">
    추가
  </button>
</form>
#todo-form {
  display: flex;
  gap: 8px;
}

.sr-only {
  position: absolute;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
  • ① 라벨이 보이고, 칸은 그대로
  • ② 라벨은 보이지 않고, 칸도 그대로
  • ③ 라벨은 보이지 않지만, 칸이 오른쪽으로 밀림
힌트

남은 네 줄 가운데 무엇이 그려진 모습을 지우고, 무엇이 자리를 비우는지 2절 표와 1절에서 찾아봅니다.

정답

②입니다.

결과 화면
잰 값개발자 도구에서 본 값
  • input의 왼쪽 자리8px
  • label의 positionabsolute
  • input의 읽는 이름할 일
  • 라벨 상자는 글만큼 커졌지만 clip-path: inset(50%)⁠가 모두 지워 보이지 않습니다. absolute가 남아 있어 흐름에서도 빠져, 칸은 그대로 줄 맨 앞입니다.
  • 흔한 오답은 ①입니다. 1 × 1로 줄이는 두 줄이 숨기는 일을 한다고 본 것입니다. 숨기는 일은 자르는 두 줄이, 자리를 비우는 일은 absolute가 합니다.

2. .sr-only 여섯 줄 가운데 한 줄이 비었습니다. 1 × 1 밖으로 넘친 글을 자르는 줄을 쓰세요.

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  ____
  clip-path: inset(50%);
  white-space: nowrap;
}
힌트

앞 레슨에서 둥근 선 밖의 그림을 자를 때 쓴 선언을 떠올려 봅니다.

정답

overflow: hidden;입니다.

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

1 × 1 상자의 안쪽 여백 가장자리 밖으로 넘친 글을 그리지 않습니다. clip이나 display: none을 쓰는 답이 흔합니다. display: none은 이름까지 지웁니다.

3. 여행 일정 페이지의 도시 칸입니다. 라벨 '도시 이름'을 화면에서만 숨기려 했는데, 라벨은 그대로 보이고 입력 칸이 보이지 않습니다. 이 페이지 CSS에는 .sr-only 여섯 줄이 있습니다. 몇 번 줄을 어떻게 고칠까요?

<label for="city">
  도시 이름
</label>
<input
  id="city"
  class="sr-only"
/>
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
힌트

class="sr-only"가 어느 요소에 붙었는지 봅니다.

정답

html 6번 줄의 class="sr-only"를 지우고, 1번 줄 라벨에 붙입니다. 고치기 전 잰 값은 이렇습니다.

결과 화면
잰 값개발자 도구에서 본 값
  • input의 width1px
  • input의 읽는 이름도시 이름

고친 뒤입니다.

<label
  for="city"
  class="sr-only"
>
  도시 이름
</label>
<input id="city" />
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
결과 화면
잰 값개발자 도구에서 본 값
  • label의 너비1px
  • input의 읽는 이름도시 이름
  • 고치기 전에는 칸이 1 × 1로 숨어, 이름은 남아도 마우스로 누를 수 없고 키보드로 들어가도 친 글이 보이지 않았습니다. 숨길 것은 칸이 아니라 라벨입니다.
  • 흔한 오답은 .sr-only에 선언을 더하는 답입니다. 규칙은 맞고, 붙인 자리가 틀렸습니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 1절 예제를 index.html과 style.css로 저장하고 link로 이어 엽니다(문서 뼈대의 body 안에 예제 HTML을 넣습니다). .sr-only의 여섯 줄을 아래에서부터 한 줄씩 지우며 저장 · 새로고침하고, 라벨이 다시 보이는 것은 몇 줄째를 지웠을 때인지 적어 봅니다. 줄마다 칸을 검사해 Accessibility 창의 Name이 '검색할 요리'로 남는지도 봅니다.

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

HTML·CSS 목차로