๐ 07. CSS Grid: '2์ฐจ์ ๋ ์ด์์์ ์ค๊ณ์'
๐ ๊ฐ์
Flexbox๊ฐ ํด๊ฒฐํ์ง ๋ชปํ๋ ๋ณต์กํ ๋งค๊ฑฐ์ง ์คํ์ผ ๋ ์ด์์์ ๋จ ๋ช ์ค๋ก ์ค๊ณํ๋ CSS Grid์ ๊ฐ๋ ฅํ ํ์ ์์ฒ ์ด์ ํจ๊ป ๊ฒฝํํด ๋ด ๋๋ค.
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 12๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 6๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
[ํ๊ณผ ์ด์ ์ ์] โ [grid-template-areas์ ์๊ฐํ] โ [fr ๋จ์์ ๋ฐ์ํ auto-fit]
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- ํ์ด์ง ์ ์ฒด์ ๊ณจ๊ฒฉ(๋์๋ณด๋, ๋ด์ค ๋ ์ด์์ ๋ฑ)์ Grid๋ก ์ค๊ณํฉ๋๋ค.
-
grid-template-areas๋ฅผ ์ฌ์ฉํด ์ฝ๋๋ง ๋ณด๊ณ ๋ ๋ ์ด์์์ ๋จธ๋ฆฟ์์ ๊ทธ๋ฆฝ๋๋ค. - ๋ฏธ๋์ด ์ฟผ๋ฆฌ ์์ด๋ ํ๋ฉด ํญ์ ๋ฐ๋ผ ์์ดํ ๊ฐ์๊ฐ ๋ณํ๋ ๋ง๋ฒ์ ๋ถ๋ฆฝ๋๋ค.
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ๐ฃ ์์ฒ ( ์ ์ ): "์ํธ ๋! ์ด๋ฒ ์ฌ์ดํธ ๋ฉ์ธ ํ์ด์ง๊ฐ ๊ฑฐ์ ์ก์ง์ฒ๋ผ ๋ณต์กํด์. ํค๋ ๋ฐ์ ์ผ์ชฝ ์ฌ์ด๋๋ฐ, ์ค๊ฐ ๋ณธ๋ฌธ, ์ค๋ฅธ์ชฝ ๊ด๊ณ ... ์ด๊ฑฐ ๋ค Flexbox๋ก ์ค์ฒฉํด์ ๋ง๋ค๋ ค๋๊น ์ฝ๋๊ฐ ์คํ๊ฒํฐ์ฒ๋ผ ๊ผฌ์ด๊ณ ์์ด์! ๐"
- ๐ฆ ์ํธ ( ๋ฆฌ๋ ): "์์ฒ ๋, Flexbox๋ 'ํ ์ค์ฉ' ์ ๋ ฌํ๋ ๋ฐ๋ ์ต๊ณ ์ง๋ง, ์ด๋ฐ '๋ฉด(2์ฐจ์)' ์ ์ฒด๋ฅผ ์ค๊ณํ ๋๋ ํ๊ณ๊ฐ ์์ฃ . ์ด์ ํ์ ์ง๋ ์ค๊ณ์, CSS Grid๊ฐ ๋ฑํํ ์ฐจ๋ก์ ๋๋ค."
๐ค ์ ์์์ผ ํ๋๊ฐ
Flexbox๊ฐ '์ ๋ ฌ' ์ ์ํ ๊ฒ์ด๋ผ๋ฉด, Grid๋ '๊ตฌ์กฐ' ๋ฅผ ์ํ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ด๋ฉด์ ๋ณด๋ ๋๋ถ๋ถ์ ๋ณต์กํ ์น ์๋น์ค(๋ค์ด๋ฒ, ์ ํ๋ธ, ๋์๋ณด๋ ๊ด๋ฆฌ์ ํ์ด์ง ๋ฑ)๋ Grid๋ฅผ ํตํด ๊ทธ ๋ผ๋๋ฅผ ์ก์ต๋๋ค.
์ ์
๊ฐ๋ฐ์๋ค์ด ๊ฐ์ฅ ์ด๋ ค์ํ๋ ๊ฒ์ด "์ด ๋ ์ด์์์ ์ํด div๋ฅผ ์ผ๋ง๋ ๋ ๊ฐ์ธ์ผ ํ์ง?"๋ผ๋ ๊ณ ๋ฏผ์
๋๋ค. Grid๋ฅผ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ๋ํผ(Wrapper) ํ๊ทธ ์์ด๋ ์์ฃผ ๊ฐ๋จํ๊ฒ ์์ญ์ ๋๋ ์ ์์ต๋๋ค. 5๋
์ฐจ ์ด์์ ์๋์ด๋ Grid๋ฅผ ํตํด HTML ๊ตฌ์กฐ๋ ๊น๋ํ๊ฒ ์ ์งํ๋ฉด์๋ ํ๋ คํ ๋ฐฐ์น๋ฅผ ์์ ์์ฌ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
๐๏ธ 1. ํ ์ง๊ธฐ: Container์ Track
Grid๋ ๋ถ๋ชจ(Container)์์ ํ(Rows)๊ณผ ์ด(Columns)์ ๋ฏธ๋ฆฌ ์ ์ํ๊ณ ์์ํฉ๋๋ค.
.container {
display: grid;
grid-template-columns: 200px 1fr 1fr; /* 200px ๊ณ ์ , ๋๋จธ์ง๋ 1:1 ๋น์จ */
grid-template-rows: auto 1fr auto; /* Header, Body, Footer */
gap: 15px;
}fr(Fraction): '๋ถ์'๋ผ๋ ๋ป์ผ๋ก, ๋จ๋ ๊ณต๊ฐ์ ๋น์จ๋ก ๋๋ ๊ฐ๋ Grid ์ ์ฉ ๋จ์์ ๋๋ค. (Flex-grow์ ๋น์ทํ์ฃ !)
๐ fr ๋จ์์ ๊ณต๊ฐ ๋ฐฐ๋ถ (grid-template-columns: 200px 1fr 1fr)
* ๋ธ๋ผ์ฐ์ ์ฐฝ ํฌ๊ธฐ๋ฅผ ๋ฐ๊ฟ๋ณด๋ฉด 200px ์ด์ ๊ณ ์ , ๋๋จธ์ง 1fr ์ด๋ค์ด ๋จ์ ๊ณต๊ฐ์ 1:1๋ก ๋๋ ๊ฐ์ต๋๋ค.
๐จ 2. ๋ง๋ฒ์ ์ฃผ๋ฌธ: grid-template-areas
์ด ์์ฑ์ CSS Grid์ ๊ฝ์ ๋๋ค. ๋ ์ด์์์ ํ ์คํธ๋ก **'๊ทธ๋ฆผ'**์ ๊ทธ๋ฆฌ๋ฏ ์ ์ํ ์ ์์ต๋๋ค.
/* ๐ฆ ์ํธ: ์ด๋ ๊ฒ ์ฐ๋ฉด ๋๋ฃ ๊ฐ๋ฐ์๊ฐ ๋์ค์ ๋ด๋ ๋ฐ๋ก ์ดํดํฉ๋๋ค. */
.layout {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
}
.header { grid-area: header; }
.main { grid-area: main; }
/* ... ๋๋จธ์ง ์ฐ๊ฒฐ */๐ฃ ์์ฒ : "์... ์ด๊ฑฐ ์ง์ง ๋๋ฐ์ธ๋ฐ์? ์ฝ๋๊ฐ ๊ทธ๋ฅ ๋๋ฉด ๊ทธ ์์ฒด์์!"
๐จ grid-template-areas: ์ฝ๋๊ฐ ๊ณง ๋๋ฉด
๐ฑ 3. ๋ฏธ๋์ด ์ฟผ๋ฆฌ ์๋ ๋ฐ์ํ: auto-fit & minmax
Grid์ ์ง์ง ๊ฐ๋ ฅํ ์ ์ ํ๋ฉด ํญ์ ๋ฐ๋ผ ์์ดํ ๊ฐ์๋ฅผ ์์์ ์กฐ์ ํ๋ ์ง๋ฅ์ ๋๋ค.
/* ๐ฆ ์์ ๋ฆฌ๋: ๋ฏธ๋์ด ์ฟผ๋ฆฌ 10์ค ์งค ๊ฑฐ ํ ์ค๋ก ๋๋ด๋ ๋น๊ธฐ์
๋๋ค. */
.item-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}- ์๋ฏธ: "์ต์ 250px์ ๋ณด์ฅํ๋, ์๋ฆฌ ๋จ์ผ๋ฉด ๋๊ฐ์ด ๋๋ ๊ฐ์ ธ. ์๋ฆฌ ๋ถ์กฑํ๋ฉด ์์์ ๋ค์ ์ค๋ก ๋ด๋ ค๊ฐ!"
๐ฑ auto-fit + minmax: ์์์ ์ค ๋ฐ๊ฟ!
* ๋ธ๋ผ์ฐ์ ์ฐฝ ํฌ๊ธฐ์ ๋ฐ๋ผ ์นด๋ ๊ฐ์๊ฐ ์๋ ์กฐ์ ๋ฉ๋๋ค. ๋ฏธ๋์ด ์ฟผ๋ฆฌ ์์ด!
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. grid-template-columns: 1fr 2fr; ์ค์ ์, ์ ์ฒด ๋๋น๊ฐ 300px์ด๋ผ๋ฉด ์ฒซ ๋ฒ์งธ ์ด์ ์ค์ ๋๋น๋ ์ผ๋ง์ผ๊น์?
โ
์ ๋ต: 100px
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
:
fr์ ๋จ์ ๊ณต๊ฐ์ ๋น์จ๋ก ๋๋๋ ๋จ์์ ๋๋ค.1fr 2fr์ ์ ์ฒด๋ฅผ 1:2 ๋น์จ๋ก ์ชผ๊ฐ ๋ค๋ ๋ป์ด์์. 300px รท (1+2) = 100px์ด 1fr์ ๋ชซ์ด๋ฏ๋ก, ์ฒซ ๋ฒ์งธ ์ด์1 ร 100 = 100px, ๋ ๋ฒ์งธ ์ด์2 ร 100 = 200px์ด ๋ฉ๋๋ค. - ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋,
fr์ 'fraction(๋ถ์)'์ ์ฝ์์์.px์ฒ๋ผ ๊ณ ์ ๋ ๊ฐ์ด ์๋๋ผ ํ์ ๋ค๊ณผ ๋๋ ๊ฐ๋ ๋น์จ์ด๋ผ๋ ๊ฑธ ๊ธฐ์ตํ์ธ์!" - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "fr = ํผ์ ์กฐ๊ฐ ์. 1fr 2fr์ด๋ฉด ์ด 3์กฐ๊ฐ, ๋ด ๋ชซ์ 1์กฐ๊ฐ!"
Q2. grid-template-areas์์ ํน์ ์นธ์ ๋น ๊ณต๊ฐ์ผ๋ก ๋๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ๊ธฐํธ๋ ๋ฌด์์ธ๊ฐ์?
#.(๋ง์นจํ)_null
โ
์ ๋ต: 2. . (๋ง์นจํ)
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
:
grid-template-areas์์.(๋ง์นจํ)์ "์ด ์นธ์ ๋น์๋ฌ"๋ผ๋ ์์ฝ ๊ธฐํธ์ ๋๋ค. ์ฌ๋ฌ ๊ฐ๋ฅผ ์ฐ์์ผ๋ก ์ฐ๋ฉด(.. ..) ๋น ์นธ์ด ์ฌ๋ฌ ๊ฐ ์ด์ด์ง๋ ํจ๊ณผ๋ฅผ ๋ผ ์๋ ์์ด์. - ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋,
#์ด๋_,null์ Grid์์ ํน๋ณํ ์๋ฏธ๊ฐ ์์ด์. ์ค์ง.๋ง์ด '๋น ์์ญ'์ ๋ปํ๋ ๊ณต์ ๊ธฐํธ์ ๋๋ค!" - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "์ค๊ณ ๋๋ฉด์ ๋ง์นจํ(.)๋ฅผ ์ฐ์ผ๋ฉด, ๊ทธ ์๋ฆฌ๋ '๊ณตํฐ'๊ฐ ๋๋ค!"
Q3. [์์ฒ ์ด์ ํ
์คํธ ํ์: ์ํคํ
์ฒ ์ค๊ณ]
์์ ๋์์ด๋ ๋์ด "๋ชจ๋ฐ์ผ์์๋ ํค๋-์ฌ์ด๋๋ฐ-๋ณธ๋ฌธ ์์๋ก ๋์ค๋๋ฐ, ๋ฐ์คํฌํฑ์์๋ ํค๋-๋ณธ๋ฌธ-์ฌ์ด๋๋ฐ ์์๋ก ์์น๋ฅผ ๋ฐ๊ฟ์ฃผ์ธ์!"๋ผ๊ณ ํ์ญ๋๋ค. HTML ๊ตฌ์กฐ๋ฅผ ๋ฐ๊พธ์ง ์๊ณ ์ค์ง CSS Grid๋ง์ผ๋ก ์ด ๋ฐฐ์น๋ฅผ ๊ฐ์ฅ ์ฝ๊ฒ ๋ฐ๊พธ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ผ๊น์?
โ
์ ๋ต: ๋ฏธ๋์ด ์ฟผ๋ฆฌ ์์์ grid-template-areas์ ๊ตฌ์กฐ๋ง ์๋ก ์ ์ํ๋ค.
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
: Grid๋ HTML ์์ ์์์ ๊ด๊ณ์์ด
grid-area๋ก ์ ์๋ ์์ญ์ ์์น๋ฅผ ๋ง์๋๋ก ์ฌ๋ฐฐ์นํ ์ ์์ต๋๋ค. - ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋, ์๋ฐ์คํฌ๋ฆฝํธ๋ก DOM์ ๊ฐ์๋ผ์ฐ๊ฑฐ๋
order๋ฅผ ๋ณต์กํ๊ฒ ์ฐ๋ ๊ฑด ํ์ฑ ์ ๋๋ค. Grid Areas๋ผ๋ ๋๋ฉด์ ์๋ก ๊ทธ๋ฆฌ๋ ๊ฒ ์ ์์ด์์." - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "๋๋ฉด(Areas)๋ง ๋ฐ๊พธ๋ฉด ์ด์ฌ ๋!"
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋ CSS Grid๋ฅผ ๋ฐฐ์ฐ๊ณ ๋๋, ๊ทธ๋์ Flexbox๋ก ์๋ฑ๋ฐ๋ฑํ๋ ๊ฒ ๋ง์น ํฌํฌ๋ก ๊ตญ์ ๋จน์ผ๋ ค ํ๋ ๊ฒ ๊ฐ๋ค.
grid-template-areas๋ ์ ๋ง ์ถฉ๊ฒฉ์ ์ด์๋ค. CSS ์ฝ๋ ์์ ๋ ์ด์์ ๋ชจ์์ด ๊ทธ๋๋ก ์๋ค๋!
๐ก "Grid๋ ๋จ์ํ ๋ฐฐ์น๊ฐ ์๋๋ผ ์์ญ์ ๋ฒ์ ์ธ ๊ฒฝ๊ณ๋ฅผ ๊ธ๋ ๊ฑด์ถ์ด๋ค. ์๋ฒฝํ ๊ณจ๊ฒฉ์ด ์๋ฒฝํ UX๋ฅผ ๋ง๋ ๋ค."
ํนํ repeat(auto-fit, ...) ์ด๊ฑธ ๋ณด๋ฉด์ "์, ์ด๊ฑฐ๋ฉด ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๋ฐ์ ์ค์ผ ์ ์๊ฒ ๋๋ฐ?" ์ถ์๋ค.
์์ ๋์ด ์ฃผ์ ๋ณต์กํ ๊ด๋ฆฌ์ ๋์๋ณด๋ ์์, ์์ ๊ฐ์ผ๋ฉด ํ์จ๋ถํฐ ๋์๊ฒ ์ง๋ง ์ด์ Grid ๋๋ฉด๋ถํฐ ๊ทธ๋ ค๋ณด๊ณ ์ถ๋ค.
๋ด์ผ์ ์์๋ค์ '๊ณ๊ธ ์ฌํ'์ธ z-index๋ Stacking Context๋ฅผ ๋ฐฐ์ด๋ค๋๋ฐ, ๋ฒ์จ ๋จธ๋ฆฌ๊ฐ ์ง๋๊ฑฐ๋ฆฌ์ง๋ง ์ํธ ๋์ด ๊ณ์๋๊น ๋ ๋ ํ๋ค! ๐