유연 상자의 정렬을 익히고 나서 나는 한동안 만족했다. 그런데 카드 세 개를 나란히 놓았더니 남는 공간이 오른쪽에 뭉텅 남고, 화면을 줄이자 카드 안 텍스트가 컨테이너를 뚫고 나가 가로 스크롤이 생겼다. 정렬만으로는 풀리지 않는 문제였다. 답은 아이템이 스스로 늘고 주는 신축의 원리에 있었다.
이번 편은 유연 상자의 두 번째 기둥인 신축을 다룬다. 아이템이 남는 공간을 어떻게 나눠 늘어나는지, 공간이 부족할 때 어떻게 줄어드는지, 그리고 그 기준이 되는 기본 크기가 무엇인지를 파고든다. 여기에 초보자를 괴롭히는 넘침 함정과 그 해법까지 함께 정리한다.
1. 유연 아이템의 세 가지 성질
유연 상자 안의 아이템은 세 가지 신축 성질을 가진다. 남는 공간을 얼마나 차지하며 늘어날지, 공간이 부족할 때 얼마나 줄어들지, 그리고 늘고 줄기 전의 기본 크기가 얼마인지다. 이 셋을 각각 조절하는 속성이 있고, 이 셋을 한꺼번에 지정하는 단축 속성도 있다. 신축의 모든 것은 이 세 성질에서 나온다.
첫 번째 성질은 확장이다. 컨테이너에 남는 공간이 있을 때, 이 값이 그 공간을 아이템에게 나눠주는 비율을 정한다. 기본값은 늘어나지 않음이다. 그래서 아이템들이 내용 크기만큼만 차지하고 남는 공간이 그대로 비는 것이다. 내가 카드 오른쪽에 빈 공간이 남던 것도 확장이 꺼져 있었기 때문이다.
두 번째 성질은 수축이다. 컨테이너가 아이템들을 다 담기에 좁을 때, 이 값이 아이템을 얼마나 줄일지를 정한다. 기본값은 줄어듦이 켜진 상태다. 그래서 공간이 부족하면 아이템들이 알아서 조금씩 줄어들며 한 줄에 맞추려 한다. 이 자동 수축이 때로는 도움이 되지만 때로는 문제의 근원이 된다.
세 번째 성질은 기본 크기다. 아이템이 늘거나 줄기 전에 출발점으로 삼는 크기다. 이 값을 자동으로 두면 아이템의 내용이나 지정된 폭을 기준으로 삼고, 구체적인 값을 주면 그 크기에서 출발한다. 확장과 수축은 이 기본 크기를 기준으로 남거나 모자란 공간을 계산해 적용된다.
이 세 성질은 서로 맞물려 동작한다. 기본 크기로 출발한 아이템들이 컨테이너에 다 들어가면 확장이 작동해 남는 공간을 나누고, 넘치면 수축이 작동해 공간을 짜낸다. 나는 이 흐름을 이해하고 나서야 아이템 크기가 왜 그렇게 정해지는지를 예측할 수 있게 되었다.
실무에서는 이 셋을 따로 지정하기보다 단축 속성으로 한 번에 다루는 경우가 많다. 단축 속성은 확장, 수축, 기본 크기를 순서대로 받는다. 나는 이 단축을 즐겨 쓰는데, 세 성질을 한눈에 보며 아이템의 신축을 설계할 수 있기 때문이다. 다음 절에서 자주 쓰는 조합들을 살펴본다.
2. 확장으로 공간 채우기
확장 값을 켜면 아이템이 남는 공간을 차지하며 늘어난다. 여러 아이템에 같은 확장 값을 주면 남는 공간을 똑같이 나눠 갖는다. 그래서 아이템들의 폭이 균등해진다. 내비게이션 메뉴 항목들을 화면 폭에 맞춰 고르게 펼치고 싶을 때, 나는 각 항목에 확장 값을 준다.
확장 값은 비율로 동작한다는 점이 중요하다. 한 아이템에 두 배의 값을 주면 그 아이템이 남는 공간의 두 배를 가져간다. 이 성질로 사이드바는 좁게, 본문은 넓게 같은 비대칭 배치를 만들 수 있다. 나는 본문에 큰 확장 값을, 곁가지에 작은 값을 주어 비율을 조절한다.
가장 흔한 활용은 한 아이템만 늘려 남는 공간을 밀어내는 것이다. 예컨대 툴바에서 왼쪽 요소와 오른쪽 요소 사이에 빈 아이템 하나를 확장시키면, 그 아이템이 공간을 다 차지해 양쪽 요소를 끝으로 밀어낸다. 주축 정렬로도 되지만, 이 방식이 더 유연할 때가 있다.
확장 값을 켤 때 기본 크기를 함께 생각해야 한다. 기본 크기를 0으로 두면 아이템들이 순수하게 확장 비율대로만 공간을 나눠, 내용 길이와 무관하게 폭이 정해진다. 기본 크기를 자동으로 두면 내용 크기를 먼저 확보한 뒤 남는 공간만 비율로 나눈다. 이 미묘한 차이가 결과를 크게 바꾼다.
나는 균등한 폭을 원하면 확장을 켜고 기본 크기를 0으로 두는 조합을 쓴다. 이러면 내용이 길든 짧든 아이템들이 똑같은 폭을 갖는다. 반대로 내용에 따라 폭이 달라지되 남는 공간만 나누길 원하면 기본 크기를 자동으로 둔다. 목적에 맞는 조합을 고르는 것이 신축 설계의 핵심이다.
확장을 잘 쓰면 미디어 쿼리 없이도 반응형에 가까운 배치가 나온다. 화면이 넓어지면 아이템이 함께 늘어나 공간을 채우고, 좁아지면 함께 줄어든다. 나는 간단한 툴바나 메뉴에서 이 자동 신축만으로 충분한 경우가 많아, 불필요한 미디어 쿼리를 줄이는 데 확장을 적극 활용한다.
3. 수축과 넘침의 함정
수축은 기본으로 켜져 있어 공간이 부족하면 아이템이 알아서 줄어든다. 대개는 편리하지만, 이 자동 수축이 예상치 못한 결과를 낳기도 한다. 이미지나 고정 폭 요소가 원치 않게 찌그러지는 경우가 그렇다. 나는 로고 이미지가 좁은 화면에서 뭉개지는 걸 보고 이 수축을 처음 의심했다.
특정 아이템이 줄어들지 않게 하려면 수축을 꺼야 한다. 수축 값을 0으로 주면 그 아이템은 기본 크기를 고집하며 줄어들지 않는다. 아이콘, 로고, 고정 폭 버튼처럼 크기가 지켜져야 하는 요소에 나는 이 설정을 준다. 그러면 다른 아이템들이 대신 줄어들며 공간을 양보한다.
수축과 관련해 초보자를 가장 크게 괴롭히는 함정이 따로 있다. 유연 아이템은 기본적으로 자기 내용보다 작게 줄어들지 않으려는 성질이 있다. 그래서 긴 텍스트나 넓은 콘텐츠가 든 아이템은 아무리 화면을 줄여도 줄어들지 않고 컨테이너를 뚫고 나가 가로 스크롤을 만든다. 이게 그 악명 높은 넘침 문제다.
이 함정의 원인은 아이템의 최소 크기가 자동으로 내용 크기에 맞춰지는 데 있다. 즉 아이템은 자기 안의 가장 긴 내용보다 작아지길 거부한다. 나는 이 사실을 모른 채 왜 아이템이 안 줄어드나 며칠을 헤맸다. 정렬도 수축도 다 켰는데 아이템은 요지부동이었다.
해법은 그 아이템의 최소 크기를 0으로 명시하는 것이다. 이 한 줄을 주면 아이템이 내용보다 작게 줄어들 수 있게 되어, 컨테이너 안에 얌전히 담긴다. 긴 텍스트라면 말줄임이나 줄바꿈과 함께 쓰면 깔끔하다. 나는 유연 아이템이 넘칠 때 반사적으로 이 최소 크기 설정을 떠올린다.
이 넘침 함정은 유연 상자를 쓰는 사람이라면 거의 누구나 한 번은 겪는다. 그래서 나는 긴 콘텐츠가 들어갈 유연 아이템에는 처음부터 최소 크기 설정을 습관처럼 넣는다. 예방하는 편이 나중에 원인을 찾아 헤매는 것보다 훨씬 낫다. 이 작은 습관 하나가 가로 스크롤 사고를 크게 줄여준다.
4. 순서와 개별 정렬
유연 상자는 아이템의 시각적 순서를 문서 순서와 다르게 바꿀 수 있다. 순서 속성에 값을 주면 그 값에 따라 아이템이 재배열된다. 값이 작을수록 앞에 온다. 나는 화면 크기에 따라 특정 요소를 앞뒤로 옮겨야 할 때 이 속성을 쓴다. 마크업을 건드리지 않고 순서만 바꿀 수 있어 편리하다.
다만 이 순서 변경에는 접근성 주의가 따른다. 시각적 순서만 바뀔 뿐 화면 낭독기와 키보드 이동은 여전히 문서 순서를 따른다. 그래서 보이는 순서와 읽히는 순서가 어긋나면 혼란을 준다. 나는 순서 속성을 큰 폭으로 바꾸는 건 피하고, 정말 필요한 미세 조정에만 제한적으로 쓴다.
앞 편에서 본 개별 교차축 정렬도 신축과 함께 쓰면 유용하다. 대부분의 아이템은 늘려서 높이를 맞추되, 특정 아이템 하나만 위나 아래에 붙이는 식이다. 나는 카드 목록에서 배지 하나만 위에 고정하고 싶을 때 이 개별 정렬로 예외를 만든다. 전체 규칙과 개별 예외를 함께 다루는 것이다.
자동 여백을 이용한 배치 기법도 알아두면 좋다. 유연 아이템에 특정 방향 여백을 자동으로 주면, 그 방향의 남는 공간을 여백이 전부 흡수한다. 이 성질로 한 아이템만 끝으로 밀어낼 수 있다. 나는 메뉴에서 마지막 항목 하나만 오른쪽 끝으로 보낼 때 이 자동 여백을 즐겨 쓴다.
이런 개별 조정 속성들은 컨테이너의 전체 규칙을 특정 아이템에서만 덮어쓰는 도구다. 컨테이너가 큰 틀을 정하고, 개별 아이템이 예외를 선언하는 구조다. 나는 이 이층 구조를 이해하고 나서 유연 상자로 훨씬 섬세한 배치를 짤 수 있게 되었다. 규칙과 예외를 나눠 생각하면 복잡한 배치도 정리된다.
결국 신축과 개별 정렬을 함께 다루면 유연 상자의 표현력이 활짝 열린다. 대부분은 균등하게, 일부는 예외적으로. 대부분은 늘리되, 일부는 크기를 지키게. 이런 미세한 제어가 실무의 다양한 요구를 감당한다. 나는 이 조합을 손에 익히고 나서 유연 상자로 못 짜는 한 줄 배치가 거의 없어졌다.
5. 신축을 실무 감각으로 익히기
신축을 실무에서 다룰 때 나는 몇 가지 정형화된 조합을 상비약처럼 쓴다. 첫째, 균등한 폭이 필요하면 아이템에 확장을 켜고 기본 크기를 0으로 둔다. 둘째, 크기를 지켜야 하는 요소에는 수축을 끈다. 셋째, 긴 콘텐츠가 든 아이템에는 최소 크기를 0으로 준다. 이 셋만 알아도 대부분의 상황이 풀린다.
카드 목록을 짤 때 나는 각 카드에 최소 폭을 정해두고 확장과 수축을 함께 켜서, 화면에 맞춰 카드 수가 자연스럽게 조절되게 한다. 여기에 줄바꿈을 허용하면 좁은 화면에서 카드가 다음 줄로 넘어간다. 미디어 쿼리 없이도 카드 그리드에 가까운 배치가 이 조합으로 나온다.
넘침이 의심되면 나는 개발자 도구로 어느 아이템이 컨테이너를 뚫는지부터 확인한다. 대개 긴 텍스트나 큰 이미지가 든 아이템이 범인이다. 그 아이템에 최소 크기 설정을 주고, 필요하면 텍스트에 말줄임을 걸어 마무리한다. 원인을 눈으로 확인하고 손대는 이 순서가 시간을 아껴준다.
확장을 남용하면 아이템이 예상보다 크게 늘어나 어색해질 수 있다. 그래서 나는 최대 폭을 함께 걸어 무한정 늘어나지 않게 제한한다. 신축은 자유롭게 두되 상한과 하한을 정해주는 것이다. 유연함과 통제 사이의 균형을 잡는 것이 신축 설계의 묘미다.
신축은 정렬과 함께 유연 상자의 두 기둥이다. 정렬이 아이템의 위치를 정한다면, 신축은 아이템의 크기를 정한다. 이 둘을 함께 다뤄야 유연 상자를 온전히 쓰는 것이다. 나는 배치를 짤 때 정렬로 큰 그림을, 신축으로 크기의 유연함을 잡는 두 단계를 늘 함께 밟는다.
정리하면 유연 아이템은 확장, 수축, 기본 크기의 세 성질로 신축한다. 확장으로 공간을 채우고, 수축을 제어해 크기를 지키며, 넘칠 땐 최소 크기를 0으로 풀어준다. 개별 정렬과 자동 여백까지 더하면 표현력이 완성된다. 다음 편에서는 한 방향을 넘어 행과 열을 동시에 다루는 격자, 그리드로 넘어간다.