[CSS] 12. grid



12. grid

grid 개요

  • flex 박스가 main axis만 가능했다면, grid는 main + cross
  • 이차원 배열
  • 컨테이너를 가지고 행과 열을 만든 다음에 내부를 꾸미는 방식
  • rows : 행
  • columns : 열
  • gutters (gao) : 행과 열 사이에 공백
  • 레이아웃을 하기 위해 table 보다 grid 사용하기


Container - display

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
</div>

.container {
    border: 5px solid red;
    display: inline-grid;
    grid-template-colums: 1fr 1fr 1fr

    width: 150px;

}

.item {
    border: 3px solid;
}
  • 외부 레이아웃 + 내부 레이아웃 가능
  • inline-grid
  • grid : 외부 컨테이너를 만들고 행과 열을 만든 후 형제 Item 들을 하나 하나 넣는 것


Container - grid-template-rows, grid-template-columns

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
</div>

.container {
    border: 5px solid red;
    display: inline-grid;

    // 3열을 만드는데 100px 150px 150px
    grid-template-columns: 100px 150px 100px;
    grid-template-rows: 100px 100px;

    // 1 : 1 : 1로 전체 width를 사이좋게 나눠가지고 싶다면
    grid-template-rows: 1fr 1fr 1fr
    grid-template-colums: 2fr 1fr // 2 : 1

    grid-template-rows: 80px 80px 80px 80px;
    // 이걸 함수 표기하면?
    grid-template-rows: repeat(4, 80px);

}

.item {
    border: 3px solid;
}
  • container 에 사용하는 속성
  • 행과 열의 차이, 사용법은 동일


Container - grid-template-areas

<div class="container">
    <div class="item header">1</div>
    <div class="item main">2</div>
    <div class="item sidebar">3</div>
    <div class="item footer">4</div>
</div>

.container {
    border: 5px solid red;
    width: 400px;
    height: 400px;

    display: grid;
    grid-template-colums: repeat(5, 1fr);
    grid-template-rows: repeat(3, 1fr);
    // 칸은 15개 인데 아이템은 4 개다

    grid-tempalte-areas:
        "hd hd hd hd hd"
        "ma ma ma . sb"
        "ft ft ft ft ft";
    // . 은 빈 공간



    width: 150px;

}

.item {
    border: 3px solid;
}

.header {
    grid-area: hd;
}

.main {
    grid-area: ma;
}

.sidebar {
    grid-area: sb;
}

.footer {
    grid-area: ft;
}

  • item 들이 한칸에 한개가 아니라 여러칸에 한개가 들어가도록 하는 것
  • 각각의 덩어리가 네모 형태여야 한다.(ㄱ,ㄴ,ㄷ 같은 모양 안된다)


Container - row-gap, column-gap, gap

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
</div>

.container {
    border: 5px solid red;
    display: grid;

    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(4, 1fr);

    row-gap: 20px;
    column-gap: 50px;
    // 둘이 합치면?
    gap: 20px 50px;
    // 앞이 무조건 row 뒤가 column 이어야 한다

}

.item {
    border: 3px solid;
}
  • 행간의 간격, 열간의 간격
  • gutter 의 너비를 결정하는 것


Container - grid-auto-rows, grid-auto-columns

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
    <div class="item">10</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: 100px 150px 80px;
    grid-template-rows: repeat(3, 1fr);
    // 칸은 9개인데 아이템은 10개

    grid-auto-rows: 100px;
    // 넘쳐나는 애들의 행을 100px로 한다.
    grid-auto-colums: 50px;
    // 암시적으로 지정한다
    // 아이템이 없으면 눈에 보이지 않는다.

}

.item {
    border: 3px solid;
}
  • grid 는 내부에 item 이 있건 없건 내부에 명시적으로 공간을 만들어 놓는다.
  • 공간은 9개인데 10번째 아이템이 있다면?
  • 그것의 크기를 지정하는게 grid-auto-rows(colums)


Container - grid-auto-flow

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);

    // 1 2 3
    // 4 5 6

    grid-auto-flow: column;
    // 행축으로 방향축을 잡는다.

    // 1 4
    // 2 5
    // 3 6

    grid-auto-flow: row dense;
    // 중간에 크기가 커서 빈영역이 생긴다면 뒤에 아이들이 그 빈영역으로 올라온다.
    // 위의 빈 영역이 채워진다
    // 1 . .
    // 2~~~~~~
    // 3 4 5 일때

    // 1 3 4
    // 2~~~~~
    // 5
}

.item {
    border: 3px solid;
}

.item:nth-child(2) {
    grid-column: span 2;
}
  • item들이 어떻게 흘러갈 것인지를 결정하는 것
  • 자리 잡는 방법의 흐름
  • row, column, row dense, column dense
  • row : default


Container - grid (shorthand)

grid: 행(row) / 열(column)

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: 100px 200px;
    grid-template-rows: 1fr 2fr

    // shorthand
    grid: 1fr 2fr / 100px 200px;

    grid-auto-flow: row | column;

    // row
    grid: auto-flow 1fr 2fr / 100px 200px;
    // column
    grid: 1fr 2fr / auto-flow dense 100px 200px;

}

.item {
    border: 3px solid;
}

  • 컨테이너 속성의 단축어
  • 처음에는 각각의 속성을 직접 쓰는 것을 추천
  • 익숙해지면 단축어 사용하기
  • 외재적인 속성 (명시적) : grid-template-rows, grid-template-columns, grid-template-areas
  • 내용물이 있건 없건 눈에 보인다.
  • 내재적인 속성 (암시적) : grid-auto-rows, grid-auto-columns, grid-auto-flow
  • 아이템이 있어야만 눈에 보인다.


Container - justify-content, align-content

grid: 행(row) / 열(column)

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
</div>

.container {
    border: 5px solid red;
    width: 100%;
    height: 500px;
    display: grid;
    grid-template-colums: repeat(3, 100px);
    grid-template-rows: repeat(3, 100px);

    // 메인축을 기준으로
    justify-content: start; //default
    justify-content: end;
    justify-content: center;
    justify-content: space-around; // 좌우 공백 동일
    justify-content: space-between; // 양 끝 제외 하고 여백 동일

    // 교차축을 기준으로
    align-content: start;
    align-content: end;
    align-content: center;
    align-content: space-around; // 좌우 공백 동일
    align-content: space-between; // 양 끝 제외 하고 여백 동일

}

.item {
    border: 3px solid;
}

  • 전체 컨테이너를 기준으로 아이템들을 어떻게 배치하느냐
  • flex 와 동일하다
  • 조건 : 컨테이너의 크기가 내부 아이템의 크기보다 커서 빈공간이 남아야한다.


Container - justify-items, align-items

grid: 행(row) / 열(column)

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
</div>

.container {
    border: 5px solid red;
    width: 100%;
    height: 500px;
    display: grid;
    grid-template-colums: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);

    justify-items: stretch; //default
    justify-items: start | end | center 
    align-items: stretch | start | end | center

    // 메인축을 기준으로
    
}

.item {
    border: 3px solid;
}

.item:;nth-child(1) {
    width: 50px;
    height: 50px;
    // 실제 한 칸보다 매우 작아진다.
    // 왼쪽위에 작게 위치한다.
}

.item:nth-child(1) {
    justify-self: end;
    각각의 아이템에게 줄 때는 self
}

  • 하나의 아이템에 대한 이야기
  • justify-items는 전체 레이아웃에서 내부 뭉텅이를 어찌 넣느냐
  • justify-items 는 한 칸에 대한 정렬
  • 큰 틀의 크기랑은 상관이 없다.


Item - grid-row, grid-column

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: repeat(3, 1fr);
    grid-template-rows: repeat(3, 100px);


}

.item {
    border: 3px solid;
}

.item:nth-child(1) {
    background-color: red;
    // start,end의 숫자는 선 기준이다. 3칸일때 위에서부터 1, 2, 3, 4
    // 명시적 속성일 경우는 (grid-template-*)
    // -4, -3, -2, -1로도 가능
    grid-row-start: 1;
    grid-row-end: 4; // -1 도 된다.
    // 1 . .
    // 1 . .
    // 1 . .

    // shorthand
    grid-row: 1 / -2;
    grid-column: 1 / 3;
    
    //시작하는 곳부터 몇칸 차지했으면 좋겠을 땐?
    grid-row: 2 / span 2;
    // 시작하는 위치부터 2칸 차지햇으면 좋겠어
}
  • grid-row-start + grid-row-end 의 shorthand


Item - grid-area

// 하나라면
// grid-template-areas 지명 목적
grid-area: a;

// shorthand
grid-area: 2 / 1 / 2 / 4;

// grid-row + grid-column
grid-row: 4 / span 2;
grid-column: 2 / -1;

grid-area : 4 / 2 / span 2 / -1;
// 순서 주의하기
  • 1 : grid-template-areas 에서 아이템 알려주기 위한 지명 목적
  • 2 : grid-row-start, grid-column-start, grid-row-end, grid-column-end => shorthand


Item - order

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);


.item {
    border: 3px solid;
}

.item:;nth-child(5) {
    order: -1;
    // 다른 것들이 기본값이 0 이기 때문에 가장 앞으로 온다
    // 5 1 2 3 4
}

.item:nth-child(3) {
    order: -1;
    // -1 중 순서가 더 빠른 3번이 가장 앞으로 온다
    // 3 5 1 2 3
    // 마크업에서는 원래 순서와 같다 
    // 1 2 3 4 5
}

  • 초기값 : 0


Item - z-index

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    grid-template-colums: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);


.item {
    border: 3px solid;
}

.item:;nth-child(1) {
   grid-row: 1 / span 2;
   grid-column: 1 / span 2;
   z-index: 5;
   // 1이 위로 올라온다.
}

.item:nth-child(2) {
   grid-row: 1 / 2
   grid-column: 2 / 4;
   // 둘이 겹쳐진다
   // 마크업상 뒤에 있는 2가 위로 온다.
   z-index: 3;
}


grid 단위 - fr, min-content, max-content

  • fr (fraction) : 유동적으로 width의 길이를 비율에 따라 나눌 때
  • 절대 비율과 사용 가능 100px 1fr 1fr : 100px 의 남은 공간을 나눠 갖는다.
  • 이 경우 절대 길이가 우선적으로 지정된다.
  • grid-template-columns: min-content 1fr 1fr;
  • min-content : content의 내용 중 가장 짧은 단어에 맞는 크기로 줄어든다.
  • max-content : 이 content를 한 줄에 볼 수 있는 길이까지 길어진다.
  • 둘 다 내용에 따라 유동적으로 변경된다.


grid 단위 - auto-fill, auto-fit

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
</div>

.container {
    border: 5px solid red;
    display: grid;
    // 이 두가지를 모두 쓰면 여백 없이 반응형에 맞게 할 수 있다.
    grid-template-colums: repeat(auto-fill, minmax(100px, 1fr));
    grid-template-rows: repeat(auto-fit), 1fr);


.item {
    border: 3px solid;
}


  • 반응형때 사용
  • auto-fill: width 가 늘어나면 빈공간이 생기는 것이 아닌 남는 공간에 칼럼 갯수를 증가시키는 것
  • minmax(min, max) : 가장 작을 때 값과 가장 클 때 값을 지정
  • auto-fit: auto-fill을 사용할 때 width 가 매우 증가하면 거기 대응할 칼럼이 없다면 빈공간이 생기게 된다.
  • 하지만 auto-fit은 내부 아이템 크기가 증가하여 여백을 만들지 않는다.
  • 남는 공간이 생길 때 공간이 생기지 않는다는 것이 좋다.


나의 회고 🤫

드디어 레이아웃 끝판왕 grid를 배웠다.
알고있는 속성도 있었고 처음보는 속성도 있었다.
이제부터는 레이아웃을 잡을 때 grid, flex를 상황에 맞게 적절하게 사용하여 더 이쁜 레이아웃을 만들 수 있어졌다.
html, css 를 다시 공부하며 얕게 여러번 공부하는 것 보다 깊에 한번 제대로 공부하는 것이 더 얻는 것이 많음을 다시 한번 깨달았다.
오늘로 끝이 아닌 TIL보며 자주 복습하자! 😳👍