본문 바로가기

Grid 레이아웃

행과 열의 트랙·간격·영역을 정의하고 아이템 위치와 정렬을 제어해 반응형 2차원 페이지를 구성합니다.

지난 장에서 우리는 Flexbox를 사용해 1차원(한 줄 또는 한 열) 방향으로 아이템을 유연하게 배치하고 정렬하는 방법을 학습했습니다.

Flexbox는 내비게이션 바나 카드 목록처럼 한 방향으로 흐르는 콘텐츠를 다룰 때 매우 강력한 도구입니다.

하지만 웹 페이지는 종종 여러 행과 열로 구성된 복잡한 2차원 레이아웃을 필요로 합니다.

예를 들어, 신문 기사처럼 여러 열로 나뉜 텍스트, 복잡한 대시보드, 갤러리 페이지 등이 그렇습니다.

이러한 2차원 레이아웃 요구를 해결하기 위해 나온 것이 CSS Grid Layout입니다.

Grid는 이름 그대로 격자(Grid) 형태의 레이아웃을 만들 수 있도록 설계된 CSS3 레이아웃 모듈입니다.

부모 요소에 그리드 구조를 정의하고, 그 안의 자식 요소를 특정 그리드 셀에 배치함으로써 전체 페이지의 큰 틀이나 복잡한 그리드 UI를 쉽고 효율적으로 구현할 수 있습니다.

이 장에서는 Grid의 기본 개념과 주요 속성을 상세하게 학습하고, 실습을 통해 Grid의 강력함을 직접 경험해 볼 것입니다.

Flexbox와 Grid는 서로 보완 관계에 있으므로, 두 기술을 모두 능숙하게 다루는 것은 현대 웹 개발자에게 필수 역량입니다.

Grid 트랙·라인·영역과 자동 배치 모델

GRID COORDINATES

트랙은 공간이고, 라인은 그 공간의 경계입니다

네 개의 동일한 열 트랙은 다섯 경계 라인을 만듭니다. 영역을 지정한 항목과 자동 배치되는 A/B의 좌표를 비교합니다. 아래 그림은 본문의 3열 실습과 구별되는 4열 좌표 설명용 예입니다.

같은 네 열·다섯 라인의 Grid 배치네 열의 경계선은 1부터5다. header는 열1/5, sidebar는 열1/2·행2/5, main은 열2/4·행2/5다. row 자동 배치 A는 열4/5·행2/3, B는 열4/5·행3/4이며 오른쪽 아래 칸은 빈다. 모바일 보조는 같은 sidebar의 이름이며 좌표와 트랙 수가 달라진 것이 아니다. 1122334455headersidebarmainABheader: column 1/5 · sidebar: column 1/2, row 2/5main: column 2/4, row 2/5 · auto A/B: column 4/5
같은 네 열·다섯 라인의 Grid 배치네 열의 경계선은 1부터5다. header는 열1/5, sidebar는 열1/2·행2/5, main은 열2/4·행2/5다. row 자동 배치 A는 열4/5·행2/3, B는 열4/5·행3/4이며 오른쪽 아래 칸은 빈다. 모바일 보조는 같은 sidebar의 이름이며 좌표와 트랙 수가 달라진 것이 아니다.1122334455header보조mainAB보조 = sidebar열 1/2 · 행 2/5A: 열 4/5 · 행 2/3B: 열 4/5 · 행 3/4

4개 트랙 → 5개 라인

grid-template-columns: repeat(4, minmax(0, 1fr)); header의 1 / 5는 네 열 전체를 사용합니다. span은 라인 개수가 아니라 차지하는 트랙 수입니다.

  • 명시 line 배치
  • span·named area
  • auto-placement

line은 track의 경계이고 item은 line 번호 사이에 놓인다. 이 예시는 gap: 0, grid-auto-flow: row, 모든 order: 0이며 header·sidebar·main의 두 축을 지정합니다. A/B는 남은 4열의 2행·3행에 순서대로 배치됩니다. 일부 축만 지정된 item도 나머지 축의 자동 배치에 관여할 수 있습니다.


Grid의 기본 개념

Flexbox와 마찬가지로 Grid도 부모-자식 관계를 기반으로 작동합니다.

Grid 레이아웃을 적용하려는 영역을 Grid 컨테이너(Grid Container)로 만들고, 그 안에 있는 직계 자식 요소들이 Grid 아이템(Grid Item)이 됩니다.

  • Grid 컨테이너: display: grid 또는 display: inline-grid 속성이 적용된 부모 요소입니다. 컨테이너에 적용하는 속성들은 그리드의 전체적인 구조(행과 열)와 아이템들의 배치를 결정합니다.
  • Grid 아이템: Grid 컨테이너의 직계 자식 요소들입니다. 아이템에 직접 적용하는 속성들은 해당 아이템이 그리드 내에서 차지할 영역을 지정합니다.
  • Grid Line (그리드 라인): 그리드 트랙의 경계입니다. 한 축에 명시적으로 N개 트랙을 정의하면 그 축의 명시 라인은 N+1개입니다. 아래 예처럼 양의 번호는 1부터 읽습니다. 자동 배치로 추가되는 암시 트랙은 별도입니다.
  • Grid Track (그리드 트랙): 그리드 라인 사이에 형성되는 공간으로, 행(Row)과 열(Column)을 의미합니다. 트랙의 크기는 grid-template-columns와 grid-template-rows로 정의합니다.
  • Grid Cell (그리드 셀): 하나의 행 트랙과 하나의 열 트랙이 교차하는 가장 작은 단위입니다.
  • Grid Area (그리드 영역): 여러 개의 그리드 셀을 아우르는 사각형 영역입니다.

Grid 컨테이너 속성

Grid 컨테이너에 적용하는 속성들은 그리드의 행과 열을 정의하고, 그 안에 있는 아이템들의 전체적인 배치와 정렬에 영향을 미칩니다.

display로 Grid 컨테이너 선언

  • display: grid;: 컨테이너를 블록 레벨 Grid 컨테이너로 만듭니다. (가장 일반적인 사용)
  • display: inline-grid;: 컨테이너를 인라인 레벨 Grid 컨테이너로 만듭니다.

grid-template-columns

그리드의 열(Column) 트랙의 크기와 개수를 정의합니다.

공백으로 구분하여 각 열의 너비를 지정합니다.

  • 단위: px, %, em, rem, vw, vh 등 다양한 CSS 단위 사용 가능.
  • fr (Fraction): 사용 가능한 공간에 대한 비율을 나타내는 단위. 남은 공간을 유연하게 나눌 때 매우 유용합니다. (예: 1fr 2fr 1fr은 남은 공간을 1:2:1 비율로 나눔)
  • repeat() 함수: 동일한 크기의 트랙을 반복할 때 사용합니다. repeat(반복 횟수, 트랙 크기). (예: repeat(3, 1fr)은 1fr 1fr 1fr과 동일)
  • minmax() 함수: 트랙의 최소 및 최대 크기를 지정합니다. minmax(최소 크기, 최대 크기). (예: minmax(100px, 1fr)은 최소 100px, 최대 남은 공간을 차지)
  • auto: 콘텐츠의 크기에 맞춰 자동으로 조절되거나, 남은 공간을 균등하게 분배합니다.
.container {
    display: grid;
    /* 3개의 열: 첫 번째 200px, 두 번째 남은 공간의 2배, 세 번째 남은 공간의 1배 */
    grid-template-columns: 200px 2fr 1fr;
    /* 4개의 동일한 열 (각각 남은 공간의 1/4) */
    grid-template-columns: repeat(4, 1fr);
    /* 최소 150px, 최대 남은 공간을 차지하는 열들을 자동으로 생성 */
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); /* 반응형 그리드에 자주 사용 */
}

grid-template-rows

그리드의 행(Row) 트랙의 크기와 개수를 정의합니다.

grid-template-columns와 동일한 방식으로 단위를 사용합니다.

.container {
    display: grid;
    /* 3개의 행: 첫 번째 100px, 두 번째 콘텐츠 크기만큼, 세 번째 남은 공간의 1배 */
    grid-template-rows: 100px auto 1fr;
}

grid-gap / gap

그리드 트랙(행과 열) 사이의 간격을 설정합니다.

  • grid-column-gap (or column-gap): 열 트랙 사이의 간격
  • grid-row-gap (or row-gap): 행 트랙 사이의 간격
  • grid-gap (or gap): 행과 열 간격을 동시에 설정하는 단축 속성입니다.
    • gap: 20px; (행과 열 모두 20px 간격)
    • gap: 10px 20px; (행 간격 10px, 열 간격 20px)
.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: auto auto;
    gap: 20px; /* 모든 그리드 셀 사이 20px 간격 */
}

justify-items

그리드 셀(Cell) 내부에서 아이템을 인라인 축으로 정렬합니다. 이 예제의 기본 가로 쓰기에서는 가로 방향입니다.

  • stretch: 해당 축의 크기가 auto인 아이템을 셀에 맞춰 늘립니다. 초기값 normal은 일반적인 auto 크기 아이템에서 stretch처럼 동작하지만, 고유 크기나 종횡비가 있는 아이템은 다르게 정렬될 수 있습니다.
  • start: 셀의 시작 지점으로 정렬.
  • end: 셀의 끝 지점으로 정렬.
  • center: 셀의 중앙으로 정렬.
.container {
    display: grid;
    grid-template-columns: repeat(3, 150px); /* 각 열의 너비를 150px로 고정 */
    justify-items: center; /* 각 셀 내부의 아이템들을 가로 중앙 정렬 */
}

align-items

그리드 셀(Cell) 내부에서 아이템을 블록 축으로 정렬합니다. 위의 가로 쓰기 예제에서는 세로 방향입니다.

  • stretch: 해당 축의 크기가 auto인 아이템을 셀에 맞춰 늘립니다. 초기값 normal의 동작 조건은 앞의 justify-items 설명과 같습니다.
  • start: 셀의 시작 지점으로 정렬.
  • end: 셀의 끝 지점으로 정렬.
  • center: 셀의 중앙으로 정렬.
.container {
    display: grid;
    grid-template-rows: repeat(2, 100px); /* 각 행의 높이를 100px로 고정 */
    align-items: center; /* 각 셀 내부의 아이템들을 세로 중앙 정렬 */
}

justify-content

컨테이너 내에서 그리드 전체를 인라인 축(이 예제에서는 가로) 방향으로 정렬합니다.

그리드 총 너비가 컨테이너 너비보다 작을 때 유효합니다.

  • Flexbox의 justify-content와 유사하게 작동합니다. (start, end, center, space-between, space-around, space-evenly)
.container {
    display: grid;
    grid-template-columns: 100px 100px 100px; /* 그리드 총 너비: 300px */
    width: 500px; /* 컨테이너 너비: 500px */
    justify-content: center; /* 300px 그리드를 500px 컨테이너의 중앙에 배치 */
}

align-content

컨테이너 내에서 그리드 전체를 블록 축(이 예제에서는 세로) 방향으로 정렬합니다.

그리드 총 높이가 컨테이너 높이보다 작을 때 유효합니다.

  • Flexbox의 align-content와 유사하게 작동합니다. (start, end, center, space-between, space-around, space-evenly)
.container {
    display: grid;
    grid-template-rows: 50px 50px; /* 그리드 총 높이: 100px */
    height: 300px; /* 컨테이너 높이: 300px */
    align-content: center; /* 100px 그리드를 300px 컨테이너의 중앙에 배치 */
}

앞의 Grid 다이어그램은 트랙을 만든 뒤 라인·영역, 자동 배치, 반응형 크기를 결정하는 순서를 보여줍니다.


Grid 아이템 속성

Grid 아이템에 적용하는 속성들은 해당 아이템이 그리드 내에서 어떤 위치와 크기를 차지할지 지정합니다. 앞 .container의 grid-template-columns 세 줄은 독립 예를 한 블록에 모은 것이므로 그대로 실행하면 마지막 유효 선언인 auto-fit만 적용됩니다. 고정 열과 repeat(4, 1fr)를 관찰할 때는 비교할 한 선언만 남기세요.

grid-column-start, grid-column-end

아이템이 시작하고 끝날 열 라인(Column Line)을 지정합니다.

  • grid-column-start: N; (N번째 세로 라인에서 시작)
  • grid-column-end: N; (N번째 세로 라인에서 끝남)
  • span N: 현재 라인에서 N개의 트랙을 차지. (예: span 2는 두 칸을 차지)

grid-row-start, grid-row-end

아이템이 시작하고 끝날 행 라인(Row Line)을 지정합니다.

grid-column과 동일한 방식으로 작동합니다.

단축 속성 grid-column / grid-row

  • grid-column: [start-line] / [end-line];
  • grid-row: [start-line] / [end-line];
.item-a {
    grid-column: 1 / 3; /* 첫 번째 세로 라인에서 시작하여 세 번째 세로 라인에서 끝남 (2칸 차지) */
    grid-row: 1 / 2; /* 첫 번째 가로 라인에서 시작하여 두 번째 가로 라인에서 끝남 (1칸 차지) */
}
.item-b {
    grid-column: span 2; /* 두 칸 너비를 차지 */
    grid-row: span 3; /* 세 칸 높이를 차지 */
}

grid-area

그리드 컨테이너에서 grid-template-areas로 정의된 영역 이름을 사용하여 아이템을 배치합니다.

훨씬 직관적이고 가독성이 높은 방법입니다.

  • 컨테이너에 영역 정의
    .container {
        display: grid;
        grid-template-columns: 1fr 2fr 1fr;
        grid-template-rows: auto 1fr auto;
        grid-template-areas:
            "header header header" /* 첫 번째 행: 모두 header 영역 */
            "nav    main   aside"  /* 두 번째 행: nav, main, aside */
            "footer footer footer"; /* 세 번째 행: 모두 footer 영역 */
    }
  • 아이템에 영역 지정
    header { grid-area: header; }
    nav { grid-area: nav; }
    main { grid-area: main; }
    aside { grid-area: aside; }
    footer { grid-area: footer; }
    💡 장점: 레이아웃 구조가 CSS 코드에서 시각적으로 명확하게 드러납니다.

justify-self

개별 Grid 아이템을 자신이 속한 셀의 인라인 축(이 예제에서는 가로)으로 정렬합니다.

컨테이너의 justify-items보다 우선합니다.

  • start, end, center, stretch

align-self

개별 Grid 아이템을 자신이 속한 셀의 블록 축(이 예제에서는 세로)으로 정렬합니다.

컨테이너의 align-items보다 우선합니다.

  • start, end, center, stretch

실습: Grid를 활용한 반응형 웹 페이지

지금까지 배운 Grid 속성들을 활용하여 실제 웹 페이지의 전체적인 레이아웃을 만들어 봅시다.

헤더, 내비게이션, 메인 콘텐츠, 사이드바, 푸터가 있는 전형적인 구조를 Grid로 구현하고 반응형 웹도 고려합니다.

프로젝트 폴더 구조
grid_layout.html
grid.css
grid_layout.html 파일 작성
grid_layout.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Grid 레이아웃 실습</title>
    <link rel="stylesheet" href="css/grid.css">
</head>
<body>
    <div class="grid-container">
        <header class="header">
            <h1>내 Grid 웹사이트</h1>
            <p>CSS Grid로 만드는 멋진 레이아웃</p>
        </header>

        <nav class="navbar">
            <ul>
                <li><a href="#">홈</a></li>
                <li><a href="#">제품</a></li>
                <li><a href="#">소개</a></li>
                <li><a href="#">문의</a></li>
            </ul>
        </nav>

        <main class="main-content">
            <h2>환영합니다!</h2>
            <p>이곳은 CSS Grid Layout을 이용해 만들어진 반응형 웹 페이지입니다. Grid는 2차원 레이아웃에 특화되어 복잡한 웹 페이지 구조를 효율적으로 설계할 수 있게 해줍니다.</p>
            <div class="image-gallery">

            </div>
            <h3>Grid의 장점</h3>
            <ul>
                <li>복잡한 2차원 레이아웃 설계 용이</li>
                <li>아이템들의 위치와 크기 정교하게 제어</li>
                <li>반응형 디자인에 강력</li>
            </ul>
        </main>

        <aside class="sidebar">
            <h3>관련 정보</h3>
            <p>Grid Layout은 Flexbox와 함께 현대 웹 개발의 필수 기술입니다.</p>
            <button>자세히 보기</button>
        </aside>

        <footer class="footer">
            <p>&copy; 2025 Grid Layout 학습. 모든 권리 보유.</p>
        </footer>
    </div>
</body>
</html>
css/grid.css 파일 작성
css/grid.css
/* 기본 스타일 및 박스 사이징 */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f0f2f5;
    color: #333;
    line-height: 1.6;
}

/* Grid 컨테이너 설정 */
.grid-container {
    display: grid; /* Grid 활성화 */
    gap: 20px; /* 그리드 셀 사이의 간격 */
    min-height: 100vh; /* 최소 높이를 뷰포트 높이로 설정 */
    max-width: 1200px; /* 최대 너비 제한 */
    margin: 0 auto; /* 중앙 정렬 */

    /* 그리드 영역 이름 정의 및 배치 */
    grid-template-areas:
        "header  header  header"
        "navbar  main    sidebar"
        "footer  footer  footer";

    /* 각 열의 너비 정의 */
    grid-template-columns: 200px 1fr 250px; /* nav 200px, main 가변, sidebar 250px */
    /* 각 행의 높이 정의 */
    grid-template-rows: auto 1fr auto; /* header, footer는 콘텐츠만큼, main은 남은 공간 모두 */
}

/* 그리드 아이템 기본 스타일 */
.grid-container > * {
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

/* Grid 아이템을 정의된 영역에 배치 */
.header {
    grid-area: header;
    background-color: #2c3e50;
    color: white;
    text-align: center;
    padding: 30px;
}

.header h1 {
    font-size: 2.8em;
    margin-bottom: 10px;
}

.navbar {
    grid-area: navbar;
    background-color: #34495e;
    color: white;
}
.navbar ul {
    list-style: none;
    padding: 0;
}
.navbar li {
    margin-bottom: 10px;
}
.navbar a {
    display: block; /* 링크 영역 확장 */
    color: white;
    text-decoration: none;
    padding: 10px;
    border-radius: 5px;
    transition: background-color 0.3s ease;
}
.navbar a:hover {
    background-color: #4a6581;
}

.main-content {
    grid-area: main;
}
.main-content h2 {
    color: #2980b9;
    margin-bottom: 15px;
    border-bottom: 2px solid #2980b9;
    padding-bottom: 5px;
}
.main-content h3 {
    color: #4a6581;
    margin-top: 25px;
    margin-bottom: 10px;
}
.main-content ul {
    list-style-type: disc;
    margin-left: 20px;
}
.main-content li {
    margin-bottom: 5px;
}

/* 이미지 갤러리 (Grid in Grid - Flexbox와 함께 사용) */
.image-gallery {
    display: grid; /* 갤러리 내부를 다시 그리드로 */
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); /* 최소 180px, 가변 열 */
    gap: 15px;
    margin: 20px 0;
    padding: 15px;
    background-color: #f9f9f9;
    border-radius: 5px;
}
.image-gallery img {
    width: 100%;
    height: 150px;
    object-fit: cover; /* 비율 유지하며 채우기 */
    border-radius: 5px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.sidebar {
    grid-area: sidebar;
    background-color: #ecf0f1;
}
.sidebar h3 {
    color: #2c3e50;
    margin-bottom: 15px;
}
.sidebar button {
    background-color: #28a745;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-top: 15px;
    transition: background-color 0.3s ease;
}
.sidebar button:hover {
    background-color: #218838;
}

.footer {
    grid-area: footer;
    background-color: #34495e;
    color: white;
    text-align: center;
    padding: 20px;
    font-size: 0.9em;
}

/* 반응형 디자인: 화면 너비 768px 이하 */
@media (max-width: 768px) {
    .grid-container {
        /* 모바일에서는 모든 영역을 하나의 열에 세로로 쌓음 */
        grid-template-areas:
            "header"
            "navbar"
            "main"
            "sidebar"
            "footer";
        grid-template-columns: 1fr; /* 하나의 열만 사용 */
        grid-template-rows: auto auto 1fr auto auto; /* 각 영역 높이 조정 */
        gap: 15px; /* 간격도 조금 줄임 */
    }

    .header, .navbar, .main-content, .sidebar, .footer {
        padding: 15px; /* 패딩도 줄임 */
    }

    .navbar ul {
        display: flex; /* 네비게이션 메뉴를 플렉스박스로 가로 정렬 */
        flex-wrap: wrap; /* 공간 부족 시 줄바꿈 */
        justify-content: center;
        gap: 10px;
    }
    .navbar li {
        margin-bottom: 0;
    }
    .navbar a {
        padding: 8px 12px;
        font-size: 0.9em;
    }

    .image-gallery {
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); /* 모바일 이미지 갤러리 조정 */
        gap: 10px;
    }
}
결과 확인
  • Live Server를 통해 grid_layout.html 파일을 열어 보세요.
  • 웹 페이지의 헤더, 내비게이션, 메인 콘텐츠, 사이드바, 푸터가 명확한 격자 형태로 배치된 것을 확인할 수 있습니다. grid-template-areas를 통해 코드에서 레이아웃 구조가 시각적으로 어떻게 보이는지 주목하세요.
  • 브라우저 창의 너비를 조절하세요. 768px 이하에서 다섯 영역이 한 열로 쌓입니다. HTML의 .image-gallery는 비어 있으므로 이미지가 저절로 생기지는 않으며, 사진을 추가해야 내부 Grid의 열 변화를 관찰할 수 있습니다. 현재 사이드바 버튼도 업무 동작 없이 표시만 합니다.

이번 장에서는 2차원 레이아웃을 위한 강력한 CSS 모듈인 CSS Grid Layout에 대해 학습했습니다.

Grid 컨테이너에 행과 열 트랙을 정의하고(grid-template-columns, grid-template-rows), 트랙 사이의 간격을 설정하며(gap), 아이템들을 라인 기반(grid-column, grid-row) 또는 영역 이름 기반(grid-area, grid-template-areas)으로 배치하는 방법을 배웠습니다.

또한, 그리드 셀 내부에서 아이템을 정렬하고(justify-items, align-items), 그리드 전체를 정렬하는(justify-content, align-content) 방법도 익혔습니다.

Flexbox가 1차원 배열에 강점을 가진다면, Grid는 행과 열을 함께 다루는 2차원 레이아웃에 적합합니다.

이 두 기술은 현대 웹 개발에서 거의 모든 레이아웃 문제를 해결할 수 있는 핵심 도구입니다.

이로써 3장 CSS 기초와 레이아웃의 모든 내용을 마쳤습니다.

3장에서는 HTML 구조에 CSS를 적용하고, Flexbox와 Grid로 반응형 레이아웃을 설계하는 기본 흐름을 정리했습니다.

CSS Grid로 페이지 영역을 설계할 때는 명시 트랙과 자동 배치, 반응형 크기를 함께 고려합니다.

라인과 트랙을 실제 값으로 계산하기

가로쓰기 컨테이너의 콘텐츠 폭이 650px이고 grid-template-columns: 200px 2fr 1fr, column-gap: 20px라고 가정합니다. 콘텐츠 최소 크기에 따른 추가 제한은 없고 세 열만 사용합니다. 각 열 폭, 열 라인 수, grid-column: 1 / 3이 차지하는 트랙 수를 구하세요.

남는 공간과 경계 확인

열 사이 두 gap은 40px이고 고정 열은 200px이므로 fr로 나눌 공간은 650−40−200=410px입니다. 둘째 열은 410×2/3≈273.33px, 셋째는 410×1/3≈136.67px입니다. 세 트랙에는 네 라인이 있으며 1 / 3은 두 트랙과 그 사이 gap을 덮습니다. 두 라인 번호의 차이로 트랙 수를 읽으며 “3번째 열까지”로 읽지 않습니다.

독립 변경

실습에서 데스크톱 nav를 오른쪽에 놓으려면 HTML을 옮기기 전에 두 번째 영역 행을 "sidebar main navbar"로 바꾸어 보세요. 해당 영역의 실제 폭도 의도대로 바꾸려면 열 선언을 250px 1fr 200px로 맞춥니다. 모바일의 한 열 영역 선언은 그대로 두고 768px·769px에서 대조하세요. 시각 배치가 바뀌어도 기본 읽기·포커스 순서는 HTML에서 시작하므로, 의미상 순서까지 바꿔야 하는지는 별도로 판단합니다.