# 효과적인 웹 타이포그래피와 스페이싱 설계의 이해 ~~라고 괜히 거창하게 써봄..~~ 오늘 자습 시간에 추상적이지만 좋은 질문이 디코에 올라왔습니다. "기본적인 사이즈 및 여백 설정에 대해 어떻게 공부해야 할까요?" 이 질문에 대한 답변을 생각해보고 스스로 답을 내리기에 구체적이지 않은 부분을 검색으로 찾아보면서 이해한 내용을 정리합니다. 여백(간격) 설정은 웹 디자인의 기초지만 직관적으로 이해하기 어려운 부분이 많다고 느낍니다. 절대값과 상대값을 어떻게 설정해야 하는지, 어떤 기준으로 설정해야 하는지, 어떤 방식으로 설정해야 하는지 등에 대한 고민이 크죠. 절대값으로 핸들링하면야 편하겠지만, 내가 서빙하는 웹페이지(앱일 수도 있고)를 사용하는 사용자의 환경(디바이스, 브라우저, 시력 등)에 따라 랜더링 되는 최종 모양새가 달라지니 어려울 수 밖에요. 게다가 우리는 처음으로 웹 사이트를 만드는 경험을 하는 중이니, 더 어려울 수 밖에 없습니다. 저는 약간의 프론트 지식이 있는 상태에서 처음 디코의 질문을 읽었을 때, 가장 먼저 떠오른 것은 **타이포그래피와 여백을 어떻게 설정하는지**에 대한 것이었습니다. 그리고 이 부분을 컨트롤하는데 있어 가장 중요한 것은 시각적 계층(Visual Hierarchy)을 만드는 것이라는 주관이 있습니다. 우리가 만드는 디자인과 프론트엔드 엔지니어링 기법은, 사용자가 웹사이트를 보고 정보를 쉽게 찾을 수 있도록 도와주는 것이 궁극적인 목표 중 하나니까요. 이런 주관을 가지고 타이포그래피와 스페이싱 시스템을 기준잡아 정보를 탐색했습니다. 여러 공학적인 근거를 찾아보기에 앞서, 잘 만들어졌다고 생각되는 몇개의 사이트들을 후보로 골라두고 개발자도구를 이용한 스타일을 분석하는 방식으로 접근했구요. 그 결과, 대부분의 사이트들은 기본적으로 16px의 폰트 사이즈를 기준으로 타이포그래피와 간격을 설정하고 있었습니다. 그리고 간격 조정에는 예전과는 다르게 절대값인 px을 지양하고 상대값인 em, rem 사용을 지향하는 경향도 발견했구요. 대부분의 브라우저(크롬, 엣지, 파폭, 아크 등..)는 16px을 기본 글꼴 크기로 채택했습니다. 평균적인 시력을 가진 사용자가 60cm 거리에서 읽기에 적합한 크기로, 16px 의 폰트 사이즈가 규정된 것 같고, 이게 W3C가 권장하는 접근성 가이드라인에 부합하는 수치로 해석됩니다. ### 참고 - W3C는 웹 접근성을 위해 WCAG([https://www.w3.org/TR/WCAG21/](https://www.w3.org/TR/WCAG21/))를 제공하고 있고, 가장 널리 사용되는 웹 접근성 가이드라인입니다. 몇년 전 2.2버전이 나왔고, 3.0버전도 준비중입니다. 접근성 가이드라인에서 시야각에 대한 가이드를 제공하고 있는데, 이를 통해 브라우저를 만드는 벤더들이 기본 글꼴 크기를 16px로 설정하게 된 것으로 추정됩니다. - 크롬 브라우져 주소창에 [chrome://settings/fonts](chrome://settings/fonts) 를 입력해보세요. - 1rem은 루트 요소(html)의 폰트 사이즈를 기준으로 계산됩니다. - 1em은 부모 요소의 폰트 사이즈를 기준으로 계산됩니다. - 생각보다 훨씬 잘 기술되어있는 em,rem https://developer.mozilla.org/ko/docs/Web/CSS/font-size - line-height는 폰트 사이즈의 배수로 설정하는 것이 좋다고 합니다. https://developer.mozilla.org/en-US/docs/Web/CSS/line-height ## 타이포그래피 기본 단위와 계층 구조 ### 기본 타이포그래피 설정의 원칙 웹사이트 타이포그래피 설계는 정보에 맥락을 부여하고 시각적 계층(Visual Hierarchy)을 만드는 일입니다. 다음과 같은 기본값을 시작점으로 삼는 것이 좋은듯 합니다. ```css :root { /* 기본 타이포그래피 설정 */ font-size: 16px; line-height: 1.5; /* 16px * 1.5 = 24px */ } p { font-weight: 400; /* 400이 스펙 상 기본 값이긴 합니다만, 명시적이어서 나쁠 건 없죠 */ margin-bottom: 1.5em; /* line-height와 동일 */ } ``` 이 기본값을 설정한 후 정보의 **중요도**에 따라 타이포그래피를 조절합니다. ```css h1 { font-size: 2.5em; /* 40px */ } h2 { font-size: 2em; /* 32px */ } h3 { font-size: 1.75em; /* 28px */ } h4 { font-size: 1.5em; /* 24px */ } ``` 잠시 여담입니다만, 연관된 공학 분야로 정보 아키텍처(Information Architecture)라는 것이 있습니다. 토스의 디자인 시스템은 IA를 중요시 여기고 앱은 웹 전근성이 높기로 유명하죠. 정보를 단순히 하나의 스타일로 뭉개어 처리하지 않고 시각적 계층 및 중요도를 분류해 맥락을 표시함으로써 정보를 쉽게 찾을 수 있도록 도와주는 것이 그 목적인 기술분야 입니다. 본문에 여러 정보를 짬뽕해두면 제대로 된 타이틀을 뽑아내기 어렵습니다. 특정한 섹션의 정보를 제공할 때, 타이틀이 되는 요소를 헤더로 표현하는 것은 이런 원칙을 따르는 것이라고 볼 수 있습니다. 좋은 아티클을 소개합니다 [[번역] 웹디자인을 위한 IA(Information Architecture) 만들기](https://medium.com/@mistam0264/%EB%B2%88%EC%97%AD-%EC%9B%B9%EB%94%94%EC%9E%90%EC%9D%B8%EC%9D%84-%EC%9C%84%ED%95%9C-ia-information-architecture-%EB%A7%8C%EB%93%A4%EA%B8%B0-12e13e9c8e84) ## 간격(Spacing) 시스템 설계 자 다음은 간격입니다. 여백은 두가지 방식으로 제어할 수 있습니다. 마진과 패딩. 크롬 개발자도구를 이용해서 웹사이트들을 살펴볼 때, Element 탭에서 각 요소의 스타일을 분석해보면 대부분의 요소들이 마진과 패딩을 사용하고 있죠. 이 두 속성은 박스 모델(Box Model)의 일부로, 요소의 크기와 위치를 제어하는 데 사용됩니다. ``` +-----------------------------------+ | MARGIN | | +---------------------------+ | | | BORDER | | | | +-------------------+ | | | | | PADDING | | | | | | +-----------+ | | | | | | | CONTENT | | | | | | | +-----------+ | | | | | +-------------------+ | | | +---------------------------+ | +-----------------------------------+ ``` 마진과 패딩 중 무엇을 사용할까? 를 먼저 가볍게 정리하면 다음과 같습니다. - "요소 자체의 모양과 느낌"을 조정 하는 건 → 패딩 - "요소와 다른 요소와의 관계"를 조정 하는 건 → 마진 정도로 이해하면 될 것 같습니다. ### 자꾸 요소 요소 하는데 요소가 뭐냐면... 위에서도 블록 레벨 요소라거나, 인라인 요소라는 단어가 나왔었는데 요걸 또 한 번 정리하고 넘어가면 다음 내용을 읽기에 좀 더 나은데요. HTML 요소들은 크게 세 가지 표시 방식으로 나뉩니다. `블록 요소(Block elements)` - 예: div, p, h1 ~ h6, ul, li - 가장 쉬운 이해: 한 줄을 통째로 차지함! - 부모 요소의 전체 너비를 차지함 - 높이, 너비, 여백 등 모든 박스 모델 속성이 적용됨. `인라인 요소(Inline elements)` - 예: span, a, strong, [em](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)(단위 말하는 것 아님 Emphasis 요소임) - 줄바꿈 없이!! 텍스트 흐름 내에서 표시 됨 - width와 height 속성이 적용되지 않음. - 상하(top/bottom) 마진이 적용되지 않음. - 패딩, 보더, 좌우(left/right) 마진은 적용됨. `인라인-블록 요소(Inline-block elements)` - 예: img, input, button - 인라인처럼 텍스트 흐름 내에 표시되지만 - 블록 요소처럼 width, height, 모든 마진을 설정할 수 있음! 예외적인 짬뽕 요소들이 있나봅니다. 원래 세상 모든 것에는 예외가 있으니 넘어가 줍시다. 이제 하나씩 조금 더 구체적으로 들여다보죠. ### 1. 마진(margin) - 요소 **외부** 여백 - 요소 간 관계를 정의하는 데 사용 - 주의: 마진 상쇄([Margin Collapse](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing)) 현상 발생 - div, p, h1 등 한 줄을 통째로 차지하는 두 개 이상의 블록 레벨 요소의 수직 방향 마진이 만나면 큰 마진 값으로 병합되는 현상이라고 이해했습니다. 블록 요소의 상단과 하단에 마진이 있는 경우에만 발생합니다. - 해외에 이 부분의 시각화를 잘 해둔 아티클이 있으니 한번 읽어보세요. [The Rules of Margin Collapse](https://www.joshwcomeau.com/css/rules-of-margin-collapse/) - 이러한 마진 상쇄 현상을 피하기 위해 위 혹은 아래 등 단일 방향으로만 마진을 기본적용하는 기법이 보편적인 것 같습니다. ```css .element { margin: 1.5rem; /* 상하좌우 모두 여백 */ margin: 1rem 2rem; /* 상하 1rem, 좌우 2rem */ margin: 1rem 2rem 1.5rem 0; /* 상 우 하 좌 */ } ``` ### 2. 패딩(padding) - 요소 **내부** 여백. - 요소 내용과 테두리 사이의 공간 - 마진 상쇄가 발생하지 않음 - 텍스트 요소의 경우 일반적으로 패딩만 사용하고 마진은 사용하지 않음 ```css .element { padding: 1rem; } ``` ### 3. 높이와 너비(height & width) 이걸 스페이싱에 넣어야 하나 말아야하나 좀 고민이 되긴 했는데, 일단은 화면에서 차지하는 면적이 있으니 여기에 추가해도 괜찮겠다 싶네요.(엄밀히 이야기해서 스페이싱 시스템은 아니지만요) - 요소 자체의 크기 제어 (높이, 너비) - 텍스트 요소의 경우 일반적으로 너비만 제어하고 높이는 콘텐츠에 맞게 자동 조정되도록 둠. - 높이와 너비를 사용할 때는 주로 px, %, em, rem 등의 단위 사용 - 이미지, 비디오 등의 미디어 요소에 대한 크기 제어에도 자주 사용 ```css .container { width: 80%; max-width: 1200px; } ``` 마지막으로 다시 정리해보면 ### 블록 레벨 요소 (div, p, h1-h6 등) - 기본적으로 부모 요소의 전체 너비를 차지 - 자동으로 줄바꿈 발생 - 높이는 내용에 따라 결정됨 ### 인라인 요소 (span, a, strong 등) - 내용물의 크기만큼만 공간 차지 - 줄바꿈 없이 텍스트 흐름을 따라감 - `width`, `height`, `margin-top`, `margin-bottom` 적용 불가 입니다. ### 웹사이트 디깅 - 스페이싱 흥미로운 점은 정말 많은 디자인 시스템 적용 사이트들이 아래의 css 속성을 베이스로 적용하고 있다는 점이었습니다. 즉 이 속성은 모든 요소에 적용되는 기본 스타일이라고 할 수 있겠습니다. ```css { box-sizing: border-box; /* 요소 크기 계산 단순화 */ border: 0 solid; margin: 0; padding: 0; } ``` 제가 자주 방문하거나 참고하는 사이트인 [테일윈드](https://tailwindcss.com/), [애플](http://www.apple.com/), [github](https://github.com/), [토스](https://toss.im/) 등을 둘러보았습니다. 토스의 경우 아직 em이나 rem을 사용하지 않고 px로 스타일을 핸들링 하는 부분이 많았지만, 나머지 사이트들은 em이나 rem을 최대한 적극적으로 사용하고 있었습니다. 역시 외국 문물이 한국에 들어와 정착하기까지는 시간이 좀 걸리나봅니다. ## 실용적인 여백 시스템 구축 여백 시스템은 일관성 있게 설계되어야 합니다. 앱도 그런지 모르겠지만.. 일단 웹은 8의 배수를 기반으로 한 스페이싱 시스템이 많이 사용됩니다. 부트스트랩도 그랬고, 메테리얼도 그랬던 것 같아요. 레퍼런스 찾아보기 귀찮으니 그냥 이렇게 말만 하고 넘어가도록 하겠습니다. 굉장히 많은 상업용 사이트들을 개발자도구로 열어보면 아래와 같은 스타일이 선언되어있으니 참고하시면 좋을 것 같습니다. :root 같은 클래스명은 바꿀 수 있는 것이고, 중요한 건 값과 변수화를 통한 유지보수성 증가입니다. ```css :root { /* 여백 변수 정의 */ --space-xs: 0.25rem; /* 4px */ --space-sm: 0.5rem; /* 8px */ --space-md: 1rem; /* 16px */ --space-lg: 1.5rem; /* 24px */ --space-xl: 2rem; /* 32px */ --space-xxl: 3rem; /* 48px */ } /* 여백 클래스 */ .margin-bottom-md { margin-bottom: var(--space-md); } .padding-sm { padding: var(--space-sm); } ``` `var()`는 변수를 사용하는 모습입니다. (js를 본격적으로 배울 때도 사용하겠지만)css도 변수를 선언하고 사용할 수 있습니다. 며칠간 공부하시면서 느꼈겠지만 엔지니어들은 타이핑을 정말 많이 해야되죠. 이렇게 변수를 선언해서 스타일 시트 내에서 사용하면 여백 값이 변경되어도 한 곳에서만 수정하면 되기 때문에 유지보수가 편리해집니다. 실제로 사용할 땐 이런 느낌이 됩니다. ```html <div class="margin-bottom-md"> <!-- 여백이 적용된 블록 요소 --> </div> <span class="padding-sm"> <!-- 패딩이 적용된 인라인 블록 요소 --> </span> ``` 그런데 이 많은 스페이싱 관련 선언과 정의를 어느세월에 다 외울 수 있겠어요? 라는 생각이 들 수 있습니다. 그럴 때 필요한 게 bootstrap이나 tailwind, meterial 같은 css 프레임워크 및 라이브러리입니다. (디자인 시스템 이라고 퉁쳐 불리곤합니다) 이런 걸 다 미리 정의 해두었기 때문에, 엔지니어들은 그냥 가져다 쓰기만 하면 되니까요. 우리는 지금 공부하느라고 밑바닥부터 차근차근 뭔가를 쓰고있지만 어느정도 익숙해지면 ~~우리 모두 라이브러리의 노예가 ㄷ..~~ ## 반응형 타이포그래피와 여백 화면 크기에 따라 타이포그래피와 여백이 자동으로 조정되도록 설계하는 방법도 필요합니다. ```css :root { /* 모바일 기준 */ font-size: 16px; } @media (min-width: 768px) { :root { /* 태블릿 기준 */ font-size: 17px; } } @media (min-width: 1024px) { :root { /* 데스크탑 기준 */ font-size: 18px; } } ``` 드디어 미디어 쿼리가 등장했습니다. 미디어 쿼리는 뷰포트의 크기에 따라 스타일을 다르게 적용할 수 있게 해주는 기능입니다. 저도 아직 많이는 모르겠습니다. 대충 이런 느낌이구나 하고 넘어가도록 하겠습니다. `FYI`: 뷰포트란 브라우저 화면에 보이는 영역을 말합니다. 스마트폰 시대에 들어서며 많은 기기와 브라우져가 생겼고 *각각의 뷰포트의 크기가 달라 많은 FE들이 매일 눈물을 흘립니다.* ## 피곤해서 더이상 못쓰겠음 갑자기 끝 는 약간 뻥이고 이 정보들을 쭉 탐색하고 공부하면서 결론적으로 중요하게 인지된 내용은 - 모든 디자인은 정보를 표시하는 텍스트 콘텐츠를 기반으로 시작해서 구현(및 디자인)스펙이 확장된다. - 내가 아무런 스타일링을 하지 않아도 가독성 및 시인성을 위해 텍스트 콘텐츠가 노출되는 요소들은 기본적으로 마진이나 패딩을 가진다. (브라우저 만드는 사람들이 글케 만듦) 입니다. 나중에 에너지가 충전되면 계속 써보겠음. 진짜 갑자기 끝!