Writing modes/Vertical form controls

김동현·2026년 3월 21일

mdn 학습 번역 - CSS

목록 보기
170/190

안녕하세요! 프론트엔드 강사입니다.

여러분, 웹 페이지를 만들 때 <input type="range"> (슬라이더)나 <progress> 바가 기본적으로 항상 가로 방향(수평)으로만 렌더링되어서 답답했던 적 있으신가요?
오디오 볼륨 조절기나 이퀄라이저처럼 슬라이더를 세로 방향(수직)으로 세우고 싶은데, 예전에는 이걸 하려고 자바스크립트를 복잡하게 짜거나 transform: rotate(-90deg) 같은 꼼수를 써야만 했습니다. (이러면 레이아웃 다 깨지고 난리도 아니었죠!)

하지만 이제는 CSS만으로 아~주 깔끔하고 우아하게 폼 컨트롤 요소들을 수직으로 세울 수 있게 되었습니다! 어떻게 하는지 MDN 문서를 통해 바로 확인해 볼까요?


수직 폼 컨트롤 만들기 (Creating vertical form controls)

이 가이드는 CSS의 writing-mode (글쓰기 방향) 속성과 direction (텍스트 방향) 속성을 사용하여 세로 방향의 폼 컨트롤(vertical form controls)을 만들고 설정하는 방법을 설명합니다.

여기서 다룰 요소들은 다음과 같습니다:


이 문서의 목차 (In this article)


일반적인 기법 (General technique)

최신 브라우저에서는 writing-mode 속성에 수직 방향 값(vertical value)을 주면 폼 컨트롤을 수직으로 렌더링할 수 있습니다.
원래 영어, 한국어 같은 라틴계열 언어의 텍스트는 수평으로 쓰여지는데, 이 속성을 주면 글자들이 시계 방향으로 90도 돌아가 누운 채로 세로로 쌓이게 됩니다. 반면, 중국어나 일본어 같이 원래 세로쓰기가 가능한 문자들은 돌아가지 않고 올바르게 서 있는 형태로 나열됩니다.

👨‍🏫 강사님의 꿀팁 & 보충설명:
writing-mode는 원래 아시아권 언어의 "세로쓰기"를 위해 도입된 속성이지만, 부가적으로 슬라이더나 버튼 같은 폼 요소 자체를 세로로 세워버리는 훌륭한 부작용(?)을 가지고 있습니다!
예전처럼 transform: rotate(90deg)를 쓰면 요소가 돌아가면서 주변 레이아웃을 겹치게(overlap) 만들거나 여백 계산이 엉망이 되는데, writing-mode를 쓰면 요소의 진짜 물리적인 가로/세로 크기가 완벽하게 바뀌기 때문에 레이아웃이 전혀 깨지지 않습니다.

구체적인 속성값은 이렇습니다:

  • writing-mode: vertical-lr: (Left-to-Right) 수직 폼 컨트롤을 만들되, 블록(Block)의 흐름이 왼쪽에서 오른쪽으로 향합니다. 즉, 텍스트가 여러 줄일 때 두 번째 줄은 첫 번째 줄의 오른쪽에 나타납니다.
  • writing-mode: vertical-rl: (Right-to-Left) 수직 폼 컨트롤을 만들되, 블록의 흐름이 오른쪽에서 왼쪽으로 향합니다. 즉, 텍스트가 여러 줄일 때 두 번째 줄은 첫 번째 줄의 왼쪽에 나타납니다. (전통적인 동양의 세로쓰기 방식이죠.)

참고 (Note): writing-mode 속성 자체는 아주 오래전부터 지원되었지만, 이를 이용해서 폼 요소(Form controls)를 수직으로 세우는 기능은 2024년이 되어서야 모든 브라우저에서 완벽하게 지원되기 시작했습니다. (그 전에는 브라우저마다 렌더링이 달랐어요!)

참고 (Note): 실험적인 기능인 sideways-lrsideways-rl 값은 위 값들과 비슷하게 동작하지만, 중국어/일본어 같은 세로쓰기 문자까지 강제로 90도 눕혀버린다는 차이가 있습니다.

여기에 추가로, direction 속성을 사용하면 컨트롤 내부 콘텐츠의 진행 방향을 바꿀 수 있습니다:

  • direction: ltr: (Left-to-Right의 약자지만 세로 모드에서는) 콘텐츠가 위에서 시작해 아래로 흐르게 합니다.
  • direction: rtl: (Right-to-Left의 약자지만 세로 모드에서는) 콘텐츠가 아래에서 시작해 위로 흐르게 합니다.

direction 속성은 인라인 기본 방향(inline base direction)을 설정합니다. 글자가 들어간 텍스트 박스라면 글이 위에서부터 읽힐지, 아래에서부터 읽힐지를 결정하죠.
하지만 범위 슬라이더(range slider)처럼 텍스트가 없는 컨트롤에서는 컨트롤이 그려지는 방향을 의미합니다.

👨‍🏫 강사님의 핵심 꿀팁:
세로 슬라이더를 만들 때 이 direction 속성이 제일 중요합니다!
세로 슬라이더에 direction: ltr(기본값)을 주면 최솟값(0)이 맨 에 있고, 최댓값(100)이 맨 아래에 위치합니다.
하지만 우리가 아는 볼륨 조절기는 보통 위로 올릴수록 값이 커지죠? 이때 direction: rtl;을 주면 최솟값이 맨 아래로, 최댓값이 맨 위로 가도록 슬라이더의 방향을 180도 홱 뒤집어줍니다!

자, 이제 이 기능들을 활용해서 각 폼 요소들을 직접 세로로 세워봅시다!


범위 슬라이더, 미터, 프로그래스 바 (Range sliders, meters, and progress bars)

기본 예제 (Basic example)

먼저 슬라이더(<input type="range">), 진행률 바(<progress>), 미터기(<meter>)를 수직으로 세워보겠습니다.

HTML:

<form>
  <input type="range" min="0" max="11" value="9" step="1" />
  
  <meter id="fuel" min="0" max="100" low="33" high="66" optimum="80" value="20">
    at 50/100
  </meter>
  
  <progress id="file" max="100" value="70">70%</progress>
</form>

CSS:

input[type="range"],
meter,
progress {
  margin-block-end: 20px;
  writing-mode: vertical-lr; /* 핵심! 요소를 수직으로 세웁니다. */
}

이렇게 하면 브라우저에서 슬라이더와 바들이 깔끔하게 세로로 서 있는 것을 볼 수 있습니다!


컨트롤을 아래에서 위로 그리기 (Drawing the control from bottom to top)

앞서 말씀드렸듯, 기본적으로 슬라이더는 위쪽이 0, 아래쪽이 100(최댓값)입니다. 이걸 뒤집어 볼까요?

CSS:

input[type="range"],
meter,
progress {
  margin-block-end: 20px;
  writing-mode: vertical-lr;
  direction: rtl; /* 방향 뒤집기! 이제 값이 아래에서부터 위로 채워집니다. */
}

direction: rtl; 한 줄만 추가하면 마법처럼 슬라이더의 게이지가 아래에서 위로 차오르는 완벽한 볼륨 조절기 UI가 완성됩니다!


구형 브라우저에서 수직 슬라이더 만들기 (Legacy browsers)

만약 2024년 이전의 구형 브라우저(특히 예전 크롬, 사파리, 파이어폭스)를 지원해야 한다면 어떻게 해야 할까요? 아쉽게도 <meter><progress>는 방법이 없지만, <input type="range">에 한해서는 몇 가지 꼼수(편법)가 있습니다.

  1. 구형 Chrome / Safari: CSS에 비표준 속성인 appearance: slider-vertical;을 추가합니다.
  2. 구형 Firefox: HTML 요소 자체에 비표준 속성인 orient="vertical"을 추가합니다.
<input type="range" min="0" max="11" value="9" step="1" orient="vertical" />
/* 구형 웹킷 기반 브라우저를 위한 CSS */
input[type="range"] {
  appearance: slider-vertical;
}

(하지만 이제는 대부분 writing-mode를 지원하므로 최신 프로젝트에서는 이 구형 방법들을 굳이 쓸 필요가 없습니다.)


Select 요소 (Select elements)

<select> 태그 (드롭다운이나 다중 선택 리스트박스)도 세로로 세울 수 있습니다.

Select 기본 예제

HTML: 여러 개를 선택할 수 있는 multiple select와 일반 select를 만들어 봅시다.

<form>
  <select multiple>
    <option>First</option>
    <option>Second</option>
    <option>Third</option>
    <option>Fourth</option>
    <option>Fifth</option>
  </select>
</form>

CSS:

select {
  inline-size: 100px; /* 세로 모드이므로 이 값은 사실상 세로 높이(height)를 의미하게 됩니다! */
  margin-block-end: 20px;
  writing-mode: vertical-rl; /* 우측 상단에서 시작해 아래로 텍스트가 흐릅니다 */
}

👨‍🏫 강사님의 꿀팁:
여기서 inline-size라는 논리적 속성(Logical Properties)을 쓴 것에 주목하세요! writing-mode가 수직으로 바뀌면 글자가 흐르는 인라인 방향도 세로가 됩니다. 따라서 width 대신 inline-size를 쓰면, 세로 모드일 때는 높이(height)를, 가로 모드일 때는 너비(width)를 컨트롤하게 되어 반응형 레이아웃을 짜기 훨씬 수월해집니다!


텍스트 방향과 옵션 순서 조절하기 (Adjusting text direction and option order)

<select> 요소에서 directionwriting-mode 값들을 섞어 쓰면 글씨가 어떻게 변하는지 비교해 보겠습니다.

/* 1. 기본 세로 (우측에서 좌측으로 블록이 쌓임) */
select {
  writing-mode: vertical-rl;
}

/* 2. 글씨 역방향 (글자가 아래에서 위로 거꾸로 써짐!) */
.direction select {
  writing-mode: vertical-rl;
  direction: rtl;
}

/* 3. 블록 쌓이는 순서 역방향 (옵션이 좌측에서 우측으로 쌓임) */
.reverse-option-order select {
  writing-mode: vertical-lr; 
}

버튼 (Buttons)

<button>, <input type="button">, <input type="submit"> 요소들도 세울 수 있습니다.

<button>Press me<br />Please?<br />Thanks</button>
button {
  inline-size: 100px; /* 버튼의 세로 길이 */
  writing-mode: vertical-rl; /* 버튼 안의 글씨를 세로로! */
}

이것도 마찬가지로 vertical-lr로 바꾸면 첫 번째 줄이 왼쪽에, 다음 줄이 오른쪽에 나타나게 됩니다.


텍스트 기반 폼 컨트롤 (Text-based form controls)

마지막으로 텍스트를 입력받는 <textarea><input type="text">입니다. (비밀번호 입력창이나 URL 입력창도 동일하게 작동합니다.)

<form>
  <textarea>This is my textarea</textarea>
  <input type="text" value="Input text" />
</form>
textarea,
input[type="text"] {
  inline-size: 100px; 
  writing-mode: vertical-rl; /* 입력창의 커서가 오른쪽 위에서 깜빡거리고 아래로 써집니다! */
}

만약 텍스트에라어(<textarea>)에서 vertical-lr을 쓰면, 엔터를 칠 때마다 다음 줄이 왼쪽이 아닌 오른쪽에 생기게 됩니다. 이렇게 텍스트 입력창 자체의 성질을 완벽하게 수직 문자로 탈바꿈시킬 수 있습니다.


같이 보기 (See also)

더 자세한 내용을 알고 싶으시다면 아래 문서를 참고해 보세요!


MDN 개선에 도움을 주세요 (Help improve MDN)

이 페이지가 도움이 되었나요? (Was this page helpful to you?)

이 페이지는 MDN 기여자들에 의해 2025년 12월 15일에 마지막으로 수정되었습니다.


어떠셨나요? 이제 복잡한 자바스크립트나 transform 회전 없이도 writing-mode 속성 하나만으로 아주 깔끔하고 반응형에 완벽하게 대응하는 세로 슬라이더와 세로 입력창을 만들 수 있겠죠? 당장 오늘 여러분의 토이 프로젝트에 엣지 있는 세로 볼륨 슬라이더를 추가해 보세요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글