📒

4. 화면 요소들의 반응형 처리



4. 화면 요소들의 반응형 처리

4.1 flex

4.1.1 flex(flexbox)란?

flexbox(Flexible Box Module)은 웹 디자인 및 웹 개발에서 사용되는 레이아웃 모델 중 하나로 flexbox 내의 아이템 간 공간 배분과 정렬 기능을 제공하기 위한 1차원 레이아웃 모델입니다. flex(flexbox)는 요소의 중앙 정렬, block 요소들의 가로 정렬 등 다양한 레이아웃을 편하게 구현하는 것을 가능하게 합니다.
💡
flex와 flexbox는 뭐가 다른가요?
CSS에서의 flex속성은 하나의 flex-item(자식)이 자신의 flex- container(부모)가 차지하는 공간에 맞추기 위해 크기를 조절하는 속성이며 flex-grow, flex-shrink, flex-basic의 단축 속성입니다.
책에서 소개하고자 하는 내용은 CSS 레이아웃 중 하나인 flexbox에 대해서 다룹니다. flexbox를 적용하기 위해선 컨테이너의 display 속성에 flex 혹은 inline-flex 사용이 요구되기 때문에 편의상 flexbox를 flex로 지칭하도록 하겠습니다.
flexbox 레이아웃을 만들기 위한 기본적인 HTML 구조는 다음과 같습니다.
<div class="container"> <div class="item">hello</div> <div class="item">flex</div> <div class="item">box</div> </div>
부모 요소인 div.containerFlex-Container라고 부르고 자식 요소인 div.itemFlex-Item이라고 부릅니다. 컨테이너의 Flex 속성에 따라 각각의 아이템들 배치 형태가 결정됩니다.
notion imagenotion image
 
💡
알아두면 좋아요
 
개발자 도구에 flexbox 디버깅 도구가 있습니다. 이 도구를 활용하시면 flexbox 레이아웃에 대한 정보를 직관적으로 확인할 수 있습니다. 개발자 도구 단축키는 f12 누르시면 됩니다.
notion imagenotion image
notion imagenotion image

4.1.2 flex의 두 개의 축

플렉스박스 레이아웃은 주축(main axis)교차축(cross axis)의 개념을 사용합니다.
notion imagenotion image
 
  • 주축(main axis) : 플렉스 아이템이 배치되고 있는 방향으로 진행하는 축입니다. 기본값은 행(row) 방향입니다. 주축의 시작과 끝을 일컬어 main start과 main end라고 합니다.
  • 교차축(cross axis) : 플렉스 아이템이 내부에 배치되는 방향에 직각을 이루는 축입니다. 교차축의 시작과 끝을 일컬어 cross start과 cross end라고 합니다.
주축과 교차축의 방향을 flex-direction속성을 통해 변경할 수 있습니다. 이 속성에 대해서는 뒤에서 설명하겠습니다.

4.1.3 flex container

플렉스는 부모 요소의 display 속성에 flex 또는 inline-flex 값을 지정하여 사용합니다. 이때 부모 요소가 flex container가 됩니다.
.container { display: flex; // display: inline-flex }
이 css 속성을 통해 기본적으로 아이템들은 가로로 배치가 되고 너비 값은 아이템 자신의 컨텐츠만큼 차지하게 되고 높이 값은 컨테이너의 높이 값 만큼 차지하게 됩니다. 아이템들이 inline-block 처럼 배치가 된다고 볼 수 있습니다.
notion imagenotion image
 
그렇다면 display: flex 와  display: inline-flex의 차이는 무엇일까요?
간단하게 설명하자면 display: flex로 지정된 컨테이너들은 block 요소와 같은 성향을 가지며 display: inline-flex로 지정된 컨테이너들은 inline 요소와 같은 성향을 가지게 됩니다.
notion imagenotion image
 
컨테이너에 다양한 플렉스 속성을 통해 다음과 같이 아이템을 제어할 수 있습니다.
  • flex-direction : 플렉스 아이템의 배치 방향을 설정합니다.
  • flex-wrap : 플렉스 아이템을 여러 줄 배치합니다.
  • flex-flow : 플렉스 아이템의 배치 방향과 여러 줄 배치를 한 번에 설정합니다.
  • justify-content : 주축 방향으로 다양하게 플렉스 아이템을 배치합니다.
  • align-items : 교차축 방향으로 다양하게 플렉스 아이템을 배치합니다.
뒤에서 하나씩 살펴보도록 하겠습니다.
flex-direction
flex-direction속성은 컨테이너의 아이템을 배치할 때 사용할 주축 및 방향을 지정합니다.
flex-direction 속성을 따로 지정하지 않았을 때의 기본값은 row(행) 방향입니다. 즉 아이템들이 수평으로 배치가 됩니다. 아이템들을 수직으로 배치하고 싶을 때에는 flex-direction: column을 명시적으로 지정해 주어야 합니다. 또한 기본적으로 아이템들은 왼쪽에서 오른쪽으로 배치가 됩니다. 아이템들의 배치 방향을 반대로 바꾸고 싶다면 flex-direction: row-reverse을 지정해 주어야 합니다.
  • flex-direction: row : 주축이 수평 방향입니다. 컨테이너의 아이템들이 수평축(왼쪽에서 오른쪽)으로 배치됩니다.
notion imagenotion image
 
  • flex-direction: row-reverse : row와 동일하게 동작하지만 주축의 시작점과 끝점이 반대로 위치됩니다. 아이템들이 수평축(오른쪽에서 왼쪽)으로 배치됩니다.
notion imagenotion image
 
  • flex-direction: column : 주축이 수직 방향입니다. 컨테이너의 아이템이 수직축(위에서 아래)으로 배치됩니다.
notion imagenotion image
 
  • flex-direction: column-reverse : column과 동일하게 동작하지만 수직축의 시작점과 끝점이 반대로 위치됩니다. 아이템들이 수직축(아래에서 위로)으로 배치됩니다.
notion imagenotion image
 
💡
접근성 고려 사항 flex-direction 속성에 row-reverse 또는 column-reverse 값을 사용하면 DOM 구조와 그 시각적 표현에 차이가 생깁니다. 이는 스크린 리더 등 접근성 기술을 사용하는 사용자들에게 잘못된 정보를 전달할 가능성이 생깁니다.
 
flex-wrap
flex-wrap 속성은 아이템들을 한 줄로 배치되게 할지, 컨테이너의 가능한 영역 내에서 벗어나지 않고 여러행으로 나누어 배치할지 결정하는 속성입니다. flex-wrap 속성을 따로 지정하지 않으면 기본값 flex-wrap: nowrap으로 지정됩니다.
  • flex-wrap: nowrap : 기본 설정값으로 컨테이너의 영역을 벗어나더라도 아이템들을 한 줄로 배치합니다.
notion imagenotion image
 
아이템들 크기를 고정 값으로 설정해놓아도 flex-shrink 값을 설정하지 않았으면 초기값 1로 설정되어 아이템들이 컨테이너의 크기에 맞춰 일정 비율 줄어들지만,
notion imagenotion image
 
flex-shrink0으로 설정하면 설정한 아이템들의 크기가 고정되어 컨테이너 안에 한 줄로 배치됩니다.
  • flex-wrap: wrap : 아이템들이 컨테이너 영역보다 클 때 컨테이너의 영역 내에 한 줄로 배치되지 못하는 상황이 있습니다. 그때 여러 행의 걸쳐 배치되게 하는 속성입니다. 여러행으로 배치되었을 때 각각의 행은 하나의 컨테이너라고 생각해야 합니다. 공간 배분은 해당 행에서만 이루어지며 다른 행은 영향을 받지 않기 때문입니다.
notion imagenotion image
 
flex-direction: row 일 때 main axis(주축)이 컨테이너의 왼쪽에서 시작하는 가로 축이므로 아이템들이 컨테이너의 가로 영역을 넘게 되면 다음 줄(위에서 아래)로 정렬되게 됩니다.
notion imagenotion image
 
flex-direction: column 일 때 main axis(주축)이 컨테이너의 위쪽에서 시작하는 세로 축이므로 아이템들이 컨테이너의 세로 영역을 넘게 되면 다음 줄(좌에서 우)로 정렬되게 됩니다.
  • flex-wrap: wrap-reverse : wrap속성과 동일하지만, 아이템들이 나열되는 시작점과 끝점이 반대가 됩니다. 예시를 보면 더욱 쉽게 이해할 수 있습니다.
notion imagenotion image
 
flex-wrap: wrap 일 때는 아이템들이 컨테이너의 가로 영역을 넘게 되면 위에서 아래로 줄이 바뀌어 정렬되었습니다. flex-wrap: wrap-reverse는 반대로 아래에서부터 시작하여 위로 줄이 바뀌게 됩니다.
notion imagenotion image
 
main axis이 column 일 때도 마찬가지로 초반 한 줄까지는 flex-wrap: wrap 속성과 동일합니다. 하지만 아이템이 컨테이너의 세로 영역을 넘게 되면 flex-wrap: wrap 속성에서는 좌에서 우로 줄이 바뀌어 정렬되었던 것에 반해 flex-wrap: wrap-reverse는 오른쪽에서부터 시작하여 왼쪽으로 줄이 바뀌게 됩니다.
flex-flow
flex-flow 속성은 flex-direction, flex-wrap 속성의 단축 속성입니다.
기본값은 flex-flow : row nowrap이며 사용법은 아래와 같습니다.
flex-flow = <'flex-direction'> || <'flex-wrap'>
flex-flow : column wrap 속성값으로 아이템들이 컨테이너 영역보다 클 때 한 줄로 배치되지 못하고 다음 행으로 배치됩니다.
notion imagenotion image
 
flex-flow : row-reverse wrap 속성값으로 아이템의 배치 방향이 오른쪽에서 왼쪽으로 바뀌었고 아이템들이 컨테이너 영역보다 클 때 다음행에 오른쪽에서 왼쪽으로 배치됩니다.
notion imagenotion image
 
이 외에도 ‘row wrap-reverse’, ‘column wrap’ 등등 다른 속성값들을 넣어서 실습해 보시면 어떻게 동작하는지 알 수 있을 것입니다.
justify-content
컨테이너에서 flex-direction 속성 값으로 인해 정해진 주축을 기준으로 컨테이너의 아이템들을 어떻게 정렬할 것인지를 정의합니다. 예를 들어 flex-direction의 값이 column이라면 위에서 아래 방향으로의 정렬을 정합니다. 기본적으로는 flex-direction 속성의 기본값은 row이므로 따로 지정하지 않으면 컨테이너의 가로 방향으로 정렬을 정의합니다.
notion imagenotion image
 
justify-content 속성 값은 다음과 같습니다.
  • justify-content : flex-start : 컨테이너의 아이템들이 주축의 시작 부분부터 밀착되어 정렬됩니다. 따로 속성 값을 지정해 주지 않으면 기본값으로 들어가는 값입니다.
notion imagenotion image
 
  • justify-content : flex-end : 컨테이너의 아이템들이 주축의 끝부분부터 밀착되어 정렬됩니다.
notion imagenotion image
  • justify-content : center : 컨테이너의 아이템들이 주축의 중앙 부분부터 밀착되어 정렬됩니다.
notion imagenotion image
 
  • justify-content : space-between : 컨테이너의 아이템들이 주축을 따라 고르게 분포됩니다. 아이템들 사이의 공간이 동일하게 유지되고 첫 번째 아이템은 주축의 시작점의 가장자리에 마지막 아이템은 주축의 끝점의 가장자리에 밀착됩니다.
notion imagenotion image
 
  • justify-content : space-around : 컨테이너의 각 아이템들의 이전과 이후의 공간의 크기가 동일하게 정렬됩니다. 즉 첫 번째 아이템의 이전과 마지막 아이템의 이후의 공간은 아이템 간의 사이 공간 크기의 절반을 차지합니다.
notion imagenotion image
 
  • justify-content : space-evenly : 컨테이너의 아이템들 간의 공간과 첫 번째 아이템 이전, 마지막 아이템 이후의 공간이 동일하게 정렬됩니다.
notion imagenotion image
 
align-items (교차축 방향으로 다양하게 플렉스 아이템 배치하기)
컨테이너의 교차축을 기준으로 컨테이너의 아이템들을 어떻게 정렬할 것인지 정의합니다.
기본적으로는 flex-direction 속성의 기본값은 row이므로 따로 지정하지 않으면 컨테이너의 세로 방향 정렬을 정의합니다.
notion imagenotion image
 
align-items 속성 값은 다음과 같습니다.
  • align-items : stretch : 컨테이너의 너비 및 높이에 한해서 아이템들이 교차축 방향으로 가득 채웁니다. 따로 속성 값을 지정해 주지 않으면 기본값으로 들어가는 값입니다.
notion imagenotion image
 
  • align-items : flex-start : 컨테이너의 아이템들이 교차축의 시작선에 정렬됩니다.
notion imagenotion image
 
  • align-items : flex-end : 컨테이너의 아이템들이 교차축의 끝선에 정렬됩니다.
notion imagenotion image
 
  • align-items : center : 컨테이너의 아이템들이 교차축의 중앙에 정렬됩니다.
notion imagenotion image
 
align-content
flex-wrap : wrap 상태에서 아이템들이 2줄 이상이 되었을 때 아이템들의 교차축 방향으로 어떻게 정렬할 것인지 정하는 속성입니다. flex-wrap : nowrap 상태에서는 아무 효과도 없습니다. align-content 속성 값은 다음과 같습니다.
  • align-content : stretch
notion imagenotion image
 
  • align-content : flex-start
notion imagenotion image
 
  • align-content : flex-end
    • notion imagenotion image
 
  • align-content : center
notion imagenotion image
 
  • align-content : space-between
notion imagenotion image
 
  • align-content : space-around
notion imagenotion image
 
  • align-content : space-evenly
notion imagenotion image
 

4.1.4 flex item

아이템들에게 플렉스 속성을 적용하면 아이템의 배치, 크기, 정렬 등을 제어할 수 있습니다.
아이템에 다양한 아이템 속성을 통해 다음과 같은 아이템을 제어할 수 있습니다.
  • flex-basis : 아이템의 초기 크기 설정합니다.
  • flex-grow : 아이템이 부모 컨테이너에 남은 공간을 얼마나 차지할지 설정합니다.
  • flex-shrink : 아이템이 부모 컨테이너의 공간보다 클 때 얼마큼 줄어들지 설정합니다.
뒤에서 하나씩 살펴보도록 하겠습니다.
flex-basis
flex-basis는 아이템들의 기본 크기를 지정합니다. flex-direction 속성값이 row일 때는 너비 값을, column일 때는 높이값를 지정합니다.
💡
auto값을 가지지 않는 flex-basiswidth(flex-direction 값이 column인 경우 height )값을 동시에 적용하는 경우 flex-basis 값이 우선 적용됩니다.
flex-basis의 속성값으로는 fill, max-content, min-content, fit-content 같은 content 키워드를 사용하거나 <’width’> 값을 나타내는 단위를 사용합니다. 기본값은 auto입니다.
flex-basis값을 따로 지정해 주지 않을 때에 기본값 auto는 해당 아이템의 width값을 사용합니다. width 값을 따로 지정해 주지 않았다면 아이템의 크기는 컨텐츠의 크기입니다.
notion imagenotion image
 
.item { flex-basis: 150px; }
flex-basis값을 150px로 주었을 때, ‘flex’ 와 ‘love’ 아이템은 150px로 늘어나고 ‘flexbox hi’ 아이템은 기존에 150px보다 컸으므로 그대로 유지됩니다.
notion imagenotion image
 
  • content : 컨테이너의 아이템의 컨텐츠 크기에 따라 자동으로 크기가 바뀝니다.
💡
flex-basis의 속성값 content는 flex-basis와 width, height 속성을 전부 auto로 설정한 것과 동일하게 작동합니다.
flex-grow
flex-grow는 아이템들이 컨테이너 안에서의 할당 가능한 공간을 어떻게 분배할지를 결정합니다. 각각의 아이템들이 flex-grow 값을 갖는다면 컨테이너 안에서 할당 가능한 공간을 flex-grow 값의 비율만큼을 가지게 됩니다. flex-grow의 속성값으로는 숫자 값이 들어가고 기본값은 0입니다. 기본값이 0이기 때문에 따로 적용하기 전까지는 아이템들은 컨텐츠 만큼의 크기를 가지게 되거나 flex-basis값만큼의 크기를 가집니다.
모든 아이템들이 동일한 flex-grow값을 갖는다면 컨테이너 안에서 동일한 공간을 할당받습니다.
.item { flex-grow : 1; /* flex-grow : 0; 기본값 */ }
notion imagenotion image
 
이번에는 각각의 아이템들에게 flex-grow 값을 1:2:1 비율로 설정하여 컨테이너의 남은 공간을 나누어 가지도록 해보겠습니다.
/* 1:2:1의 비율로 설정할 경우 */ .item1 { flex-grow : 1; } .item2 { flex-grow : 2; } .item3 { flex-grow : 1; }

notion imagenotion image
 
flex-shrink
flex-shrink는 아이템의 크기를 고정시키거나 축소할 때 사용하는 속성입니다. 기본적으로 flex-shrink 속성의 기본값은 1이므로 아이템들의 크기가 컨테이너의 크기보다 큰 경우 아이템의 크기가 줄어듭니다. 속성값을 0으로 지정해 주면 아이템들의 크기가 컨테이너의 크기보다 커도 줄어들지 않습니다.
flex-grow는 컨테이너의 남은 공간을 아이템들이 어떻게 분배할지 정하는 속성이라면 flex-shrink는 컨테이너 안에서 아이템들이 컨테이너가 줄어들었을 때 아이템들이 얼마큼 줄어들지를 결정하는 속성입니다. flex-grow의 반대개념이라고 할 수 있겠습니다.
💡
flex-shrink는 컨테이너에 flex-wrap: wrap 속성이 부여된 경우 작동하지 않습니다.

4.2 Grid 레이아웃

4.2.1 Grid 개념

Grid 레이아웃은 식당 내부의 테이블을 배치하는 것과 비슷한 원리로 작동합니다. 식당에는 여러 크기와 모양의 테이블이 있으며, 각 테이블을 일정한 간격과 패턴에 따라 배치할 수 있습니다. 필요에 따라 특정 테이블에 더 많은 공간을 주거나, 작은 테이블을 여러 개 묶어 큰 테이블처럼 보이도록 조절할 수도 있습니다. 이와 같이, Grid 레이아웃은 콘텐츠와 요소를 규칙적으로 배치하고 정렬하는 데 사용되며, 반응형 웹 디자인에 매우 유용합니다.
Grid는 웹 페이지의 요소를 격자(그리드) 형태로 정렬하고 배치하는 데 사용되는 기술입니다. Flex와의 주요 차이점은 Flex는 1차원의 한 방향 레이아웃 시스템인 반면, Grid는 2차원의 두 방향(x축, y축) 레이아웃 시스템을 제공한다는 것입니다. 이러한 이유로 Grid는 Flex보다 더 복잡한 레이아웃 표현이 가능합니다.
Grid 역시 Flex와 마찬가지로 container와 item 개념을 사용하여 웹 페이지의 구성 요소를 조합하고 정렬합니다.
<div class= "container"> <div class= "item">A</div> <div class= "item">B</div> <div class= "item">C</div> </div>
부모 요소인 div.container를 Grid Container(그리드 컨테이너)라고 부르고, 자식 요소인  div.item을 Grid Item(그리드 아이템)이라고 부릅니다. 그리드 컨테이너는 그리드의 영향을 받는 영역을 나타내고, 그리드 아이템은 이 영역 내에서 설정에 따라 배치되는 요소를 나타냅니다.
 
notion imagenotion image
 
notion imagenotion image
 
  • 그리드 컨테이너 (Grid Container)
그리드 레이아웃을 적용하는 전체 영역입니다. 일반적으로는 <div> 요소나 다른 블록 수준 요소가 그리드 컨테이너 역할을 합니다.
  • 그리드 셀 (Grid Cell)
그리드 컨테이너 내에서 그리드 아이템이 배치되는 개별 셀입니다. 셀은 행과 열의 교차점에 해당하며, 그리드 아이템은 이러한 셀에 위치하게 됩니다.
 
notion imagenotion image
 
  • 그리드 아이템 (Grid Item)
그리드 컨테이너의 자식 요소로, 그리드 레이아웃 내에서 배치되는 콘텐츠입니다
 
notion imagenotion image
 
  • 그리드 트랙 (Grid Track)
그리드 레이아웃에서 행 또는 열을 나타내는 요소입니다. 그리드 컨테이너 내에서 행과 열을 만들어 내는 구성 요소이며, 이를 통해 그리드 아이템을 배치합니다.
 
notion imagenotion image
 
  • 그리드 라인 (Grid Line)
그리드 셀을 구분하는 선입니다. 가로로는 수평 그리드 라인, 세로로는 수직 그리드 라인이 있습니다. 그리드 아이템은 이러한 그리드 라인 사이에 배치됩니다.
  • 그리드 넘버 (Grid Number)
그리드 라인의 각 번호이며,  그리드 넘버는 행과 열을 구분하고 정확한 위치를 나타내는 데 도움을 줍니다.
 
notion imagenotion image
 
  • 그리드 갭 (Grid Gap)
그리드 셀 사이의 간격으로, 행과 열 간의 간격을 나타냅니다. 그리드 갭을 설정하여 그리드 아이템 사이의 간격을 지정할 수 있습니다.
 
notion imagenotion image
 
  • 그리드 영역 (Grid Area)
여러 그리드 셀이 결합된 영역을 나타냅니다. 그리드 아이템은 하나 이상의 그리드 셀을 차지하고, 이를 통해 그리드 영역을 형성합니다.
 
💡
크롬의 개발자 도구에는 그리드 레이아웃을 명확하게 시각화하는 기능이 있습니다. 개발자 도구를 열고 그림과 같이 표시된 영역을 클릭하면 이를 확인할 수 있습니다.
 
notion imagenotion image
 

4.2.2 Grid Container

display 속성
그리드 레이아웃을 만들 때, 먼저 그리드를 적용할 가장 바깥 영역을 그리드 컨테이너로 지정해야 합니다. 이를 위해 컨테이너 요소에 display: griddisplay: inline-grid를 선언하는 것으로 시작합니다.
display: grid는 컨테이너 내부의 요소를 블록(block) 요소로 배치합니다. 이미 블록 요소인 경우, 이 속성을 지정했을 때는 아무런 변화가 없습니다.
display: inline-grid는 컨테이너 내부의 요소를 인라인(inline) 요소로 배치합니다. 그리드 컨테이너는 텍스트 흐름 내에서 정렬되므로 다른 인라인 요소와 같은 줄에 배치됩니다.
.container1 { display: grid; } .container2 { display: inline-grid; }
 
grid-template-columns, grid-template-rows 속성
그리드는 플렉스와 마찬가지로, 컨테이너에 적용하는 속성과 아이템에 적용하는 속성으로 나눌 수 있습니다. 그리드 컨테이너 내에서 열과 행의 크기와 개수를 지정하기 위해서 grid-template-columns 속성과 grid-template-rows 속성을 사용합니다. 열과 행의 크기를 조절하기 위해 px, 백분율(%), em 등과 같은 고정 크기 값뿐만 아니라, repeat() 함수, 상대적인 크기를 나타내는 fr(fraction), 자동 크기를 나타내는 auto 등의 단위를 사용하여 크기를 지정할 수 있습니다.
  • grid-template-columns: 열 방향 그리드 트랙의 크기를 설정합니다.
  • grid-template-rows: 행 방향 그리드 트랙의 크기를 설정합니다.
다음 예제를 통해 그리드 컨테이너의 행과 열을 지정하는 방법에 대해 알아보겠습니다.
.container { display: grid; grid-template-columns: 100px 200px 300px; grid-template-rows: 200px 200px; }
notion imagenotion image
 
위의 예시에서 첫 번째 열은 1/6, 두 번째 열은 1/3, 세 번째 열은 1/2의 너비를 가지게 됩니다. 그리고 두 개의 행을 만들어 첫 번째와 두 번째 행은 200px 높이를 가지게 됩니다.
 
fr(fraction)
열과 행의 크기를 지정할 때, 픽셀(px) 단위를 이용하면 크기가 고정되어 있기 때문에 반응형으로 동작하지 않습니다. 그래서 그리드 레이아웃에서는 상대적인 크기 조절이 가능한 fr(fraction) 단위를 주로 사용합니다. fr은 사용할 수 있는 공간에 대한 비율을 의미합니다. 요소 간의 비율을 조절하여 컨테이너의 크기에 맞게 공평하게 분할하여 일관된 레이아웃을 유지하는 데 도움을 줍니다. 이 단위는 그리드 컨테이너 안에서만 사용되며, 상황에 따라 유연하게 레이아웃을 제어하는 데 유용합니다.
예를 들어, 3개의 열을 너비가 동일한 1:1:1의 비율로 만든다면 다음과 같이 지정할 수 있습니다.
grid-template-columns: 1fr 1fr 1fr;
notion imagenotion image
 
또한, 고정 크기와 가변 크기를 섞어 쓸 수도 있습니다. 예를 들어, 다음과 같이 지정하면 왼쪽 첫 번째 열은 100px로 고정되고, 나머지 두 번째와 세 번째 열은 1:2의 비율로 유연하게 조절됩니다.
grid-template-columns: 100px 1fr 2fr;
notion imagenotion image
 
repeat 함수
px이나 fr 단위를 사용하면 똑같은 값을 여러 번 반복하는 일이 발생합니다. 이때, 그리드 레이아웃에 내장된 repeat() 함수를 사용하면 반복하는 값을 간결하게 정의할 수 있어 코드의 가독성을 향상시키고 유지 보수를 쉽게 할 수 있습니다.
repeat(반복 횟수, 반복 값);
첫 번째 인자는 생성할 그리드의 행이나 열의 개수를 나타내는 반복 횟수이고, 두 번째 인자는 각 그리드의 행이나 열의 크기를 정의하는 반복할 값을 지정합니다.
 
이러한 repeat() 함수를 이해하기 위해 몇 가지 예제들을 통해 알아보겠습니다.
grid-template-columns: repeat(3, 200px);
notion imagenotion image
 
위 예제는 100px 크기의 column을 3개 배치할 때 100px을 3번 사용하는데, 즉 repeat(3, 100px)은 100px 100px 100px과 같습니다.
 
grid-template-columns: repeat(4, 1fr 2fr); grid-template-rows: repeat(2, 1fr);
notion imagenotion image
 
위 예제는 1fr과 2fr 크기를 번갈아가면서 column을 4번 반복하고, 1fr 크기의 row를 2번 반복하여 생성합니다. 따라서, 총 8개의 열과 2개의 행이 생성됩니다.
 
minmax()
minmax() 함수를 사용하면 그리드 아이템의 너비나 높이를 고정하지 않고, 최소 크기와 최대 크기 사이에서 자동으로 조절할 수 있습니다.
minmax(최솟값, 최댓값)
이 함수는 두 개의 인자를 받으며, 첫 번째 인자는 최소 크기를 나타내고 두 번째 인자는 최대 크기를 나타냅니다. 이렇게 설정하면 그리드 아이템은 최솟값보다 크거나 같고, 최댓값보다 작거나 같은 크기 범위 내에서 그리드 아이템의 크기를 유연하게 조절할 수 있게 해줍니다. 이 함수를 이용하면 다양한 화면의 크기와 레이아웃에 대응하기 위한 반응형 디자인을 구현할 수 있습니다.
grid-template-columns: minmax(100px, 1fr);
notion imagenotion image
 
위 예제는 열의 크기를 최소 100px로 하고, 사용 가능한 공간이 추가로 있을 경우 1fr 크기까지 늘릴 수 있게 합니다.
 
auto-fill과 auto-fit
repeat 함수와 함께 사용되는 auto-fillauto-fit 키워드는 그리드 아이템의 배치에 유용한 속성 값입니다. 이들은 반복 횟수를 고정하지 않고, 그리드 컨테이너의 너비나 높이에 따라 최대한 많은 셀을 배치하고 싶을 때 사용됩니다. 특히 행과 열의 아이템 개수가 명확하지 않은 경우에 유용하게 사용됩니다.
  • auto-fill: 그리드 아이템이 사용할 수 있는 공간을 모두 채울 때까지 반복됩니다. 그리드 컨테이너에 가능한 한 많은 그리드 행 또는 열을 생성하려고 시도하며, 그리드 아이템이 부족한 경우에는 빈 공간이 남게 됩니다.
  • auto-fit: auto-fill과 비슷하지만, 셀의 길이를 나눠서 길이를 딱 맞게 설정해 그리드 아이템과 함께 비어 있는 공간도 고려하여 열 또는 행의 수를 결정합니다. 따라서 그리드 내 아이템이 적더라도 남는 공간 없이 채우려고 합니다.
.container1 { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); } .container2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); }
notion imagenotion image
notion imagenotion image
 
auto-fillauto-fit의 주요 차이점은 그리드 컨테이너가 행 또는 열에 모든 아이템을 수용하고 남는 공간이 있을 때 발생합니다. auto-fill은 사용할 수 있는 공간을 채우는 역할을 하지만, 비어 있는 공간을 남겨둘 수 있습니다. auto-fit은 비어 있는 공간을 최대한 활용하여 남는 공간 없이 그리드를 채우기 위해 조절합니다. 이러한 키워드를 사용하면 다양한 화면 크기와 콘텐츠 양에 대응하는 반응형 그리드 레이아웃을 만들 수 있습니다.
 
column-gap, row-gap, gap
그리드 레이아웃에서 각 그리드 아이템 사이의 간격을 설정하는 데 gap 속성을 사용합니다.
  • column-gap: 그리드 아이템의 열 사이의 간격을 조절합니다.
  • row-gap: 그리드 아이템의 행 사이의 간격을 조절합니다.
  • gap: 사용해서 행 간격과 열 간격을 한꺼번에 설정할 수도 있습니다.
.container{ row-gap: 10px; /* row의 간격을 10px */ column-gap: 20px; /* column의 간격을 20px */ gap: 10px 20px; /* row-gap: 10px; column-gap: 20px; */ }
notion imagenotion image
 
💡
gap은 IE에서 지원하지 않는 속성입니다. IE를 이용하시려면 처음부터 gap을 사용하지 않고 하셔야 합니다.
 
grid-auto-columns, grid-auto-rows, grid-auto-flow
  • grid-auto-columns: 그리드 아이템의 크기를 자동으로 지정할 때 사용됩니다. 열의 개수를 알 수 없거나 자동으로 생성될 때 자동으로 크기를 지정해 줍니다.
  • grid-auto-rows: 그리드 아이템의 크기를 자동으로 지정할 때 사용됩니다. 행의 개수를 알 수 없거나 자동으로 생성될 때 자동으로 크기를 지정해 줍니다.
  • grid-auto-flow: 자동으로 생성되는 그리드 아이템의 배치 방법을 정의합니다. 그리드의 배치 방향을 정의합니다. 행 또는 열로 설정할 수 있으며, 빈 공간을 채우는 속성인 dense 옵션도 있습니다.
.container{ grid-auto-columns: 100px; /* 열의 너비를 100px로 지정합니다. */ grid-auto-rows: 50px; /* 행의 높이를 50px로 지정합니다. */ }
 
align-content & justify-content & align-items & justify-items
플렉스 박스 레이아웃에서 살펴보았던 align-content, justify-content, align-items 또는 justify-items 속성을 사용하여 그리드 레이아웃의 항목을 정렬할 수 있습니다.
그리드 컨테이너 내의 그리드 행들을 수직으로 정렬합니다. 그리드 콘텐츠의 세로 높이가 그리드 컨테이너보다 작아야 합니다. 주요 값으로 start, end, center, space-between, space-around, stretch 등이 있습니다.
 
notion imagenotion image
  • start
그리드 아이템을 시작 부분(위쪽)으로 정렬합니다.
 
notion imagenotion image
  • center
그리드 아이템을 가운데로 정렬합니다.
 
notion imagenotion image
  • end
그리드 아이템을 끝 부분(아래쪽)으로 정렬합니다.
 
notion imagenotion image
  • space-around
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분에도 간격을 두고 정렬합니다.
 
notion imagenotion image
  • space-between
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분은 컨테이너 경계에 정렬합니다.
 
notion imagenotion image
  • space-evenly
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분과 그 사이에도 간격을 동일하게 두고 정렬합니다.
 
notion imagenotion image
  • stretch
그리드 아이템들을 컨테이너의 전체 높이로 늘려 채웁니다. 그리드 아이템이 수직 방향으로 늘어나거나 줄어들어서 컨테이너의 높이를 채우도록 합니다.
 
notion imagenotion image
  • start
그리드 아이템을 시작 부분 (왼쪽)으로 정렬합니다.
 
notion imagenotion image
  • center
그리드 아이템을 가운데로 정렬합니다.
 
notion imagenotion image
  • end
그리드 아이템을 끝부분 (오른쪽)으로 정렬합니다.
 
notion imagenotion image
  • space-around
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분에도 간격을 두고 정렬합니다.
 
notion imagenotion image
  • space-between
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분은 컨테이너 경계에 정렬합니다.
 
notion imagenotion image
  • space-evenly
그리드 아이템을 동일한 간격으로 배치하되 시작과 끝부분과 그 사이에도 간격을 동일하게 두고 정렬합니다.
 
notion imagenotion image
  • stretch
그리드 아이템들을 컨테이너의 전체 너비로 늘려 채웁니다. 그리드 아이템이 수평 방향으로 늘어나거나 줄어들어서 컨테이너의 너비를 채우도록 합니다.
 
notion imagenotion image
  • start
그리드 아이템을 시작 부분(위쪽)으로 정렬합니다.
 
notion imagenotion image
  • center
그리드 아이템을 가운데로 정렬합니다.
 
notion imagenotion image
  • end
그리드 아이템을 끝부분(아래쪽)으로 정렬합니다.
 
notion imagenotion image
  • stretch
그리드 아이템을 그리드 셀의 높이에 맞게 늘립니다.
 
notion imagenotion image
  • start
그리드 아이템을 시작 부분(왼쪽)으로 정렬합니다.
 
notion imagenotion image
  • center
그리드 아이템을 가운데로 정렬합니다.
 
notion imagenotion image
  • end
그리드 아이템을 끝부분(오른쪽)으로 정렬합니다.
 
notion imagenotion image
  • stretch
그리드 아이템을 그리드 셀의 너비에 맞게 늘립니다.
 
place-content & place-items
수평 및 수직 방향 모두에서 그리드 아이템을 정렬하는 데 사용됩니다. 하나의 값만 쓰면 두 속성 모두에 적용됩니다.
  • place-content: justify-contentalign-content 값을 한 번에 지정할 수 있습니다. align-content, justify-content의 순서로 작성합니다.
  • place-items: align-itemsjustify-items 값을 한 번에 지정할 수 있습니다. align-items, justify-items의 순서로 작성합니다.
.container1 { place-content: space-between center; /* <align-content> <justify-content> */ } .container2 { place-items: center start; /* <align-items> <justify-items> */ }
 

4.2.3 Grid -item

grid-column-start, grid-column-end, grid-column, grid-row-start, grid-row-end, grid-row
그리드 레이아웃은 눈에 보이지 않는 그리드 라인이 포함되어 있습니다.
  • grid-column-start: 열의 시작 번호를 정의하여 그리드 아이템이 몇 번째 열에서 시작할지 지정합니다.
  • grid-column-end: 열의 끝 번호를 정의하여 그리드 아이템이 몇 번째 열에서 끝날지 지정합니다.
  • grid-column: grid-column-start, grid-column-end를 한 번에 설정하는 단축 속성입니다
  • grid-row-start: 행의 시작 번호를 정의하여 그리드 아이템이 몇 번째 행에서 시작할지 지정합니다.
  • grid-row-end: 행의 끝 번호를 정의하여 그리드 아이템이 몇 번째 행에서 끝날지 지정합니다.
  • grid-row: grid-row-start, grid-row-end를 한 번에 설정하는 단축 속성입니다.
이 속성들을 사용해 다음과 같은 그리드 레이아웃을 만들어 보겠습니다.
.container { width: 500px; height: 500px; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); } .box1 { background-color: ; grid-row-start: 1; grid-row-end: 2; grid-column-start: 1; grid-column-end: 4; } .box2 { background-color: ; grid-row: 2/3; grid-column: 1/2; } .box3{ background-color: ; grid-row: 2/3; grid-column: 3/4; } .box4 { background-color: ; grid-row: 3/4; grid-column: 1/span 3; }
notion imagenotion image
 
💡
span 행과 열을 병합할 때 span 키워드를 사용합니다. span의 사전적 의미는 ‘한 뼘’ 또는 ‘~을 채우다’의 의미를 가지고 있습니다. 그리드 아이템이 현재 위치에서 n 개의 그리드 행 또는 열을 차지하도록 지정합니다. span 값을 사용하면 그리드 아이템의 위치와 크기를 보다 유연하게 설정할 수 있습니다.
 
grid-template-areas & grid-area
앞에서 살펴본 그리드 라인은 시작 번호와 끝 번호를 일일이 지정해서 레이아웃을 만들어야 했습니다. 하지만 grid-template-areas을 사용하면 그리드 레이아웃이 어떻게 배치되는지 한눈에 파악하기 쉽고 코드도 더 간결해집니다.
grid-area 속성을 이용하여 각 그리드 아이템 영역에 이름을 지정하고, grid-template-areas 속성을 사용해 아이템을 어떻게 배치할지 지정합니다. 각 아이템 영역을 공백으로 구분하고, 만약 아이템 영역을 비워 두려면 해당 자리에 마침표(.)를 넣으면 됩니다. 한 줄에 들어갈 영역을 큰따옴표(“ ”)로 묶어주고, 각 줄마다 줄 바꿈을 하면 그리드 레이아웃을 한눈에 볼 수 있습니다.
.container { width: 500px; height: 500px; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); grid-template-areas: "box1 box1 box1" "box2 . box3" "box4 box4 box4" } .box1 { background-color: ; grid-area: box1; } .box2 { background-color: ; grid-area: box2; } .box3{ background-color: ; grid-area: box3; } .box4 { background-color: ; grid-area: box4; }
notion imagenotion image
 
💡
grid-template-areasgrid-area를 사용할 때 주의할 점은 모든 상황에서 유용하지는 않을 수 있습니다. 만약 그리드 레이아웃이 매우 복잡하거나 각 그리드 아이템을 독립적으로 제어해야 할 때는 grid-column-start, grid-column-end, grid-row-start, grid-row-end 속성을 사용하는 것이 더 유용할 수 있습니다. 따라서 어떤 속성을 선택할지는 프로젝트의 요구사항과 복잡성에 따라 달라질 수 있으므로 적절한 선택을 하는 것이 중요합니다.
 
align-self & justify-self
플렉스 박스 레이아웃에서 살펴보았던 align-self 또는 justify-self 속성을 사용하여 그리드 레이아웃의 항목을 정렬할 수 있습니다.
 
notion imagenotion image
  • start
그리드 아이템을 컨테이너의 시작(위쪽) 부분에 정렬합니다.
  • center
그리드 아이템을 수직 중앙에 정렬합니다.
  • end
그리드 아이템을 컨테이너의 끝(아래쪽) 부분에 정렬합니다.
  • stretch
그리드 아이템을 수직으로 늘려 컨테이너에 맞춥니다.
 
notion imagenotion image
  • start
그리드 아이템을 컨테이너의 시작(왼쪽) 부분에 정렬합니다.
  • center
그리드 아이템을 수평 중앙에 정렬합니다.
  • end
그리드 아이템을 컨테이너의 끝(오른쪽) 부분에 정렬합니다.
  • stretch
그리드 아이템을 수평으로 늘려 컨테이너에 맞춥니다.
 
place-self
align-selfjustify-self를 같이 쓸 수 있는 단축 속성입니다. align-self, justify-self의 순서로 작성하고, 하나의 값만 쓰면 두 속성 모두에 적용됩니다.
.item { place-self: start center; }
 
order
order 속성은 플렉스와 마찬가지로 각 그리드 아이템의 배치 순서를 지정하는 데 사용되는 속성입니다. 이 속성은 그리드 아이템의 순서를 나타내는 정수 값으로 설정하며, 작은 숫자일수록 먼저 배치됩니다. order 속성을 사용하면 HTML 구조와 상관없이 원하는 순서로 아이템을 배치할 수 있어 그리드 레이아웃을 더 유연하게 제어할 수 있습니다. 예를 들어, 모바일 레이아웃에서는 사이드바를 위로 올리고 본문을 아래로 내릴 수 있습니다. 또한, 특정 그리드 아이템을 시각적으로 더 강조하거나 다른 아이템보다 우선시하고 싶을 때 order 속성을 사용합니다.
.box1 { order: 3; } .box2 { order: 1; } .box3 { order: 2; }
notion imagenotion image
 
💡
order 속성은 그리드 레이아웃을 유연하게 만들어 시각적 디자인을 개선할 때 유용하지만, 의미적인 구조를 훼손하지 않고 신중하게 사용해야 합니다. 이 속성은 아이템의 시각적인 순서를 변경하는 것이지 HTML 자체의 구조를 변경하는 것은 아니므로, 웹 접근성 측면에서 주의가 필요합니다. 시각장애인분들이 사용하는 스크린 리더로 화면을 읽을 때, order를 이용해 순서를 바꾼다 해도 의미적인 구조가 변경되지는 않습니다. 따라서 order 속성을 사용할 때에는 접근성을 고려하여 의미적인 구조를 유지하면서 시각적 디자인을 조정하는 것이 중요합니다.
 
z-index
position 속성에서 봤던 z-index 속성을 그리드 레이아웃에서도 사용할 수 있습니다. 그리드 내에서는 position 속성을 사용하지 않고도 그리드 아이템이 화면에 보이는 우선순위를 설정할 수 있습니다. 예를 들어, 그리드 아이템 중 하나가 모달 팝업 또는 드롭다운 메뉴인 경우, 이러한 팝업이 다른 아이템 위에 나타나야 할 때 z-index를 사용할 수 있습니다. 또한, 그리드 내에 중첩된 그리드가 있는 경우 z-index를 사용하여 중첩된 그리드 아이템의 쌓임 순서를 조절할 수 있습니다. 이를 통해 그리드 레이아웃 내에서도 화면 요소들의 표시 순서를 조절하여 원하는 시각적 효과를 얻을 수 있습니다.
.box1 { grid-area: 1 / 1 / 2 / 3; } .box2 { grid-area: 1 / 2 / 3 / 3; z-index: 1; } .box3 { grid-area: 2 / 2 / 3 / 4; }
notion imagenotion image
 
💡
z-index 속성은 그리드 레이아웃에서 그리드 아이템의 쌓임 순서를 조절하는 데 유용하지만, 과도한 사용은 복잡성을 증가시킬 수 있으므로 필요한 경우에만 사용하는 것이 좋습니다.
 
grid 단축 속성
grid-template-xxxgrid-auto-xxx의 단축 속성입니다. grid-template-rows, grid-template-columns, grid-template-areas grid-auto-rows, grid-auto-columns, grid-auto-flow를 사용할 수 있습니다. 슬래시(/)는 보통 행의 값 / 열의 값을 분리하는 용도로 쓰입니다.
.container{ grid: auto-flow / 1fr 1fr 1fr; grid: auto-flow dense / 40px 40px 1fr; }
 
💡
IE 지원 IE 10, 11에서는  그리드 속성을 제한적으로 지원하며, 표준과 다른 특징을 가지고 있습니다.
표준
IE
display: grid grid-template-rows grid-template-columns grid-row-start grid-column-start align-self justify-self
display: -ms-grid ms-grid-rows ms-grid-columns ms-grid-row ms-grid-column ms-grid-row-align ms-grid-column-align
 

4.3 이미지

이미지는 웹 사이트에서 효과적으로 커뮤니케이션을 하는 데 있어서 핵심적인 역할을 수행합니다. 웹 페이지의 시각적인 콘텐츠 중 하나로, 이미지의 품질과 성능은 사용자 경험을 크게 좌우합니다. 특히, 모바일 디바이스와 데스크톱 환경에서 사용되는 다양한 화면 크기와 해상도에 대응하려면 이미지 반응형 처리가 필수적입니다.
이미지 반응형 처리는 웹 페이지의 빠른 로딩 속도, 데이터 사용량 최적화, 그리고 다양한 환경에서 최상의 시각적 품질을 보장하는 데 도움을 줍니다. 이를 위해서는 이미지를 효과적으로 선택하고 관리하는 기술들이 필요합니다. 이번 장에서는 이미지 반응형 웹 디자인을 위한 핵심 기술에 대해 살펴보겠습니다.
 

4.3.1 이미지 포맷 선택

이미지 포맷 선택하기에 앞서 아래 5가지의 상황을 고려하여 선택하여야 합니다.
  • 용도: 이미지가 어떤 용도로 사용되는지 고려합니다. 사진, 로고, 아이콘 등 다양한 용도에 맞는 포맷을 선택합니다.
  • 화질 요구: 화질이 중요한 경우에는 손실 압축이 적용된 JPEG나 PNG를 사용하고, 더 높은 화질이 필요한 경우에는 AVIF와 같은 고화질 포맷을 고려합니다.
  • 파일 크기: 대역폭 제한이나 페이지 로딩 시간을 고려하여 파일 크기를 최적화합니다.
  • 투명도 및 애니메이션: 투명한 배경이나 애니메이션을 지원해야 하는 경우에는 PNG 또는 WebP와 같은 포맷을 고려합니다.
  • 브라우저 호환성: 대상 브라우저에서 지원하는 이미지 포맷을 고려하여 선택합니다.
 
notion imagenotion image
JPEG (Joint Photographic Experts Group)
  • 장점: 손실 압축을 사용하므로 파일 크기를 줄이고 화질을 유지할 수 있습니다.
  • 단점: 투명한 배경을 지원하지 않으며, 비손실 압축은 제공하지 않습니다.
  • 용도: 사진 및 복잡한 이미지에 적합합니다.
notion imagenotion image
PNG (Portable Network Graphics)
  • 장점: 비손실 압축을 사용하여 높은 화질 유지하고 투명한 영역 및 알파 채널 지원합니다.
  • 단점: JPEG에 비해 파일 크기가 큰 경우가 있습니다.
  • 용도: 일반 이미지 및 그래픽에 적합하고 투명한 배경을 지원합니다.
notion imagenotion image
GIF (Graphics Interchange Format)
  • 장점: 애니메이션 및 반복 이미지를 지원합니다.
  • 단점: 색상 제한이 있고, 비손실 압축을 제공하지 않습니다.
  • 용도: 간단한 애니메이션 및 간단한 그래픽에 적합합니다.
notion imagenotion image
SVG (Scalable Vector Graphics)
  • 장점: 크기가 조절 가능하며, 해상도에 영향을 받지 않습니다. 텍스트 기반 형식이므로 파일 크기가 작습니다.
  • 단점: 복잡한 비트맵 이미지에는 적합하지 않습니다.
  • 용도: 벡터 그래픽 및 아이콘에 적합합니다.
notion imagenotion image
WebP
  • 장점: 작은 파일 크기와 높은 화질 제공하고 투명한 배경 및 애니메이션 지원 가능합니다.
  • 단점: 모든 브라우저에서 지원하지는 않을 수 있습니다.
  • 용도: Google에서 개발한 형식으로, JPEG 및 PNG 대체용으로 사용 가능합니다.
notion imagenotion image
AVIF (AV1 Image File Format)
  • 장점: 최신 비손실 압축 형식으로, 작은 파일 크기와 높은 화질을 제공합니다.
  • 단점: 모든 브라우저에서 지원하지는 않을 수 있습니다.
  • 용도: 고화질 이미지에 적합한 최신 형식입니다.
이미지 : flaticon.com
 
💡
비손실 압축(Lossless Compression)은 데이터를 압축하고 다시 복원할 때 원본 데이터를 완벽하게 복구할 수 있는 압축 방식을 의미합니다. 이 방식은 원본 데이터의 모든 정보를 보존하므로, 이미지나 오디오, 텍스트 파일 등에서 중요한 정보가 손실되지 않도록 하는 데 사용됩니다.
 

4.3.2 반응형 이미지 태그

<img> 태그는 웹 페이지에 이미지를 삽입하는 기본 태그입니다.
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <body> <img src="image.jpg" alt="반응형 이미지"> </body>
위 예제를 통해 <img> 태그에서 기본적으로 사용하는 속성들을 볼 수 있습니다.
  • src: <img> 태그에서 이미지의 URL을 지정하는 속성입니다.
  • alt: 대체 텍스트를 제공하는 속성으로, 이미지가 로드되지 않거나 스크린 리더가 페이지를 읽어줄 때 사용됩니다.
src 속성은 이미지 경로 확인을 위해 필수로 작성되어야 합니다.
이제 불러온 이미지를 다양한 화면 크기에 맞게 변화하는 반응형 이미지로 만들어보겠습니다.
img { max-width: 100%; /* 이미지 최대 너비 설정 */ height: auto; }
이미지 태그에 max-width값을 100%로 지정하여 이미지의 최대 너비를 화면에 맞게 조절합니다. 이로 인해 이미지의 너비가 부모 요소의 너비와 같아지거나 작아질 수는 있지만, 부모 요소의 너비보다 크게 확대되지는 않습니다. 또한 height값을 auto로 주어 이미지의 가로 세로 비율을 유지할 수 있도록 합니다.
  • max-width: 요소의 최대 너비를 설정하여 속성의 크기가 지정 값보다 커지는 것을 방지합니다.
  • height: 이미지의 높이를 지정합니다. 값을 auto로 줄 경우 세로는 이미지의 비율에 맞게 자동으로 조절됩니다.
화면 크기가 변화함에 따라 이미지도 반응하도록 하는 코드를 작성해 보았습니다. 여기서 이미지 크기를 좀 더 세밀하게 적용할 수는 없을까요? 아래 코드를 살펴봅시다.
/* 기본 이미지 스타일 */ img { width: 100%; height: auto; } /* 미디어 쿼리를 사용하여 화면 크기에 따라 이미지 크기 조절 */ @media (max-width: 768px) { .image-container img { width: 50%; /* 화면 너비가 768px 이하일 때 이미지 크기를 50%로 줄임 */ } }
위 코드는 미디어 쿼리를 사용하여 특정한 화면 너비에 따라 이미지 크기가 변화하도록 만든 예제입니다. 화면 너비가 768px 이하일 때 이미지 크기를 50%로 줄이도록 합니다. 이렇게 앞에서 배운 미디어 쿼리를 활용하면 더 세밀한 크기 조정이 가능합니다.
반응형 웹에서 이미지를 적용할 때는 크기와 함께 해상도 또한 고려할 수 있어야 합니다. 이미지 태그 내에는 반응형 이미지를 위해 크기와 해상도에 대해 고려할 수 있는 두 가지 속성이 있습니다. 이에 대해 자세히 알아보겠습니다.
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <body> <img srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1200w" sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 25vw" src="image-medium.jpg" alt="반응형 이미지"> </body>
기존 img 태그에서 추가된 두 가지 속성을 주목해 보세요.
첫 번째는 srcset 속성입니다. 동일한 이미지를 다양한 해상도의 버전으로 제시하여 선택하도록 합니다. 예제 코드에서는 srcset에 세 가지 선택 사항을 제시합니다.
  • image-small.jpg 300w: 뷰포트 너비가 300px 이하일 때 image-small.jpg 사용
  • image-medium.jpg 600w: 뷰포트 너비가 600px 이하일 때 image-medium.jpg 사용
  • image-large.jpg 1200w: 뷰포트 너비가 1200px 이하일 때 image-large.jpg 사용
 
두 번째는 sizes 속성입니다. 이 속성에서는 미디어 쿼리를 통해 특정 미디어 조건에 따라 차지하는 이미지 크기 값을 지정합니다. srcset에서 제공한 이미지 후보들의 사용 규칙을 정의하는 것이기 때문에, srcset 없이 단독으로는 사용할 수 없습니다. 예제 코드는 아래와 같이 정의합니다.
  • (max-width: 600px) 100vw: 화면 너비가 600px 이하일 때 이미지 크기를 100%로 설정
  • (max-width: 1200px) 50vw: 화면 너비가 1200px 이하일 때 이미지 크기를 50%로 설정
  • 25vw: 그 외에는 25%로 설정
 
srcset, sizes 속성을 이용하여 <img> 태그 안에서 반응형 이미지를 구현할 수 있는 방법에 대해 알아보았습니다. 브라우저는 이제 화면의 너비, 해상도, 이미지의 크기 등을 고려하여 환경에 따라 최적의 이미지를 나타낼 것입니다.
  • srcset: 여러 해상도의 이미지 버전을 나열합니다.
이미지 파일 이름, 공백, 고유 픽셀 너비로 이루어졌으며 고유 픽셀 너비는 w단위를 사용합니다.
  • sizes: 각 미디어 조건에 따라 이미지가 화면을 얼마나 차지할지 나열합니다.
미디어 조건문, 공백, 차지할 너비 값으로 작성하며 px, em 또는 vw를 사용해야 합니다.
 
💡
w서술자는 이미지의 해상도를 나타내는 데 사용되는 단위로, 원본 이미지의 픽셀 너비(width)를 알려줍니다. 예를 들어 300w는 이미지의 픽셀 너비가 300px 임을 의미하고, 600w는 이미지의 픽셀 너비가 600px 임을 나타냅니다.
 
<picture> 태그는 여러 환경에 따라 다른 이미지를 표시하려는 경우에 사용하는 태그입니다. <picture> 태그 내에 다양한 구성 요소들을 활용하여 화면 크기에 따른 다양한 이미지를 구현할 수 있습니다. 예제와 함께 구성 요소들을 살펴보겠습니다.
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <body> <picture> <source srcset="image-small.jpg" media="(max-width: 600px)"> <source srcset="image-medium.jpg" media="(max-width: 1200px)"> <img src="image-default.jpg" alt="반응형 이미지"> </picture> </body>
<source> 태그는 브라우저가 고를 수 있는 소스를 제공합니다.
  • srcset: 이미지의 경로
  • media: 이미지 선택을 위한 미디어 쿼리(조건) 지정
  • type: 이미지 파일의 유형
<source srcset="image.jpg" type="image/jpeg">
<img> 태그에서는 <source> 태그에서 설정한 조건에 맞는 이미지가 없을 경우에 사용될 기본 이미지를 지정합니다.
<picture> 태그 내의 두 가지 요소를 알아보았으니, 이제 예제 코드를 다시 한번 확인해 봅시다.
  • max-width: 600px: 화면 너비가 600px 이하일 때 image-small.jpg 사용
  • max-width: 1200px: 화면 너비가 1200px 이하일 때 image-medium.jpg 사용
  • 화면 너비가 1200px 초과일 때 image-default.jpg 사용 (기본 이미지 적용)
 
반응형 웹 이미지는 다양한 기기와 화면 크기에 대응하여 최적의 사용자 경험을 제공합니다. 이미지의 크기와 해상도를 조정하여 로딩 속도를 개선하고, 사용자가 편리하게 이용할 수 있도록 도움을 줍니다. 따라서 반응형 웹 디자인 프로젝트에서는 적절한 반응형 이미지 전략을 구축하여 모든 사용자에게 일관된 시각적 경험을 제공해야 합니다.
 

4.4 미디어

오디오, 비디오, 애니메이션과 같은 다양한 미디어 형식은 사용자와의 감성적인 연결을 강화하고, 정보의 전달력을 높여줍니다. 미디어 콘텐츠가 다양한 화면 크기와 해상도에서 최적의 경험을 제공하기 위해서는 반응형 처리가 필수적입니다.
HTML 내에서 직접적으로 미디어의 반응형 처리를 할 수 있는 태그는 제한적이지만, 기본 미디어 삽입 태그와 CSS의 조합을 통해 효과적인 반응형 미디어를 구현할 수 있습니다. 이번에는 이러한 접근 방식과 함께 미디어의 반응형 처리를 위한 핵심 전략을 알아보겠습니다.
 

4.4.1 미디어 포맷 선택

notion imagenotion image
MP4 (H.264 codec)
  • 장점: MP4는 효율적인 압축률과 높은 호환성을 가진 동영상 포맷입니다. 대부분의 웹 브라우저와 디바이스에서 지원되며, 고품질의 비디오를 제공합니다.
  • 단점: 특허권 문제로 인해 일부 오픈 소스 프로젝트에서 사용이 제한될 수 있습니다.
  • 용도: 웹 스트리밍 서비스(YouTube 등), 멀티미디어 콘텐츠 배포 등 다양한 웹 기반 비디오 콘텐츠에 널리 사용됩니다.
notion imagenotion image
WebM (VP8/VP9 codec)
  • 장점: WebM은 Google이 개발한 오픈 소스 동영상 포맷으로서 라이센스 문제가 없으며, 고효율의 압축률을 가지고 있습니다.
  • 단점: 아직 모든 브라우저에서 완벽하게 지원되지 않아 호환성 문제를 겪을 수 있습니다.
  • 용도: 웹 기반 비디오 스트리밍 서비스에 주로 사용되며 HTML5기반의 게임 및 앱에서도 많이 활용됩니다.
notion imagenotion image
Ogg (Theora codec)
  • 장점: Ogg Theora는 오픈 소스 동영상 포맷으로서 라이센스 문제가 없습니다.
  • 단점: 압축률과 비디오 품질 면에서 MP4나 WebM보다 상대적으로 낮으며 일부 브라우저(옛 버전의 Internet Explorer 등)에서 지원하지 않아 호환성 문제를 겪을 수 있습니다.
  • 용도: 인터넷 방송, 게임 사운드 클립 등 다양한 멀티미디어 콘텐츠에 사용됩니다.
이미지 : flaticon.com
 

4.4.2 미디어 태그

<video> 태그는 웹 페이지에 비디오를 직접 삽입하고 싶을 때 사용합니다. 비디오와 관련된 또 다른 태그인 <iframe>과는 용도, 사용 방법 등의 차이가 있습니다. 이 차이는 <video> 태그를 살펴본 후 알아보도록 하겠습니다. 아래의 예제를 통해 비디오 태그의 구성 요소들을 확인해 봅시다.
<video controls src="video.mp4" width="320" height="240"> </video>
<video> 태그 내에서는 다양한 속성을 제공합니다.
  • controls: 비디오 컨트롤(재생, 일시정지, 볼륨 등)을 표시
  • width, height: 영상의 너비, 높이를 지정
  • autoplay: 웹 페이지가 로드될 때 비디오가 자동 재생되도록 지정
  • loop: 비디오 반복 재생
  • muted: 비디오의 사운드를 음소거로 시작
  • poster: 비디오 썸네일의 이미지 경로 지정
  • src: 비디오 파일의 경로를 지정
  • type: 비디오 타입을 설정
예제 코드에서는 위와 같은 속성을 이용해서 “video.mp4”라는 비디오 파일을 임베드 합니다. 이 비디오는 너비 320px, 높이 240px의 크기로 삽입되며, controls 속성을 통해 표준 비디오 컨트롤(재생, 일시정지, 볼륨 조절, 전체 화면 등)이 비디오 아래에 표시됩니다.
 
이러한 방식으로 <video> 태그를 사용하면 웹 페이지에 비디오를 쉽게  삽입할 수 있습니다. 여기서 더 나아가 다양한 브라우저에서의 호환성을 고려한 태그로 발전시켜보겠습니다.
<video controls width="320" height="240"> <source src="sample.mp4" type="video/mp4"> <source src="sample.ogg" type="video/webm"> </video>
위 코드에서는 <video> 태그 내에 <source> 태그를 사용하였습니다. 모든 웹 브라우저가 동일한 비디오 포맷을 지원하지는 않습니다. 예를 들어, 일부 브라우저는 MP4를 지원하지만 WebM을 지원하지 않을 수 있고, 반대의 경우도 있습니다. <source> 태그를 사용하면 여러 비디오 포맷을 지정하여 브라우저가 자동으로 지원하는 포맷을 선택하게 할 수 있습니다.
 
하지만 width, height 값을 고정 값으로 넣어주게 되면 반응형 처리가 되지 않는다는 사실을 아실 것입니다. 그럼 이제 <video> 태그로 삽입한 비디오를 반응형 비디오로 만들어보겠습니다.
<div class="responsive-video"> <video controls> <source src="video.mp4" type="video/mp4"> <source src="video.webm" type="video/webm"> </video> </div>
우선, 앞선 코드에서 CSS를 이용하여 비디오 태그를 설정할 수 있도록 <div> 태그로 감싸주었으며, 고정 값을 지정하였던 width, height 속성은 제거하였습니다.
.responsive-video { position: relative; padding-bottom: 56.25%; /* 16:9 종횡비 */ height: 0; } .responsive-video video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
이제, 어떻게 반응형으로 구현하였는지 CSS 예제를 살펴봅시다.
  • padding-bottom: 56.25%: 16:9의 종횡비를 나타내며, 이를 통해 비디오는 항상 16:9의 비율을 유지
  • height: 0: 컨테이너의 높이를 0으로 설정하여 실제 높이는 ‘padding-bottom’에서만 조절 가능
  • width: 100%, height: 100%: 비디오의 크기를 컨테이너 크기에 맞게 조절
이 예제를 사용하면 브라우저 너비에 따라 크기가 자동으로 조절되면서, 동시에 16:9 종횡비를 유지하는 반응형 비디오를 구현할 수 있습니다.
 
<iframe> 태그는 <video> 태그와 달리 직접 비디오를 삽입하기 위한 태그는 아닙니다. 이는 웹 페이지 내에 다른 웹 페이지나 외부 콘텐츠를 삽입할 때 사용됩니다. YouTube, Vimeo와 같은 비디오 호스팅 서비스에서 제공하는 임베딩 코드는 주로 <iframe>을 사용합니다.
<iframe src="https://www.example.com" width="500" height="300" sandbox="allow-same-origin allow-popups allow-scripts" allowfullscreen loading="lazy"> </iframe>
<iframe>의 주요 속성은 다음과 같습니다.
  • width, height: iframe의 크기 지정
  • src: iframe의 경로 지정
  • sandbox: iframe에 대한 보안 및 기능 제한을 설정
    • 다양한 값을 사용하여 특정 기능을 활성화하거나 비활성화함
    • allow-forms: 폼 제출을 허용
    • allow-popups: 팝업 창을 허용
    • allow-same-origin: 동일한 출처 정책을 허용
    • allow-scripts: 스크립트 실행을 허용
    • allow-top-navigation: 상위 탐색을 허용
  • seamless: iframe 내용이 상위 문서와 완벽하게 통합되도록 함
  • srcdoc: iframe의 내용을 직접 명시 (iframe 내부에 표시될 HTML 문자열)
  • allowfullscreen: iframe 내에서 전체 화면 모드를 허용
  • loading: iframe의 로딩 전략을 지정
예제의 코드에서는 ‘https://www.example.com’ 주소의 웹 페이지를 로드하도록 설정되어 있습니다. 이 iframe은 loading="lazy" 속성을 통해 로드됩니다. 사용자가 페이지를 스크롤 하여 iframe 영역에 접근하기 전까지는 로드되지 않습니다. 이는 웹 페이지의 초기 로딩 속도를 빠르게 하기 위한 전략입니다.
 
<iframe> 태그의 경우 사용 시 주의사항이 있습니다. 이전에  <iframe> 을 이용해서 문제가 된 사례가 있습니다. 사례 중 일부로 설명드리도록 하겠습니다.
  • 보안이 문제가 된 사례
    • XSS 공격 (크로스 사이트 스크립팅)으로 해커들이 iframe을 이용하여 웹 페이지에 악의적인 코드를 넣어 다른 웹사이트를 가장한 후 사용자의 정보를 훔치거나 다른 해킹 시도를 시도한 적이 있습니다.
    • 클릭재킹 공격으로 iframe을 사용하여 사용자가 의도하지 않은 클릭을 유도하고 악의적인 동작을 유도하는 사례도 있었습니다.
  • 웹 접근성이 문제가 된 사례
    • iframe을 사용한 웹사이트는 스크린 리더와 같은 보조 기술을 사용하는 사용자에게 접근하기 어려운 경우가 있어서, 웹 접근성을 준수하기 어려웠습니다.
  • 검색 엔진 최적화(SEO)가 문제 된 사례
    • iframe 안의 콘텐츠는 검색 엔진에서 색인화되지 않거나 적절하게 표시되지 않을 수 있어서, 웹페이지의 SEO에 부정적인 영향을 미친 경우가 있습니다.
  • 모바일 호환성이 문제 된 사례
    • iframe은 모바일 기기에서 화면 크기에 맞게 자동으로 조절되지 않아서, 모바일 환경에서 사용자 경험을 저해하는 문제가 있었습니다.
위와 같은 내용을 잘 기억해서 iframe 태그를 활용하는 것이 중요합니다!
 
💡
iframe은 웹 페이지 내에서 다른 웹 페이지나 콘텐츠를 효과적으로 임베드 하는 강력한 도구입니다. 보안 취약성에 대한 우려가 있지만, 이러한 취약성을 신중하게 고려하고 적절하게 사용한다면, 사용자에게 다양한 콘텐츠와 기능을 제공하는 웹 사이트를 구현하는 데 큰 도움이 될 것입니다.
 
미디어 콘텐츠를 임베드 하는 경우에는 <iframe> 대신 특화된 도구들이 종종 사용됩니다. YouTube IFrame Player API가 그런 예입니다.
YouTube IFrame Player API는 YouTube 동영상을 웹 페이지에 임베드하고 제어하기 위한 JavaScript 라이브러리입니다. 이 API를 통해 개발자들은 프로그래밍 방식으로 비디오의 재생, 일시정지, 정지 및 볼륨 조절과 같은 작업을 수행할 수 있습니다. 따라서 <iframe>만으로는 어려울 수 있는 고급 제어 기능을 활용할 수 있게 됩니다.
또한 IFrame Player API를 활용하여 반응형 디자인에 맞춘 비디오 플레이어 구현도 가능합니다. CSS와 함께 적절히 활용하면 화면 크기에 따라 자동으로 크기가 조정되는 YouTube 비디오 플레이어를 만들 수 있습니다.
IFrame Player API를 사용하여 YouTube 동영상을 자동으로 크기 조정하는 방법을 JavaScript를 사용해서 구현해 보도록 하겠습니다. 동영상을 재생할 HTML 요소와 API 키가 필요합니다.
 
html 코드
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> /* youTube API를 사용하기 위해 해당 script를 import */ <script src="https://www.youtube.com/iframe_api"></script> <title>YouTubeAPI</title> </head> <body> <div id="player"></div> </body> </html>
 
javascript 코드
<script> // IFrame Player API를 비동기로 로드합니다. const tag = document.createElement('script'); tag.src = 'https://www.youtube.com/iframe_api'; const firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); /* 여기까지 IFrame Player API를 비동기 로드 한다는 의미로 해당 코드를 사용하지 않는다면 html코드에서 script를 이용해서 import 해야 합니다. */ let player; // YouTube 동영상 플레이어 객체 // API 로드 후 호출될 함수 function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '720', // 동영상 플레이어의 높이 width: '1280', // 동영상 플레이어의 너비 videoId: 'M7lc1UVf-VE', // 재생할 동영상의 고유 ID playerVars: { autoplay: 1, // 자동 재생 여부 controls: 1, // 동영상 컨트롤러 표시 여부 modestbranding: 1, // YouTube 로고 표시 여부 showinfo: 0, // 동영상 정보 표시 여부 loop: 1 // 반복 재생 여부 }, events: { 'onReady': onPlayerReady } }); } // 동영상 플레이어가 준비되면 호출되는 함수 function onPlayerReady(event) { // 동영상 플레이어 크기를 자동으로 조정 const aspectRatio = 16 / 9; // 원하는 가로:세로 비율 const playerElement = document.getElementById('player'); const containerWidth = playerElement.offsetWidth; const newHeight = containerWidth / aspectRatio; // 플레이어 크기 조정 player.setSize(containerWidth, newHeight); } </script>
videoId 항목에 재생할 동영상의 고유 ID를 넣어 줍니다. YouTube 영상을 선택하여 주소를 확인하면 다음과 같이 고유 ID를 확인할 수 있습니다.
 
창 크기가 변경될 때 onPlayerReady 함수가 호출되며 동영상 플레이어의 크기가 조정됩니다. 원하는 가로:세로 비율로 변경하려면 aspectRatio 변수를 조정합니다.
해당 API의 경우 반응형 웹 디자인과는 직접적인 연관성은 없지만 웹 페이지에서 비디오 콘텐츠를 처리하는 데 필요한 기능들을 제공합니다. 그래서 미디어에 관한 내용으로 소개해 드렸습니다.
JavaScript를 함께 사용하여 동영상의 크기가 브라우저 창의 크기에 따라 자동으로 조정되도록 만들었고, 이런 식으로 IFrame Player API는 반응형 웹 사이트에서 유용하게 활용될 수 있습니다.
 

4.4.3 오디오 포맷 선택

오디오 파일 형식으로는 다양한 포맷이 있지만, HTML5에서는 아래 세 가지의 오디오 포맷을 지원합니다.
notion imagenotion image
MP3
  • 장점: 대부분의 브라우저와 디바이스에서 지원됩니다.
  • 단점: 소리의 품질이 압축률에 따라 변화하며, 높은 압축률을 사용하면 소리 품질이 저하될 수 있습니다.
  • 용도: 음악 스트리밍 서비스, 음악 다운로드, 팟캐스트 등 웹 기반 오디오 콘텐츠에 널리 사용됩니다.
notion imagenotion image
WAV
  • 장점: 무손실 압축을 사용하여 높은 오디오 품질을 제공합니다.
  • 단점: 파일의 크기가 많이 크기 때문에 웹 배포에는 부적절하며, 스트리밍에는 적합하지 않습니다.
  • 용도: 음악 제작 및 편집, 고품질 사운드를 요구하는 전문 오디오 작업 영역에서 사용됩니다.
notion imagenotion image
OGG
  • 장점: 오픈 소스이기 때문에 라이센스 비용의 문제가 없습니다.
  • 단점: 파일의 크기가 많이 크기 때문에 웹 배포에는 부적절하며, 스트리밍에는 적합하지 않습니다.
  • 용도: 게임 사운드 클립, 인터넷 방송 등 멀티미디어 콘텐츠에 사용됩니다.
이미지 : flaticon.com
 

4.4.4 오디오 태그

<audio> 태그는 배경 음악이나 효과음 등의 오디오를 삽입할 때 사용합니다. 여기서도 이미지, 비디오 태그와 동일하게 <source> 태그를 사용하여 브라우저가 맞는 포맷을 선택하도록 다양한 옵션을 제공할 수 있습니다.
<audio controls preload="metadata" volume="0.8"> <source src="audio.mp3" type="audio/mpeg"> <source src="audio.ogg" type="audio/ogg"> <source src="audio.wav" type="audio/wav"> </audio>
<audio> 태그 내에서는 아래와 같은 속성들을 사용할 수 있습니다.
  • controls: 오디오 컨트롤(재생, 일시정지, 볼륨 조절 등)을 표시
  • autoplay: 웹 페이지가 로드될 때 오디오가 자동 재생되도록 지정
  • loop: 오디오 반복 재생
  • muted: 오디오의 사운드를 음소거로 시작
  • volume: 오디오의 초기 볼륨 지정 (0.0 음소거 ~ 1.0 최대 볼륨)
  • preload: 오디오 파일을 사전에 로드할지 여부를 지정
    • none(로드하지 않음), meta(메타 데이터만 로드), auto(전체 오디오 파일 로드)
  • type: 오디오 타입 설정
 
💡
웹 사이트의 목적 및 지원 브라우저에 따라 적절한 포맷을 선택하는 것은 매우 중요합니다. <source> 태그를 통해 여러 포맷의 오디오 파일을 동시 제공하여, 브라우저가 지원하는 최적의 포맷을 자동으로 선택하도록 해봅시다!