본문 바로가기

FrontEnd

[번역] 모든 CSS 레이아웃 방법론을 알아보자

반응형

HTML은 구조와 의미를 담당합니다.

CSS는 스타일과 레이아웃을 담당합니다.

그렇다면 CSS는 DOM의 위치를 어떻게 구성할까요?

이 게시물은 CSS의 레이아웃에 대한 모든 것을 다룹니다.

아래 게시물의 번역입니다.

https://www.smashingmagazine.com/2018/05/guide-css-layout/

 

Getting Started With CSS Layout — Smashing Magazine

Whether you’re fairly new to CSS or an experienced developer from elsewhere in the stack who wants to make sure your understanding of layout today is up to date, this guide covers everything you need to know about CSS Layout today.

www.smashingmagazine.com


Normal Flow(일반적인 흐름;Flow Layout)

CSS가 적용되지 않은 HTML 웹 페이지의 요소는 일반적인 흐름을 따라 표시됩니다.
일반적인 흐름에서는 문서의 쓰기 모드에 따라 상자가 차례로 표시됩니다.
즉, 문장이 왼쪽에서 오른쪽으로 또는 오른쪽에서 왼쪽으로 이어지는 가로 쓰기 모드(horizontal writing mode)의 경우,
일반적인 흐름은 블록 수준 요소의 상자를 차례로 페이지 아래에 수직으로 표시합니다.
 
세로 쓰기 모드(vertical writing mode)의 경우 문장이 세로로 작성되므로
일반적인 흐름은 블록을 가로로 배치합니다.
쓰기 모드에 따라 블록 및 인라인의 방향을 변경합니다.

일반적인 흐름은 모든 레이아웃의 시작점 입니다.
즉, 다른 레이아웃을 적용한다는 것은,
문서의 일반적인 흐름에서 해당 요소를 특별하게 취급한다고 생각할 수 있습니다.


일반적인 흐름을 활용하도록 문서 구조화

처음에는 일반적인 흐름에 따라 요소가 배치되도록 문서를 구조화해야 합니다.
일반적인 흐름이 없다면, 이는 페이지에 모든 항목을 우리 스스로 배치해야 함을 의미합니다.
브라우저는 디폴트로 일반적인 흐름을 사용해 콘텐츠를 즉시 읽을 수 있는 방식으로 표시합니다.
 
CSS가 로드되지 않더라도 사용자는 여전히 콘텐츠를 읽을 수 있으며
CSS의 혜택을 전혀 받지 못하는 사용자(예: 스크린 리더를 사용하는 사람)에게는
콘텐츠가 문서에 있는 순서대로 전달됩니다.
이는 접근성 관점에서 HTML 문서가 일반적인 흐름을 따라야 한다는 점을 중요하게 만듭니다.
 
또한, 일반적인 흐름에 따라 요소를 배치하는 것은
웹 개발자로서의 삶을 더 쉽게 만들어 줍니다.
사용자가 읽을 것으로 예상되는 순서대로 콘텐츠를 배치한다면, 레이아웃을 크게 변경할 필요가 없습니다.
여기에 최신 레이아웃 방법을 추가하는 정도만 하면 됩니다.

따라서 레이아웃에 대해 생각하기 전에,
문서의 구조와 콘텐츠가 문서의 위에서 아래로 읽힐 순서에 대해 생각해야 합니다.


일반적인 흐름에서 벗어나기

일반적인 흐름에 따라 잘 구조화된 문서가 있다면
이를 어떻게 원하는 레이아웃으로 바꿀지 결정해야 합니다.
이는 문서의 일부가 일반적인 흐름에서 벗어나도록 하는 것을 의미합니다.
 
이를 위한 여러가지 방법이 있지만,
우리가 살펴볼 첫 번째 방법은 float입니다.
float는 일반적인 흐름에서 요소를 분리하는 것이 무엇인지에 대한 훌륭한 데모입니다.

Floats

float는 상자를 왼쪽이나 오른쪽으로 이동하는 데 사용되며,
콘텐츠가 해당 상자를 둘러싸며 표시하게끔 할 수 있습니다.

 

항목에 float를 적용하려면,
CSS 속성 float에 left 또는 right 값을 사용하세요.

float의 기본값은 none입니다.

<style>
.item {
    float: left;
}
</style>
항목을 띄우고 텍스트가 항목 주위를 감싸면 해당 콘텐츠의 line-box가 짧아진다는 점은 주목할 가치가 있습니다.
항목을 플로팅한 다음,
텍스트가 포함된 다음에 나올 블록에 배경색이 적용된 경우
이 배경색이 플로팅된 항목 아래에 설정되는 것을 볼 수 있습니다.
 
paragraph의 배경색은 Float 아이템 뒤에 설정됩니다.
플로팅된 항목과 line box의 너비가 줄어든 래핑 텍스트 사이 공간을 만들기 위해,
항목 주변에 마진을 설정해 주는 것이 좋습니다.
 
텍스트에 마진을 설정하면 컨테이너 가장자리에서 텍스트를 이동합니다.
따라서, 떠있는 이미지를 컨테이너의 위쪽 및 왼쪽과 일치하도록 유지하면서,
텍스트와 간격을 추가하기 위해 오른쪽과 아래쪽에 여백을 추가합니다.
 

CLEARING FLOATS

요소를 플로팅하면
다음 요소가 플로팅된 요소의 바닥을 둘러싸야만, 이후에 일반적인 흐름이 계속됩니다.
이를 방지하려면 float를 clear 해야 합니다.

float 다음에 올 요소에,

왼쪽에 떠있는 요소의 float를 없애려면 clear:left

오른쪽에 떠있는 요소의 float를 없애려면 clear:right를 적용합니다.

둘다 없애려면 both를 사용합니다.

<style>
.clear {
    clear: both;
}
</style>
 
위의 방법은 float 요소 다음에 나올 요소에 적용해야 합니다.
박스 안에 플로팅된 항목과 그 옆에 텍스트가 있는 상황에 처한 경우 도움이 되지 않습니다.
텍스트가 플로팅된 항목보다 짧으면 상자가 콘텐츠 아래에 그려지고 플로팅된 요소를 무시합니다.
우리가 이미 배운 것처럼 플로트는 line-box를 줄이고 나머지 레이아웃은 일반적인 흐름으로 계속됩니다.
 
예를 들어, 아래와 같이 container에 clear:both를 적용하는 것은 의미가 없습니다.
<div class="container">
  <div class="item"></div>
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra.</p>

</div>

<style>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0 20px 20px 0;
  background-color: rgba(111,41,97,.3);
}

.container {
  clear: both;
}
</style>

텍스트 주변의 상자가 플로트를 클리어하지 않습니다.

즉, 이 상황을 방지하려면 상자 안의 무언가에서 float를 clear 해야 합니다.
 
우리는 빈 요소를 추가하고 모두 지우도록 설정할 수 있습니다.
즉, 빈 div를 문서에 추가하는 방법 등이 있습니다.
이는 이상적이지 않으며, CMS에서 페이지를 생성하는 경우 불가능할 수 있습니다.
 
일반적인 clearing floats 방법은 clear fix hack으로 알려진 것입니다.
이 방법은 CSS를 통해 콘텐츠를 추가하여 clear 하도록 하는 것입니다.
<style>
.container::after {
  content: "";
  display: table;
  clear: both;
}
</style>

블록 서식 맥락(The Block Formatting Context)

상자 내부의 플로트를 지우는 또 다른 방법은 컨테이너에서 BFC(Block Formatting Context)를 호출하는 것입니다.
Block Formatting Context는 그 안에 모든 것을 "포함"합니다.
떠다니는 항목이 더 이상 상자 바닥을 찔러 나갈 수 없다는 것을 의미합니다.
 
BFC를 강제하는 몇 가지 방법이 있습니다.
플로트를 클리어할 때 가장 일반적으로 사용되는 방법은
default 값인 visible 이외의 값을 갖도록 overflow 속성을 설정하는 것입니다.
<style>
.container {
    overflow: auto;
}
</style>
이러한 방식으로 오버플로를 사용하면 일반적으로 잘 동작하지만,
특정 상황에서는 항목의 그림자가 잘리거나 원하지 않는 스크롤 막대가 생길 수 있습니다.
또한 스타일시트를 혼란스럽게 할 수 있습니다.
스크롤 막대를 원해서 오버플로를 설정했나요? 아니면 float를 clear하기 위해 오버플로를 설정했나요?
 
의도를 더 명확하게 하고 원하지 않는 부작용을 일으키는 BFC 생성을 방지하기 위해,
display 속성의 값으로 flow-root를 사용할 수 있습니다.
display: flow-root가 수행하는 유일한 작업은 BFC를 생성하여 다른 문제 없이 플로트를 지우는 것입니다.
<style>
.container {
    display: flow-root;
}
</style>

Float는 레거시를 위해 존재합니다.

해당 속성을 대체하기 위해 grid 레이아웃이 존재합니다.

저는 신규 프로젝트에서 해당 속성을 사용하지 않는 것을 권장합니다.

Float를 더 공부하고 싶다면...

 


포지셔닝(Positioning)

일반적인 흐름에서 요소를 제거하거나 일반 흐름의 위치에서 이동하려면 CSS의 position 속성을 사용할 수 있습니다.
일반적인 흐름에 있을 때 요소는 position:static 입니다.
항목은 블록 차원에서 차례로 표시되며 페이지를 스크롤하면 함께 스크롤됩니다.
 
위치 값을 변경할 때 일반적으로 오프셋 값을 사용하여 특정 기준점에서 상자를 이동합니다.
사용되는 기준점은 position 값에 따라 다릅니다.
 

상대 위치 지정(RELATIVE POSITIONING)

아이템에 position:relative 속성이 있는 경우
기준점은 자기 자신이 일반적인 흐름에 있을 때의 위치입니다.
그 다음 top, left, bottom 및 left 속성에 대한 오프셋 값을 사용하여
자기 자신이 일반적으로 표시되는 위치에서 상자를 이동할 수 있습니다.

<style>
.item {
    position: relative;
    bottom: 50px;
}
</style>

페이지의 다른 항목은 요소의 새 위치에 반응하지 않습니다.
정상적인 흐름에서 배치된 위치는 예약되어 있으므로 
다른 요소와의 겹침을 직접 관리해야 합니다.

절대 위치 지정(ABSOLUTE POSITIONING)

position: absolute를 설정하면 해당 항목은 일반적인 흐름에서 제거됩니다.
즉 원래 일반적인 흐름에 따라 위치할 공간이 제거됩니다.
항목은 다른 위치 지정된(position:static이 아닌) 요소 내에 중첩되지 않았다면
뷰포트일 포함 블록(containing block)을 기준으로 위치가 지정됩니다.

 
따라서 항목에 position:absolute를 설정하면 일반적으로 가장 먼저 발생하는 일은
일반적으로 뷰포트의 상단과 왼쪽에 고정되는 것입니다.
(만약 다른 위치지정 요소에 중첩되지 않았다면)
그 다음 top, left, bottom 및 left 속성에 대한 오프셋 값을 사용하여
해당 위치에서 원하는 위치로 상자를 이동할 수 있습니다.
.item {
    position: absolute;
    top: 20px;
    right: 20px;
}

뷰포트가 아닌 다른 상자를 기준으로 위치하고 싶다면, 해당 요소를 포함하는 다른 블록에 static이 아닌 position 값을 제공합니다.

position: relative를 설정하면 일반적인 흐름에서 항목이 제거되지 않으므로 해당 값을 선호합니다.

오프셋의 기준이 될 부모 요소에 position:relative를 제공하고

움직일 요소에 position:absolute와 오프셋을 제공합니다.

고정 위치 지정(FIXED POSITIONING)

position: fixed 가 있는 항목은 대부분의 경우 뷰포트에 상대적으로 배치되며,
문서 흐름에서 제거되므로 공간을 차지하지 않습니다
페이지가 스크롤되면 일반적인 흐름을 따르는 나머지 콘텐츠가 평소와 같이 스크롤되므로,
고정 요소는 뷰포트에 상대적인 위치에 유지됩니다.
.item {
    position: fixed;
    top: 20px;
    left: 100px;
}
주로 화면에 고정된 네비게이션을 구현하는데 사용합니다.
콘텐츠가 스크롤되는 동안 다른 위치 지정 값과 마찬가지로 겹침이 발생할 수 있으므로
모든 콘텐츠를 읽을 수 있도록 컨텐츠가 fixed된 항목 뒤에 가지 않도록 주의해야 합니다.
뷰포트가 아닌 항목을 기준으로 FIXED된 항목을 상대 배치하려면,
포함 블록(containing block)의 transform, perspective, filter 속성 중 하나의 값이 default(none)가 아니게끔 설정하면 됩니다.
이 경우 해당 요소는 컨테이닝 블록이 되고 오프셋은 뷰포트가 아닌 해당 블록을 기준으로 설정됩니다.
 

끈끈한 위치 지정(STICKY POSITIONING)

(놀랍게도)일반적인 흐름, 끈끈한 위치 지정과 같은 용어는 mdn 공식문서의 한글 번역을 차용한 것입니다
 
position: sticky를 설정하면, 일반적인 흐름에서와 마찬가지로 요소가 문서와 함께 스크롤되지만,
뷰포트의 특정 지점에 도달하면(일반적인 오프셋 사용)"고정"되어 position: fixed처럼 행동합니다.
 
상대적으로 최신 스펙에서 사용할 수 있는 값이며,
위의 다른 위치지정 방법보다 브라우저 지원이 훌륭하지는 않습니다만,
만약 브라우저가 지원하지 않을 경우 일반적인 흐름을 따라 스크롤 되기에 큰 문제가 되지 않습니다.
.item {
    position: sticky;
    top: 0;
}

 

다음은 콘텐츠와 함께 스크롤되는 내비게이션 바의 인기 있는 효과를 흉내낸 예제입니다.
콘텐츠를 스크롤할 시 뷰포트 상단에서 부착되어 화면에 머무르도록 하는 방법입니다.

위치 지정에 대해 더 공부하기


플렉스 레이아웃(Flex Layout)

Flexible Box Layout(Flexbox)은 1차원 레이아웃을 위해 설계된 레이아웃 방법입니다.
1차원은 콘텐츠를 행이나 열로 배치하려는 것을 의미합니다.
컨테이너 내부 요소에 플렉스 레이아웃을 적용하려면 값이 flex인 display 속성을 사용합니다.
.container {
    display: flex;
}​

해당 요소의 직계 자식은 플렉스 항목이 되며
인라인 방향의 시작점 모서리에 정렬된 행으로 배치됩니다.

플렉스 박스의 축

위에서 항목이 왼쪽에 정렬된 것으로 설명하지 않았습니다.
인라인 방향 행의 시작 가장자리에 정렬된 것으로 항목을 배치했다고 설명했습니다.
 
flex-direction 속성의 기본값이 행(row)이기 때문에 우리의 항목은 행에 배치됩니다.
이렇게 하면 문장이 작성되는 방향인 인라인 방향으로 행이 생성됩니다.
왼쪽에서 오른쪽으로 쓰는 언어인 영어로 작업할 때는 행의 시작이 왼쪽에 있으므로 항목이 왼쪽에서 시작합니다.
따라서 flex-direction 값은 Flexbox의 기본 축을 정의합니다.
 
교차축( cross axis)은 주축(main axis)을 직각으로 가로지릅니다.
flex-direction이 row이고 항목이 인라인 방향으로 표시되는 경우, 교차 축은 블록이 쌓이는 방향(열 방향)을 향합니다.
flex-direction이 column이면 항목이 블록이 쌓이는 방향(열 방향)을 향하고, 교차 축은 행 방향을 향합니다.
Flexbox로 작업할 때 주축과 교차축 측면에서 생각하는 데 익숙해지는게 좋습니다.

방향과 순서(DIRECTION AND ORDER)

Flexbox는 row-reverse 또는 column-reverse의 flex-direction 값을 사용하여
기본 축에서 항목의 방향을 변경하는 기능을 제공합니다.

order 속성을 사용하여 개별 플렉스 항목의 순서를 변경할 수도 있습니다.
그러나 문서의 탭 순서가 콘텐츠가 소스에 있는 순서를 따르기 때문에,
마우스나 터치스크린이 아닌 키보드를 사용하여 탐색하는 모든 사용자에게 문제가 발생할 수 있으므로 각별히 주의해야 합니다.
자세한 내용은 시각적 및 문서 순서에 대한 아래 섹션을 참조하세요.

플렉스 속성

플렉스 속성은 기본 축을 따라 플렉스 항목의 비율을 제어하는 ​​방법입니다.
세 가지 속성은 다음과 같습니다.

  • flex-grow
  • flex-shrink
  • flex-basis

이 세가지 속성은 일반적으로 flex 속성을 이용해 약식 형식으로 사용되며,
첫 번째 값은 flex-grow, 두 번째는 flex-shrink, 세 번째는 flex-basis를 의미합니다.

.item {
    flex: 1 1 200px;
}​
flex-basis의 값은 항목이 늘어나거나 줄어들기 전의 크기를 제공합니다.
위의 예에서 해당 크기는 200픽셀이므로 각 항목에 200픽셀의 공간을 제공합니다.
컨테이너가 200픽셀로 깔끔하게 분할될 가능성이 낮으므로
각 항목에 200픽셀이 있는 경우 모든 항목에 대해 남은 공간이 있거나 충분한 공간이 없을 것입니다.
flex-grow 및 flex-shrink 속성을 사용하면 공간이 너무 많거나 부족한 경우 항목에 발생하는 작업을 제어할 수 있습니다.

flex-grow가 양수 값으로 설정되면 항목이 커져 공간을 차지할 수 있습니다.
따라서 위의 예에서 각 항목에 200픽셀을 지정하면 항목 간에 추가 공간이 공유됩니다.

flex-shrink가 양수 값으로 설정되면 모든 항목에 flex-basis가 제공되었을 때, 오버플로가 발생하는 상황에서 항목이 축소될 수 있습니다.
예제에서 컨테이너에 공간이 충분하지 않으면 모든 항목이 컨테이너에 들어갈 때까지 각 항목이 동일한 양만큼 축소됩니다.
flex-grow 및 flex-shrink 값은 양수 값이 될 수 있습니다.
flex-grow 값이 큰 항목은 크기에 비례하여 사용 가능한 공간이 더 많이 제공되고
flex-shrink 값이 큰 항목은 축소 시 더 많이 제거됩니다.
 
 
플렉스 속성이 동작하는 방식을 이해하는 것이 Flexbox를 이해하는 핵심입니다.
하나의 차원에서 컨테이너로 늘리고 찌그러뜨리고 싶은 많은 것들이 있을 때 Flexbox를 사용하는 것을 고려하십시오.
행과 열에 항목을 정렬하려는 경우 Grid가 필요하며 이 경우 Flexbox는 적절하지 않을 수 있습니다. 

플렉스박스 더 공부하기


그리드 레이아웃(Grid Layout)

CSS 그리드 레이아웃은 2차원 레이아웃을 위해 설계되었습니다.
2차원은 콘텐츠를 행과 열로 배치하는 것을 의미합니다.
Flexbox와 마찬가지로 Grid Layout은 display의 값이므로 Grid를 사용하려면 컨테이너에서 display: grid 속성을 적용한 후,
grid-template-columns 및 grid-template-rows 속성을 사용합니다.
.container {
    display: grid;
    grid-template-columns: 200px 200px 200px;
    grid-template-rows: 200px 200px;
}​
위의 CSS는 완전히 고정된 열 및 행 트랙이 있는 고정 크기 그리드를 만듭니다.
이것은 아마도 당신이 원하는 것이 아닐 것입니다.
Grid는 각 행이 같은 비율로 증가할 수 있도록 하는 기능을 제공합니다.
모든 트랙의 기본값은 auto
이 값은 일반적으로 "컨텐츠에 대해 충분히 크다"고 생각할 수 있습니다.
rows 트랙을 생성하지 않은 경우 행이 자동으로 생성되고, 자동으로 크기가 조정됩니다.
일반적인 패턴은 columns 트랙을 지정하고 Grid가 행의 크기를 자동으로 조절하도록 하는 것입니다.
 

길이 단위 또는 백분율을 사용하여 열 및 행 트랙을 설정할 수 있지만
그리드 레이아웃을 위한 새로운 단위인 fr 단위를 사용할 수도 있습니다.
fr 단위는 플렉스 단위이며 그리드 컨테이너에서 사용 가능한 공간의 공유를 나타냅니다.

(flex의 stretch, shrink도 동일하게 사용 가능한 공간의 공유를 의미합니다.)

 

그리드는 가용 공간을 분배할 수 있습니다.

내용물이 컨테이너에 맞는지 확인하기 위해 백분율을 계산할 필요가 없습니다.

아래 예에서는 fr 단위를 사용하여 열을 만들고 트랙이 자동으로 생성되도록 합니다.

우리는 또한 grid-gap을 사용하여 트랙 사이에 간격(gap)을 만들고 있습니다.

Flexbox 및 flex-grow 또는 flex-shrink와 마찬가지로 fr 단위는 사용 가능한 공간을 공유합니다.
한 트랙의 fr 값이 높을수록 비례적으로 사용 가능한 공간이 더 많아집니다.
fr 단위와 절대 길이를 혼합할 수도 있습니다.
길이에 필요한 공간은 fr 단위를 계산하기 전에 사용 가능한 공간에서 뺍니다.

그리드 용어(GRID TERMINOLOGY)

그리드에는 항상 두 개의 축이 있습니다.
인라인 축은 페이지에 단어가 배치되는 방향을 향하고 블록 축은 블록이 배치되는 방향을 향합니다.

  • 그리드 컨테이너(Grid Container)는 display: grid를 설정한 요소입니다.
  • 그리드 라인(grid line)은 grid-template-columns 및 grid-template-rows를 사용하여 지정한 열 및 행 track에 의해 생성된 직선입니다.
  • 그리드 셀(grid cell)은 그리드(4개의 교차하는 그리드 라인 사이)에서 가장 작은 단위를 이라고 합니다.
  • 그리드 트랙(grid track)은 두 라인 사이의 셀들을 의미합니다.
  • 그리드 영역(grid area)은 직사각형 모양을 만드는 한 개 이상의 그리드 셀 집합입니다.
그리드 라인은 그리드의 각 트랙 사이를 연결합니다.
그리드 트랙은 두 라인 사이에 있습니다.
그리드 셀은 그리드에서 가장 작은 단위이며, 그리드 영역은 직사각형 영역을 만드는 하나 이상의 셀입니다.

 

그리드 자동 배치(GRID AUTO-PLACEMENT)

그리드를 생성하는 즉시 그리드 컨테이너의 직계 자식이 그리드의 각 셀에 하나씩 배치되기 시작합니다.
그리드 컨테이너는 그리드 자동 배치 규칙에 따라 이 작업을 수행합니다.
이러한 규칙은 항목이 겹치지 않도록 각 항목이 빈 셀에 배치되도록 합니다.
 
위치를 지정하지 않은 그리드 컨테이너의 직계 자식은 자동 배치 규칙에 따라 배치됩니다.
아래 예에서 세 번째 항목마다 2행 트랙에 걸쳐 있도록 했지만
여전히 start line과 왼쪽 모서리가 평행하게 자동 배치되는 모습을 볼 수 있습니다.
 

기본적인 라인 기반 위치 지정(BASIC LINE-BASED POSITIONING)

그리드에 항목을 배치하는 가장 간단한 방법은,
라인 기반 위치 지정을 사용하여 그리드의 한 라인에서 다른 라인으로 확장되도록 항목 규칙을 지정하는 것입니다.
 
예를 들어, 3개의 열 트랙과 2개의 행 트랙이 있는 그리드가 있는 경우
열 라인 1에서 열 라인 3까지, 행 라인 1에서 행 라인 3까지 항목을 배치할 수 있습니다.
그러면 총 4개의 그리드 셀을 덮게 됩니다.
즉, 두 개의 열 트랙과 두 개의 행 트랙의 교집합을 의미합니다.
.item {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 3;
}

 

이러한 속성은 첫 번째 값이 시작이고 두 번째 값이 끝이 되는 속기 표현으로 나타낼 수 있습니다.
.item {
    grid-column: 1 / 3;
    grid-row: 1 / 3;
}
그리드 항목은 동일한 셀을 차지할 수 있으므로 내용이 겹치는 디자인을 만들 수 있습니다.
항목은 콘텐츠가 웹에 쌓이는 일반적인 방식(문서 구조 상 순서)으로 쌓이며
이는 html 상 아래에 위치한 항목은 다른 항목 위에 나타남을 의미합니다.
그래도 z-index를 사용하여 이를 제어할 수 있습니다.
 

이름 지정 영역을 이용한 위치 지정(POSITIONING WITH NAMED AREAS)

명명된 영역을 사용하여 그리드에 항목을 배치할 수도 있습니다.
이 방법을 사용하려면 각 항목에 이름을 지정한 다음 grid-template-areas 속성 값으로 레이아웃을 설명합니다.

.item1 {
    grid-area: a;
}

.item2 {
    grid-area: b;
}

.item3 {
    grid-area: c;
}

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-areas: 
     "a a b b"
     "a a c c";
}
이 방법을 사용할 때 기억해야 할 몇 가지 규칙이 있습니다.
  • 항목이 여러 셀에 걸쳐 있도록 하려면 이름을 반복해서 적습니다.
  • 영역은 완전한 직사각형을 형성해야 하며 L자형 또는 테트리스 조각은 허용되지 않습니다.
  • 그리드는 완전해야 합니다. 즉, 모든 셀을 채워야 합니다.
    • 공백을 남기려면 해당 셀을 .로 채웁니다.

아래 CSS는 오른쪽 하단 모서리를 비워둡니다.

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-areas: 
     "a a b b"
     "a a c .";
}

이것은 CSS를 보는 사람이라면 누구나 레이아웃이 어떻게 동작하는지 정확히 볼 수 있기 때문에 추천하는 방법입니다.

 

그리드 레이아웃에 대해 더 알아보기

CSS 그리드 레이아웃에는 해당 기사에서 공유한 것보다 훨씬 더 많은 사양이 있으며
아래 리소스는 사양을 배우는 데 도움이 될 것입니다.
컴포넌트와 전체 페이지 레이아웃 모두 그리드가 될 수 있습니다.
2차원 레이아웃이 필요한 경우 크든 작든 관계없이 그리드 레이아웃을 사용하세요.
 

 

시각적 순서와 문서 상 순서(Visual And Document Order)

처음에 위에서 아래로, 즉 읽기 쉬운 순서로 문서를 시작할 것을 추천했습니다.
이는 접근성과 CSS 레이아웃이 동작하는 방식 모두에 도움이 되기 때문입니다.
Flexbox 및 CSS Grid는 해당 순서를 상당히 많이 바꿀 수 있습니다.
이로 인해 문제가 발생할 가능성이 있습니다.
 
브라우저는 문서의 비시각적 사용 방법을 위해 html을 이용합니다.
따라서 화면 판독기가 문서 순서를 읽고 키보드를 사용하여 탐색하는 사람은
시각적 순서가 아닌 소스(html)에 있는 순서대로 문서를 탭합니다.
많은 스크린 리더 사용자는 완전히 맹인이 아니므로,
문서 상 자신의 위치를 ​​볼 수 있는 동시에 스크린 리더를 사용할 수 있습니다.
이 두 경우 모두 소스와 시각적 순서가 뒤죽박죽이면 실제로 매우 혼란스러운 상황을 유발할 수 있습니다.
 
소스에 있는 순서에서 다른 방식으로 요소를 이동할 때 조심하세요.
CSS에서 항목의 순서를 재정렬하는 경우 html 문서를 재구성해야 하나요?
해당 요소에 포커스 할 수 있는지, 포커스 순서와 시각적 순서가 맞는지 테스트하세요.

시각적 순서와 문서 상 순서에 대해 더 알아보기


박스 생성(Box Generation)

웹 페이지에 배치하는 모든 것은 상자를 생성하며,
이 기사의 모든 내용은 CSS를 사용하여 디자인에서 해당 상자를 배치하는 방법을 설명하지만
특정 상황에서는 상자를 전혀 생성하고 싶지 않을 수 있습니다.
상자를 원하지 않는 상황을 처리하는 display 속성에는 두 가지 값이 있습니다.

박스와 컨텐츠 안보여주기(display: none)

하위 항목을 포함하여 해당 요소와 해당 요소의 모든 콘텐츠가 생성되지 않도록 하려면 display: none을 사용할 수 있습니다.
이제 요소가 표시되지 않으며 해당 위치에 공간이 예약되지 않습니다.

.item {
    display: none;
}

하위 요소만 보여주기(display: contents)

display의 새로운 값은 display: contents입니다.
display: contents를 요소에 적용하면 해당 요소에 대한 상자는 생성되지 않지만 자식은 정상적으로 생성됩니다.
이는 간접 하위 요소가 플렉스 또는 그리드 레이아웃의 일부가 되도록 하려는 경우에 유용할 수 있습니다.

아래 예의 첫 번째 플렉스 아이템은 두 개의 중첩된 자식을 포함하고 있지만, display: contents가 설정되어 있어,
해당 아이템의 자식은 컨테이너의 직계 자식처럼 플렉스 항목이 됩니다.
해당 요소에서 display: 콘텐츠를 제거하여 레이아웃이 어떻게 변경되는지 확인하세요

박스 생성에 대해 더 알아보기


정렬 (Alignment)

정렬은 최근까지도 웹에서 까다로운 주제였습니다.
상자 안의 항목을 적절하게 정렬하는 방법이 매우 제한적이었기 때문입니다.
Grid 및 Flex 컨테이너에서 정렬을 제어할 때 사용하는 Box Alignment Module이 있으며,
앞으로는 다른 레이아웃 방법들도 이러한 정렬 속성을 구현할 것으로 기대됩니다.
박스 정렬 사양(Box Alignment specification)에 자세히 설명된 정렬 속성 목록은 다음과 같습니다.
  • justify-content
  • align-content
  • place-content
  • justify-items
  • align-items
  • place-items
  • justify-self
  • align-self
  • place-self
  • row-gap
  • column-gap
  • gap

레이아웃 모델은 기능이 다르기 때문에 사용 중인 레이아웃 모델에 따라 정렬이 약간 다르게 동작합니다.
몇 가지 간단한 Grid 및 Flex 레이아웃에서 정렬이 작동하는 방식을 살펴보겠습니다.

align-itemsjustify-items 속성을 설정하는 것은

모든 그리드 항목에 align-self justify-self 속성을 설정하는 것과 동일합니다

이 속성은 그리드 영역 내부의 항목을 정렬합니다.

align-contentjustify-content 속성은 그리드 컨테이너에 트랙을 표시하는 데 필요한 것보다,  
더 많은 공간이 있는 그리드 트랙정렬합니다.

Flexbox에서 align-itemsalign-self는 교차 축(Cross Axis)의 정렬을 담당하고,
justify-content는 기본 축의 공간 내 분배를 담당합니다

align-content 또한 플렉스박스에서는 교차 축 방향 공간 내 분배를 의미합니다.
아래와 같은 경우, 아이템들이 주축 뱡향이 아니라 교차 중 방향으로 분배되고 있으며,
wrap된 각 줄이 하나의 아이템처럼 취급됩니다.

align-content는 이 각 줄의 분배를 담당합니다.

행과 열 간격(ROW AND COLUMN GAPS)

그리드 레이아웃 사양에는 최근까지 grid-column-gap, grid-row-gap 및 grid-gap 속성이 있었습니다.
이들을 그리드 접두사 속성이라 합니다.
 
이들은 이제 Grid 사양에서 제거되고 Box Alignment 사양에 추가되었습니다.
동시에 그리드 접두사 속성은 column-gap, row-gap 및 gap으로 이름이 변경되었습니다.
브라우저는 접두사 속성을 이름이 변경된 속성의 별칭으로 처리하기에, 기존 소스의 호환을 걱정할 필요는 없습니다.
 
이름 변경은 이러한 속성을 다른 레이아웃 방법에도 적용할 수 있음을 의미합니다.
명백한 후보는 Flexbox입니다.
앞으로는 column-gap 및 row-gap을 사용하여 flex 항목 사이에 공간을 만들 수 있게 될 것입니다.

정렬에 대해 더 알아보기


다중 열 레이아웃 (Multi-Column Layout)

다중 열 레이아웃은 신문에서 볼 수 있는 것과 같은 열 생성을 가능하게 하는 레이아웃 유형입니다.
블록은 열로 분할되며, 사용자는 블록 방향으로 열을 읽고 다음 열의 맨 위부터 다시 읽습니다.
사람들이 읽기 위해 위아래로 스크롤할 필요가 있기 때문에,웹 컨텍스트에서 항상 유용한 것은 아니지만
소량의 콘텐츠를 표시하거나 체크박스 세트 또는 기타 작은 UI 요소를 축소하는 데 유용한 방법이 될 수 있습니다.
다중 열 레이아웃은 높이가 다른 카드 등을 표시하는데 사용할 수 있습니다.

컬럼 너비에 설정하기 (SETTING A COLUMN WIDTH)

최적의 열 너비를 설정하고 해당 너비에서 가능한 한 많은 열을 표시하도록 브라우저에 지시하려면 다음 CSS를 사용합니다.
.container {
    column-width: 300px;
}
이렇게 하면 가능한 한 많은 300픽셀 열이 생성되고 나머지 공간은 열 간에 공유됩니다.
따라서 나머지 공간 없이 너비가 정확하게 300픽셀로 나뉘지 않는 한
각 열은 300픽셀보다 약간 더 넓을 수 있습니다.

열 갯수 설정하기 (SETTING A NUMBER OF COLUMNS)

너비를 설정하는 대신 column-count를 사용하여 열 수를 설정할 수 있습니다.
이 경우 브라우저는 요청한 열 수 사이의 남는 공간을 각 열에 나누어 분배합니다.

.container {
    column-count: 3;
}
 
column-width와 column-count를 모두 추가하면 column-count 속성이 최대값으로 작동합니다.
아래 코드에서 열은 세 개의 열이 될 때까지 추가되며,
이 시점에서 추가 열을 만들 수 있는 위한 충분한 공간이 있더라도
헤당 공간은 세 열에 나누어 배분됩니다. 

GAP 속성과 COLUMN 법칙 (GAPS AND COLUMN RULES)

우리는 개별 열 상자에 마진이나 패딩을 추가할 수 없습니다.
열 간격을 지정하려면 column-gap 속성을 사용하세요.
column-gap을 지정하지 않으면 열이 서로 충돌하는 것을 방지하기 위해 기본적으로 1em으로 설정됩니다.
이것은 기본적으로 0으로 설정되는 다른 레이아웃 방법과 column-gap이 다른 점입니다.
간격을 전혀 원하지 않는 경우 0을 포함하여 간격에 대해 모든 길이 단위를 사용할 수 있습니다.
 
column-rule 속성은 두 열 사이의 rule을 추가하는 기능을 제공합니다.
column-rule-width, column-rule-color 및 column-rule-style의 줄임말이며 border와 동일한 방식으로 작동합니다.
rule은 자체 공간을 차지하지 않습니다.
rule과 내용 사이의 공간을 늘리거나 줄이려면 열 간격을 늘리거나 줄여야 하므로 column-gap 위에 놓입니다.
column-rule: 4px dotted #000;
 

요소가 열 간에 걸치게 하기 (ALLOWING ELEMENTS TO SPAN COLUMNS)

column-span 속성을 사용하여 모든 열에 걸쳐 여러 열 컨테이너 내부의 요소를 확장할 수 있습니다.

h3 {
    column-span: all;
}

column-span가 있는 스패닝 요소가 있으면,
스패닝 요소 위와 아래에만 컬럼이 있는 형태가 됩니다.

column-span: all 또는 column-span: none만 사용할 수 있습니다.
즉, 일부 열에만 걸치도록 할 수 없습니다.

 다중 열 레이아웃에 대해 더 알아보기


분할(Fragmentation)

다중 열 레이아웃은 분할(Fragmentation)의 예입니다.
이 경우 콘텐츠는 열로 나뉩니다.
이는 인쇄 시 콘텐츠가 페이지로 분할되는 방식과 매우 유사합니다.
 
이 프로세스는 Fragmentation 사양에 의해 처리되며
이 사양에는 콘텐츠 분할을 제어하는 ​​데 도움이 되는 속성이 포함되어 있습니다.
 
예를 들어, 여러 열을 사용하여 카드 세트를 배치하고 있지만,
해당 카드가 열 간에 분할되어 표시되게 하고 싶지 않으면,
break-inside 속성에 avoid 값을  사용할 수 있습니다.
브라우저 호환성을 고려하여 page-break-inside 속성을 사용하는 것도 좋습니다.
.card {
    page-break-inside: avoid;
    break-inside: avoid;
}​
heading 바로 뒤에 나오는 컨텐츠가 다른 열에 나오도록 하고 싶지 않다면, 다음 속서을 적용합니다.
.container h2 {
    page-break-after: avoid;
    break-after: avoid;
}
이러한 속성은 인쇄 전용 스타일시트를 준비할 때에도 사용할 수 있고,
멀티 컬럼 레이아웃에서도 사용할 수 있습니다.
아래 예에서는 멀티 컬럼 컨테이너에 세 개의 열로 분할되는 세 개의 단락이 있습니다.
p 요소의 break-inside: avoid  선언은 각 열에 하나의 문단만 나오도록 하는 것을 의미합니다.
(이 떄문에 각 열의 문단 길이가 고르지 않을 수 있더라도)
 

분할(Fragmentation)에 대해 더 알아보기


어떤 레이아웃을 사용해야 할까요?

대부분의 웹 페이지는 이러한 레이아웃 유형을 혼합하여 사용하며
각 사양은 서로 간에 상호 작용하는 방식을 정확하게 정의합니다.
예를 들어 일부 그리드 항목이 Flex 컨테이너이기도 한 그리드 레이아웃이 있을 수 있습니다.
이러한 플렉스 컨테이너 중 일부는 배치된 항목의 컨테이닝 블록이거나 내부에 플로팅된 이미지가 있을 수 있습니다.
사양은 우리가 레이아웃하고 있는 콘텐츠에 가장 적합한 레이아웃 모델을 혼합할 것이라는 기대와 함께 작성되었습니다.
이 게시물의 목적은 특정 효과를 달성하는 가장 좋은 방법이 무엇인지 파악하는 데 도움이 되도록
각 레이아웃 유형이 작동하는 기본 방식에 대한 개요를 제공하는 것입니다.
 
디자인을 만들기 위해 다양한 방법을 시도하는 것을 두려워하지 마세요.
레이아웃 방법의 선택이 생각보다 큰 문제를 일으키는 경우는 거의 없습니다.
좋은 문서 구조로 시작하고 해당 문서 구조의 순서에서 시각적 표현을 분리하지 않도록 주의하기만 하면 됩니다.
이후 대부분은 대상 브라우저에서 예상대로 작동하는지 테스트하는 것입니다.
 
반응형