CSS: 피할 수 없는 나쁜 부분들

1 hour ago 2
  • 웹페이지 스타일링은 단순한 블로그나 GUI에는 배울 수 있는 작은 하위 집합으로 충분하지만, 브라우저 기본값과 레이아웃 같은 함정이 며칠짜리 디버깅으로 이어질 수 있음
  • 의미 있는 HTML5 태그를 먼저 쓰고 래퍼를 줄이면, CSS가 기존 마크업에 맞춰 작동하도록 만들기 쉬워짐
  • CSS 레이아웃에는 보편적인 단일 알고리듬이 없으며, 각 시스템이 허용하는 배치 방식을 이해하는 접근이 필요함
  • box-sizing, margin, font-size, line-height, word-break는 직관과 다르게 작동해 작은 변경이 전체 배치나 가독성 문제로 번질 수 있음
  • 단순한 페이지에는 CSS reset, classless CSS, flexbox, 과도하지 않은 반응형 규칙이 실용적인 출발점이 될 수 있음

CSS 학습의 범위와 기본 관점

  • CSS, HTML, Web API는 매우 방대해 전문성이 필요하지만, 프로그래밍 블로그나 단순 GUI 같은 작업에는 현대 웹의 적당한 하위 집합으로 충분함
  • 단순 작업에 필요한 하위 집합만 가르치는 자료는 보지 못했지만, MDN을 따라가며 어느 정도 파악할 수 있음
  • 문제는 존재를 예상하지 못한 함정이 페이지를 망가뜨리고, 원인을 찾는 데 며칠이 걸릴 수 있음
  • 이 사이트의 스타일링은 약 200줄의 읽을 수 있는 CSS로 구성됨

좋은 부분: 의미 있는 HTML과 classless CSS

  • HTML5 의미 태그

    • MDN의 Elements Reference를 훑어볼 가치가 있으며, HTML 요소 수가 아주 많지는 않음
    • main, article, nav, kbd 같은 태그는 페이지 구조를 더 쉽게 만들 수 있음
    • ul은 header > nav 안의 사이트 섹션처럼 모든 종류의 목록에 쓸 수 있음
    • details는 목차에 쓸 수 있으며, MDN 소스를 확인할 수 있음
    • dl과 dt는 쌍으로 된 목록에 사용할 수 있음
  • 래퍼를 줄이는 접근

    • 실제 웹사이트의 소스를 보면 여러 겹의 래퍼 요소가 많아 레이아웃 문제를 래퍼로 푸는 방식처럼 보일 수 있음
    • 프로덕션 CSS 경험에 대한 판단은 유보되지만, 의미 있는 시맨틱 태그만 쓰도록 제한한 뒤 그 마크업에 맞는 CSS를 찾는 방식이 더 이해하기 쉬웠음
  • Classless CSS

    • 스타일을 완전히 중립적인 “아무것도 없음” 상태로 초기화할 수는 없으며, 흰색이나 투명 텍스트도 여전히 스타일임
    • 초기화 뒤에는 공통 HTML 요소를 직접 스타일링하는 방식이 가능함
    • main, header, footer, nav 태그를 쓰면 CSS 선택자를 많이 쓰지 않고도 전체 페이지 레이아웃을 설정할 수 있음
    • 이 방식은 CSS가 HTML 구조를 가정하게 만들지만, 자신의 HTML과 CSS라면 결과가 마음에 들지 않을 때 바꿀 수 있음

나쁜 부분: 레이아웃, 브라우저 기본값, 선택자

  • 레이아웃

    • 레이아웃 문제는 웹만의 문제가 아니며, 여러 GUI 프레임워크에서 어려운 문제임
    • 고정 크기 래스터 이미지와 이를 설명하는 텍스트 문단을 화면 사각형에 배치하는 방식은 여러 가지임
    • 일반적인 GUI는 많은 “레이아웃 자유도”를 가진 박스들의 계층 구조임
    • 각 박스의 레이아웃은 다른 모든 박스의 레이아웃에 영향을 주며, 보통 간격과 겹침 없이 모든 박스가 정확히 맞닿아야 함
    • 보편적인 단일 레이아웃 알고리듬은 없으며, RectCut부터 constraint solvers, 그 중간 영역까지 시스템마다 다른 휴리스틱을 사용함
    • “주어진 시스템에서 레이아웃을 어떻게 만들까”보다 “그 시스템이 허용하는 레이아웃은 무엇인가”를 생각하는 편이 나음
  • 브라우저 기본값과 CSS reset

    • CSS가 없는 의미 있는 HTML도 브라우저에서는 색, 글꼴, 크기, 큰 제목, 밑줄 링크 등 기본 스타일이 적용됨
    • 기본 스타일은 도움이 되지만 브라우저마다 다르며, 작성하지 않은 기본값에 의존하면 다른 브라우저에서 다른 결과가 보일 수 있음
    • 일반적인 해결책은 CSS reset 또는 정규화로, CSS 시작 부분에서 명시적인 규칙으로 기본값을 덮어쓰는 방식임
    • 기본값 자체가 나쁜 것이 아니라 서로 일관되지 않은 것이 문제임
    • 실제로 어떤 규칙을 덮어써야 하는지는 여러 기존 CSS reset을 비교하는 편이 좋음
  • 웹페이지를 스타일링해야 하는가

    • 웹 플랫폼에는 유연하고 적응적인 시각 매체로 보는 관점과, 콘텐츠 전달에 집중하고 사용자가 표현을 커스터마이즈해야 한다는 관점이 함께 존재함
    • 기본적으로 스타일이 없는 페이지는 사용성이 낮고 보기 좋지 않음
    • CSS 없는 페이지가 그대로 읽기 쉬운 세계가 더 낫겠지만, 현재 환경에서는 콘텐츠에 스타일을 적용하는 일이 도움이 됨
    • 고급 사용자가 자신의 CSS를 가져올 수 있도록 허용하는 것이 좋음
    • HTML 마크업은 합리적이어야 하고, HTML을 CSS에 과적합하지 않아야 하며, 페이지가 reader mode에서 작동해야 함
  • CSS 선택자

    • 기본 CSS는 강력한 상속처럼 작동하며, 웹페이지의 각 디자인 요소가 여러 규칙의 영향을 받음
    • CSS 파일에 덧붙이는 방식으로 기존 요소를 언제든 “monkey patch”할 수 있음
    • CSS 선택자가 잘못된 축으로 추상화 능력을 더한다고 보고, classless CSS와 inline style을 쓰는 접근이 가능함
    • Tailwind 같은 도구로 inline 작성의 불편함을 줄이고, JSX나 조합을 지원하는 템플릿 엔진으로 HTML 반복을 줄일 수 있음
    • CSS nesting을 사용하면 멀리 뻗는 선택자를 줄이고 컴포넌트 단위로 스타일링할 수 있음

박스 모델과 배치: box-sizing, margin, 기본 flow, flexbox

  • box-sizing

    • UI는 재귀적인 사각형이며, 레이아웃은 각 사각형이 어디에 놓이는지 정하는 과정임
    • HTML 기본값에서 요소의 width와 height는 border와 padding을 포함하지 않아 직관적이지 않음
    • 어느 한 곳의 padding을 늘리면 처음에는 완벽해 보이던 전체 레이아웃이 예기치 않게 밀릴 수 있음
    • * { box-sizing: border-box; }는 CSS reset의 첫 줄이 될 만하며, border 추가를 지역적인 변경으로 만들 수 있음
  • margin collapsing

    • 어떤 요소 주변에 8px 간격을 원한다고 해서 padding을 쓰면, 인접한 두 요소 사이 간격이 16px가 될 수 있음
    • margin은 두 이웃 margin을 합산이 아니라 max로 결합하는 방식으로 작동함
    • margin collapsing은 매우 유용하지만 놀라운 동작을 만들 수 있음
    • 자식 margin이 부모 밖으로 튀어나올 수 있다고 보지만, margin에 대한 직관적 이해는 충분하지 않음
    • Julia Evans의 글 Moving away from Tailwind, and learning to structure my CSS는 일반적으로 요소 자체에 margin을 주기보다 부모가 자식 사이 margin을 제어하는 owl selector 방식을 다룸
    • section의 첫 번째 자식을 제외한 모든 자식에 margin을 추가하는 방식은 margin 문제를 줄이는 아이디어로 이해됨
    • 이런 지식은 전문 웹 개발자가 되거나 다른 CSS 프레임워크를 역공학하지 않으면 배우기 어렵다는 점이 불편함
  • 기본 flow 레이아웃

    • 기본 레이아웃 알고리듬은 문서 언어로서의 HTML 기원과 관련이 있으며, 텍스트와 그림 중심의 종이 문서 생성 사례에 맞춰진 것으로 보임
    • 본문 텍스트에는 기본 flow가 실제로 원하는 동작에 가깝게 작동함
    • 페이지 요소의 공간 배치를 직접 제어하려면 기본 flow와 다른 방식이 필요함
  • flexbox

    • flexbox는 일련의 요소를 세로 또는 가로로 배치하고, 사용 가능한 공간에 맞춰 적응시키는 레이아웃임
    • 과거에는 “이것은 왼쪽, 이것은 오른쪽” 같은 배치에도 깊은 CSS 지식이나 불투명한 CSS 프레임워크가 필요했음
    • flexbox는 꽤 복잡해 MDN을 계속 참고해야 하지만, 대체로 원하는 작업을 끝낼 수 있음
  • 반응형 디자인

    • 현대 CSS는 화면 크기를 질의하고 사용자 에이전트 제약에 따라 조건부 로직을 구현할 수 있음
    • HTML은 본질적으로 반응형이며, PostScript나 PDF와 달리 창 크기가 바뀌면 문단을 자동으로 다시 흐르게 함
    • 명시적인 반응형 규칙을 피하고 레이아웃이 합리적으로 동작하도록 맡기는 것이 좋음
    • 이 블로그는 명시적인 @media 쿼리 없이 모바일, 태블릿, 데스크톱에서 괜찮게 보임
    • 본문 텍스트의 메인 컬럼에 max-width를 무조건 설정하는 것만으로 충분함

크기와 텍스트: 픽셀, 글꼴, 줄 높이, 줄바꿈

  • 픽셀

    • 1px는 원하는 일을 하지만, 화면의 물리적 픽셀 하나라는 뜻은 아님
    • CSS의 1px는 시각각의 단위이며, 어떤 화면에서도 지각적으로 비슷하게 보이도록 설계됨
    • 화면 크기, 픽셀 밀도, 일반적인 시청 거리에 따라 서로 다른 수의 물리적 픽셀로 변환됨
    • 따라서 서로 다른 디스플레이의 픽셀 밀도를 따로 생각하지 않고도 모든 크기를 픽셀로 지정할 수 있음
    • CSS의 센티미터와 인치 같은 “실제” 단위도 픽셀을 기준으로 정의되므로 각도처럼 작동함
  • font-size

    • font-size: 16px에서 16px는 특정 글리프 크기가 아니라 글리프 주변의 가상 박스 크기임
    • 이 박스는 글리프에 딱 맞지 않으며, 실제 글리프 크기는 글꼴에 따라 달라짐
    • font-size-adjust는 글꼴 간 font-size를 더 일관되게 만들 수 있음
    • 현재 font-size-adjust는 매우 틈새 기능처럼 보이며, 개인적으로는 box-sizing 옆에 font-size-adjust: ex-height 0.53;을 두고 싶지만 그렇게 하는 페이지는 적음
    • font-size 기본값은 브라우저 사이에서 비교적 일관되며, 16px가 압도적인 기본값임
    • 글꼴에 따라 16px가 작게 보일 수 있고, 일부 기본 글꼴은 특히 작음
    • Apple에서 font-family: serif는 sans-serif보다 훨씬 작게 보이며, 16px에서는 거의 읽기 불편함
    • CSS에서 font-size를 설정하면 브라우저의 기본 글꼴 크기 변경 방식을 비활성화함
    • 텍스트가 기본적으로 읽기 쉬울 것이라고 가정하지 말고 다른 설정에서 확인해야 함
    • font-size-adjust로 자유도를 줄이고 font-size의 의미를 고정한 뒤, 16px 기본 글꼴 크기에서 괜찮으면 완료됨
    • 그렇지 않으면 font-size를 더 큰 숫자로 설정하고, 이후 reader mode에서도 읽기 쉬운지 확인해야 함
  • line-height

    • 이름과 달리 line-height는 한 줄의 높이를 설정하지 않음
    • line-height는 같은 글꼴로 설정된 글리프 묶음의 높이임
    • 모든 텍스트가 같은 글꼴일 때는 줄 높이와 글리프 묶음 높이가 일치함
    • 일부 단어가 monospace 글꼴로 설정되면 예상과 다른 결과가 생길 수 있음
    • font-size-adjust는 박스 안의 글리프 크기를 고치지만, 상대적 위치까지 지정하지는 않음
    • 서로 다른 글꼴의 텍스트 묶음이 baseline을 공유하도록 수직 정렬되면, 각자의 line-height line-box가 서로 어긋남
    • 전체 줄 높이는 합집합처럼 구성되어 예상보다 커질 수 있음
    • 이 효과는 Deep dive CSS: font metrics, line-height and vertical-align에서 자세히 다룸
  • vertical rhythm

    • vertical rhythm은 제목, 이미지 등이 있어도 문단 사이의 줄 위치가 같은 상대 위치에 오도록 맞추는 아이디어임
    • 웹페이지 뒤에 보이지 않는 줄노트가 있는 것처럼 맞추는 방식으로 설명됨
    • 단일 컬럼 레이아웃에서는 유용하지 않은 것으로 판단됨
    • 2컬럼 레이아웃에서는 양쪽 줄을 맞추고 싶을 수 있음
    • 단일 컬럼에서 이를 위해 복잡한 노력을 들이는 것은 말이 되지 않음
  • word-break

    • flow 레이아웃의 장점은 창이 좁아질 때 텍스트가 줄로 깔끔하게 나뉘는 동적 동작임
    • 줄은 공백이나 하이픈 삽입 지점에서만 끊을 수 있음
    • inline code나 URL 같은 긴 구간은 끊기지 않을 수 있음
    • 이 문제는 모바일 기기에서 가로 오버플로를 일으키며, 보통 게시 후에야 알아차리게 됨
    • 이를 고치는 단일 비법은 없지만, Against Horizontal Scroll에 몇 가지 팁이 있음

실용적인 결론

  • 단순한 블로그를 만들기 위해서는 HTML과 CSS의 충분한 부분만 짧게 설명하는 자료가 필요함
  • margin collapsing 같은 문제에 무너지지 않고 단순 블로그를 만들 정도의 HTML과 CSS를 설명하는 100쪽짜리 짧은 책에 대한 요청으로 마무리됨
Read Entire Article