📒

2. 웹 레이아웃 기초



2. 웹 레이아웃 기초

2.1 매일 만나고 있는 레이아웃

매일 들여다보는 스마트폰의 화면, 지하철역에서 보이는 벽면 광고, 매장에서 음식을 주문하기 위해 이용하는 키오스크 등 우리는 어디서든 인쇄물, 전자 기기 등 다양한 매체를 접하게 되고, 매체를 통해 다양한 활동들을 하게 됩니다. 이러한 과정들 속에서 우리는 매체들만큼이나 다양한 레이아웃을 접하게 됩니다.
 
notion imagenotion image
 
이렇게 다양한 분야에서 사용되는 레이아웃은 공통적인 의미로 특정 공간 안의 요소들을 효율적으로 배치하는 것을 뜻한다고 할 수 있습니다. 그렇다면, 왜 반응형 웹을 만들어 가는데 레이아웃을 알고 있어야 할까요? 웹에서의 레이아웃은 화면 영역 안에 보이는 콘텐츠들을 시각적인 요인, 내용의 흐름, 사용자의 편의성 등을 고려해 콘텐츠들을 논리적으로 배치하는 것을 의미합니다.
이렇듯 디바이스와 해상도에 따라 반응하는 반응형 웹에서 콘텐츠들을 배치하는 레이아웃은 중요한 개념 중 하나이며, 견고하고, 유연한 반응형 웹을 구현하기 위해서 레이아웃에 대해 자세히 이해하고 있어야 할 필요가 있습니다.

2.2 박스 모델

2.2.1 박스 모델의 구성 요소

상상해 보세요. 당신이 방을 꾸미고 있다고 가정해 봅시다. 방 안에 여러 가지 가구를 배치하고, 그 주변의 프레임나 장식물을 두는 방법을 고려해 보겠습니다.
 
콘텐츠 영역(Content Area)
콘텐츠 영역은 방 안에 배치하는 가구 그 자체를 의미합니다. 사용자가 직접 접촉하고 사용하는 부분으로, 가구의 핵심 구성 요소입니다.
박스 모델의 콘텐츠 영역은 요소의 핵심 내용인 콘텐츠를 표시하는 부분입니다. 이것은 텍스트, 이미지, 비디오 또는 다른 미디어 요소 등 실제 콘텐츠를 포함합니다.
 
패딩 영역(Padding Area)
패딩 영역은 의자나 소파의 좌석에 놓는 쿠션과 유사합니다. 이것은 프레임이나 단단한 부분에 부드러운 쿠션을 제공하여 사용자가 편안하게 앉을 수 있도록 합니다.
박스 모델의 패딩 영역은 콘텐츠와 테두리 사이에 추가된 일정한 공간을 나타냅니다. 이렇게 콘텐츠가 테두리에 너무 가까이 붙지 않도록 요소의 내부와 외부 간에 부드러운 공간을 제공하여 디자인을 개선하는 역할을 합니다.
 
테두리 영역(Border Area)
테두리 영역은 가구 주위에 있는 장식이나 프레임과 유사합니다. 가구 주위의 프레임이나 장식 요소는 시각적으로 강조하는 역할을 합니다.
박스 모델의 테두리 영역은 콘텐츠와 패딩 영역을 감싸는 선으로, 시각적인 경계를 만들고 요소의 모양을 꾸며줍니다. 테두리는 경계선, 스타일, 색상, 그림자 효과 등을 추가하여 요소를 강조하거나 구분할 수 있습니다.
 
마진 영역(Margin Area)
마진 영역은 가구와 다른 가구 또는 벽 사이의 간격과 비슷합니다. 방 안에 여러 가구가 있다면, 이러한 가구 간에는 일정한 간격이 필요하며, 이때 생기는 여백이 마진 영역의 역할입니다.
박스 모델의 마진 영역은 테두리 바깥쪽 영역으로, 요소와 다른 요소 간의 여백을 나타냅니다. 이를
통해 요소를 다른 요소로부터 분리하거나 레이아웃의 간격을 조절하는 데 유용하게 사용됩니다.
 
notion imagenotion image
 
💡
웹 페이지에서 박스 모델을 어떻게 볼 수 있을까요?
 
notion imagenotion image
 
먼저, 원하는 웹 페이지를 브라우저에서 엽니다. 그리고 마우스 오른쪽 버튼을 눌러서 “검사”를 선택합니다. 단축키로 열 수도 있는데, Windows나 Linux에서는 ‘Ctrl + Shift + I’를 누르고, macOS에서는 ‘Cmd + Option + I’를 누르면 됩니다. 개발자 도구가 열리면, 요소(Elements) 탭에서 확인하려는 부분을 마우스로 클릭합니다. 선택된 부분은 개발자 도구에서 강조되어 표시됩니다. 그리고 개발자 도구 창 위에서 “Styles” 또는 “Computed” 탭을 클릭하면 아래 그림과 같은 박스 모델이 표시됩니다. 이 정보를 통해 요소의 크기와 여백에 대한 정보를 확인할 수 있습니다. 웹 페이지의 디자인과 레이아웃을 이해하고 수정하는 데 도움이 됩니다.
 
 

2.2.2 박스 모델의 속성

width와 height
콘텐츠의 크기를 조절하고 싶을 때, width 속성으로 너비를, height 속성으로 높이를 지정합니다. width와 height에 사용할 수 있는 속성값은 다음과 같습니다.
  • auto : 이 값은 기본값으로 설정되며, 브라우저가 박스 모델의 요소 내용에 맞게 너비와 높이를 자동으로 계산해 조정합니다.
  • <크기> : px이나 em 등의 단위를 사용하여 너비와 높이의 값을 직접 지정합니다.
  • <백분율> : 부모 요소의 너비와 높이에 대한 비율로 크기를 백분율(%)로 조정합니다.
일반적으로, px 단위를 사용하면 고정 크기를 가지므로 웹 브라우저의 크기와 상관없이 박스 크기가 유지됩니다. 그러나 백분율로 지정하면 웹 브라우저에 따라 크기가 달라지는 것을 볼 수 있습니다. 고정 크기가 필요한 경우에는 px을 사용하고, 반응형 디자인이나 다양한 디바이스에 대응해야 할 때는 백분율을 사용하여 크기를 조절하는 것이 유용합니다.
 
box-sizing
box-sizing 속성은 박스 모델의 크기를 어떻게 계산할지 지정하는데 사용됩니다. widthheight 속성은 박스 모델에서 콘텐츠 요소 주변의 여백이나 테두리를 제외한 콘텐츠 요소 크기에만 영향을 미칩니다. 따라서 실제로 박스 모델이 차지하는 크기를 결정할 때는 콘텐츠와 테두리 사이의 여백을 추가로 고려해야 합니다.
하지만 웹 문서에서 텍스트나 이미지 등의 여러 가지 요소를 배치할 때마다 원하는 박스의 크기를 설정하기 위해 여백과 테두리 값을 일일이 계산하고 추가하는 것은 번거롭고 불편할 수 있습니다. 이런 경우에 필요한 속성이 바로 box-sizing입니다. box-sizing은 박스 모델의 크기를 어떻게 결정할지 설정하며, border-boxcontent-box 두 가지 값으로 구분됩니다.
  • content-box
    • box-sizing 속성의 기본값으로, 여백의 크기를 제외한 콘텐츠 영역만 포함하여 박스 모델의 크기를 계산합니다. 주로 콘텐츠 영역의 width와 height만을 고려하여 크기를 지정할 때 사용됩니다.
  • border-box
    • 이 값은 콘텐츠 영역뿐만 아니라 테두리와 안쪽 여백까지 포함하여 박스 모델의 크기를 계산합니다. 따라서 박스의 크기를 미리 정해놓고 여백을 조절할 때 유용하게 사용됩니다.
       
예를 들어, 각 박스의 콘텐츠 영역의 너비와 높이가 200px이고, 콘텐츠와 테두리 사이의 여백은 30px, 테두리 두께도 30px이라면 실제 박스 모델의 너비와 높이는 어떻게 될까요?
.box1, .box2 { width: 200px; height: 200px; padding: 30px; border: 30px solid black; } .box1 { box-sizing: content-box; } .box2 { box-sizing: border-box; }
notion imagenotion image
 
content-box 속성을 적용한 box1은 콘텐츠 영역에 대한 크기를 계산합니다. 즉, box1의 너비는 200px에 좌우 패딩값 60px, 좌우 테두리 두께 60px을 모두 더한 320px입니다. 높이도 마찬가지로 계산됩니다.
그리고 border-box 속성을 적용한 box2는 테두리까지 포함한 너비 값이 200px이므로 좌우 패딩값 60px, 좌우 테두리 두께 60px을 뺀 나머지 80px이 실제 콘텐츠 영역의 너비입니다. box2의 높이도 너비와 동일하게 계산됩니다.
결과적으로, 두 박스는 동일한 너비와 높이를 가지지만 box-sizing 속성의 차이로 인해 크기를 계산하는 방식이 이렇게 달라집니다.
 
box-shadow
요소의 테두리 주변에 그림자 효과를 추가할 수 있습니다. box-shadow 속성을 통해 그림자 효과를 적용하면 요소가 화면에 떠 있는 것처럼 보이거나 요소를 시각적으로 돋보이게 만들 수 있습니다. box-shadow 속성은 다음과 같은 형식으로 사용됩니다.
box-shadow: inset <수평 위치> <수직 위치> <흐림 정도> <번짐 정도> <색상>
box-shadow의 속성값 중에서 수평 위치와 수직 위치의 값은 반드시 지정해야 합니다. 속성으로 두 개의 값만 제공되면 해당 값은 수평 위치와 수직 위치 값을 나타냅니다.  그 외의 속성값은 옵션으로, 필요한 경우에 사용할 수 있습니다.
  • <수평 위치> : 그림자가 수평으로 얼마나 떨어져 있는지를 나타냅니다. 양수 값은 오른쪽으로 그림자를 이동시키고, 음수 값은 왼쪽으로 그림자를 이동시킵니다.
  • <수직 위치> : 그림자가 수직으로 얼마나 떨어져 있는지를 나타냅니다. 양수 값은 아래로 그림자를 이동시키고, 음수 값은 위로 그림자를 이동시킵니다.
  • <흐림 정도> : 이 값을 별도로 지정하지 않으면 기본값인 0이 적용되며, 그림자가 진한 상태를 의미합니다. 이 값을 커질수록 그림자의 흐림 효과가 커져 그림자가 더 부드러워집니다. 음수 값은 적용되지 않습니다.
  • <번짐 정도> : 그림자의 퍼짐 정도를 나타냅니다. 기본값은 0이며, 이 경우 그림자가 요소와 동일한 크기로 표시됩니다. 양수 값을 설정하면 그림자가 모든 방향으로 퍼져서 그림자의 영역이 더 넓게 표현됩니다. 음수 값을 설정하면 그림자가 모든 방향으로 축소되어 보입니다.
  • <색상> : 그림자의 색상을 지정할 수 있습니다. 한 가지 색상만 지정할 수도 있고, 여러 색상을 공백으로 구분해 지정할 수도 있습니다.
  • <inset> : 이 키워드는 선택 사항이며, 필수 요소는 아닙니다. 기본적으로 그림자는 요소의 외부에 나타나지만, 이 속성을 사용하면 요소의 테두리 안쪽에 그림자가 그려집니다. 이렇게 하면 요소 내부를 강조하거나 입체적인 느낌을 줄 수 있습니다.
 
아래의 예제에서는 왼쪽 윗부분과 오른쪽 아랫부분에 각각 그림자를 만듭니다. box1은 번짐 정도를 따로 지정하지 않고, 반면 box2는 모든 속성을 적용하여 그림자를 나타냅니다.
.box1 { box-shadow: -15px -10px 5px 0px gold; } .box2 { box-shadow: 1rem 10px 20px 5px rgba(0, 0, 0, 0.5); } .box3 { box-shadow: inset 0 0 10px 10px green; }
notion imagenotion image
 
box1의 경우, 그림자 방향에 음수 값을 지정해 왼쪽 위로 각각 -15px, -10px의 이동이 적용되고, 흐림 정도는 5px, 그림자 색상은 gold인 그림자 효과를 보여줍니다.
box2는 오른쪽으로 1rem, 아래로 10px의 이동을 가지며, 흐림 정도는 20px, 번짐 정도는 5px인 rgba(0, 0, 0, 0.5) 색의 그림자 효과를 만듭니다.
box3는 inset 속성을 사용하여 내부 그림자를 생성하며, 흐림 정도와 번짐 정도는 각각  10px씩, 그림자 색상은 green인 그림자 효과를 보여줍니다.
 
border-style
테두리 스타일을 지정하는 border-style 속성을 사용해 테두리 선의 형태를 다양하게 설정할 수 있습니다. 테두리 선은 따로 속성값을 지정하지 않으면 화면에 나타나지 않습니다. 따라서  테두리의 두께나 색깔을 지정하더라도, 테두리를 그리기 위해 가장 먼저 border-style 속성을 지정해야 합니다.
border-style 속성에서 사용할 수 있는 속성값은 다음과 같습니다.
  • none: 테두리가 없음을 나타냅니다.
  • hidden: 테두리를 숨깁니다. ‘none’과 비슷하지만 ‘hidden’은 요소 주위에 있는 테두리를 가리는 역할을 합니다. 주로 접근성에 관련된 요소에 사용됩니다.
  • solid: 테두리가 실선으로 표시됩니다.
  • dotted: 테두리가 점선으로 표시됩니다. 점들이 일정한 간격으로 나타납니다.
  • dashed: 테두리가 파선으로 표시됩니다. 바느질 선과 같은 모양으로 선과 공백이 일정한 간격으로 번갈아 가며 나타납니다.
  • double: 테두리가 평행한 이중선으로 표시됩니다.
  • groove: 테두리가 오목하게 안쪽으로 파인 것처럼 표시됩니다. ridge의 반대입니다.
  • ridge: 테두리가 볼록하게 바깥쪽으로 튀어나온 것처럼 표시됩니다. groove의 반대입니다.
  • inset: 테두리가 요소 안쪽으로 들어가는 것처럼 표시됩니다. outset의 반대입니다.
  • outset: 테두리가 요소 바깥쪽으로 튀어나온 것처럼 표시됩니다. inset의 반대입니다.
notion imagenotion image
 
아래는 실선과 점선으로 테두리 스타일을 지정한 예제입니다.
/* 모든 방향 */ .box1 { border-style: solid; } .box2 { border-style: dotted; }
notion imagenotion image
 
만약 테두리 스타일을 모두 다르게 지정하고 싶다면 border-style 속성값을 여러 개 사용해 스타일을 지정할 수 있습니다. 최소 1개부터 최대 4개까지 속성값을 적용할 수 있습니다. 다음 예제를 통해 어떻게 지정하는지 알아보겠습니다.
/* 위아래 방향 | 좌우 방향 */ .box3 { border-style: dotted solid; } /* 위 | 오른쪽 | 아래 | 왼쪽 */ .box4 { border-style: hidden dashed double solid ; }
notion imagenotion image
 
또는 border-top-style, border-right-style, border-bottom-style, border-left-style처럼 border와 style을 설정하는 방향을 명시적으로 지정하여 속성값을 적용할 수도 있습니다.
이러한 border-style 값들은 요소의 테두리를 시각적으로 스타일을 꾸밀 때 주로 사용됩니다. 보통은 border-widthborder-color 속성과 함께 사용하여 테두리의 두께와 색상을 조정할 수 있습니다.
 
border-width
border-style과 마찬가지로 테두리의 두께가 설정되어야 화면에 표시됩니다. border-width 속성을 사용하면 요소의 테두리가 얼마나 두꺼운지를 지정할 수 있습니다. 이 속성에서 사용할 수 있는 주요 값들은 다음과 같습니다.
  • 너비 지정: 속성값을 px과 같은 단위를 사용해서 직접 지정합니다.
  • thin: 예약어로, 얇은 선의 테두리를 나타냅니다.
  • medium: 예약어로, 중간 두께의 테두리를 나타냅니다.
  • thick: 예약어로, 굵은 선의 테두리를 나타냅니다.
테두리의 두께도 속성값을 여러 개 사용하면 각각 다른 두께를 지정할 수 있습니다. 값을 한 개만 지정하거나 2개, 3개, 또는 4개까지 지정할 수 있습니다.
다음 예제를 보면서 border-width 속성을 어떻게 지정하는지 알아보겠습니다.
/* 모든 방향 */ .box1 { border-width: 10px; } /* 위아래 방향 | 좌우 방향 */ .box2 { border-width: thin medium; } /* 위 | 좌우 방향 | 아래 */ .box3 { border-width: thick thin medium; } /* 위 | 오른쪽 | 아래 | 왼쪽 */ .box4 { border-width: 5px 1.5rem 0 10px ; }
notion imagenotion image
 
추가로, border-top-width, border-right-width, border-bottom-width, border-left-width처럼 border와 width 사이에 원하는 방향을 넣고 값을 다르게 지정할 수도 있습니다.
 
border-color
이번에는 테두리에 색을 입혀보겠습니다. border-color 속성은 박스 모델의 테두리 색상을 지정하는 데 사용됩니다. 이 속성을 사용하여 상하좌우 방향의 테두리 색상을 동시에 지정할 수 있으며, 또한 bordercolor 사이에 방향을 넣어주면 개별적으로 테두리 색상을 지정할 수도 있습니다.
 
/* 모든 방향 */ .box1 { border-color: green; } /* 위아래 방향 | 좌우 방향 */ .box2 { border-color: red blue; } /* 위쪽 */ .box4 { border-top-color: yellow; } /* 오른쪽 */ .box4 { border-right-color: pink; }
notion imagenotion image
 
border
지금까지 테두리의 스타일, 두께, 색상을 지정하는 속성을 알아보았습니다. 각 속성을 개별적으로 사용하면 테두리에 대한 속성만 여러 줄을 차지하게 됩니다. 그래서 border 단축 속성을 사용하면 테두리 스타일과 두께, 색상의 속성값을 한 줄로 간편하게 지정할 수 있습니다.
border: <두께> <스타일> <색상>
만약 4개 방향의 테두리가 동일한 속성값을 가져야 할 때는 border 속성만 사용하면 되므로 유용합니다. 반면, 4개 방향의 테두리 스타일을 각각 다르게 지정하고 싶다면 border-top이나 border-right와 같이 border 속성에 방향을 함께 지정하여 따로 설정할 수도 있습니다. 이 경우에는 테두리의 스타일, 두께, 색상의 속성값을 지정하는 순서에 상관없이 사용할 수 있습니다.
 
다음 예제는 제목 텍스트 아래에 검정색 실선 테두리를 표시하고, 텍스트 단락 전체를 빨간색 점선 박스로 둘러싸고 있습니다.
h1 { border-bottom: 3px solid black; } p { border: 1px dashed red;} /* 두께 | 스타일 | 색상 */
notion imagenotion image
 
이와 같이 border 단축 속성을 사용하면 세부 속성을 따로 정의하는 것보다 코드가 간결해지고 가독성이 향상됩니다. 스타일 변경이 필요한 경우, 한 번의 수정으로 모든 요소에 동일하게 적용할 수 있어서 효율적입니다.
 
border-radius
이번에는 박스 모델의 모서리를 둥글게 만들어 보려고 합니다. 기본적으로 박스 모델은 사각형 모형으로 직각의 꼭짓점을 가지고 있습니다. 이때 border-radius 속성을 사용하여 모서리를 둥글게 조정할 수 있습니다. border-radius는 테두리 속성의 존재 여부와는 별개로 박스 모델의 모서리에 적용됩니다. 이 속성의 값으로는 px, em이나 백분율(%)을 사용하여 둥글기를 설정할 수 있습니다. 속성값은 한 개에서 네 개까지 지정할 수 있는데, 이 값의 순서는 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 순서로 적용됩니다. 또는 borderradius 사이에 방향을 넣어 각 모서리에 따로 속성값을 지정하는 방법도 있습니다.
notion imagenotion image
 
다음 예제를 통해 박스 모델을 원 형태로 만들거나, 원하는 꼭짓점만 둥글게 처리하는 방법을 알아보겠습니다.
/* 모든 방향 */
.box2 { border-radius: 2rem 0 2rem 0; }
/* 왼쪽 상단 | 오른쪽 상단 방향 */
.box4 {
border-bottom-right-radius: 40px;

/* 모든 방향 */ .box1 { border-radius: 50%; } /* 왼쪽 상단 | 오른쪽 하단 방향 */ .box2 { border-radius: 2rem 0 2rem 0; } /* 왼쪽 상단 | 오른쪽 상단 방향 */ .box3 { border-radius: 20px 20px 0 0; } /* 오른쪽 상단 | 오른쪽 하단 방향 */ .box4 { border-top-right-radius: 40px; border-bottom-right-radius: 40px; }
notion imagenotion image
 

2.3 display 속성과 레이아웃

2.3.1 display 속성

앞에서 배운 박스 모델들을 원하는 위치에 배치해 레이아웃을 완성하기 위해서는 display 속성이 무엇인지 알아야 합니다. display 속성은 HTML의 Tag들마다 설정되는 기본값이 있고, 그 기본값은 우리가 배치하고 싶은 상황에 따라 변경하여 사용해야 합니다.

2.3.2 display의 속성값들

display의 속성에는 다양한 값이 있지만 많이 사용되는 block, inline, inline-block, none을 소개하겠습니다.
div{ display: block }

notion imagenotion image
block이라는 단어의 뜻을 기억하면 이 속성을 기억하기 쉬울 것입니다.
block은 차단하다, 덩어리 등의 뜻을 가지고 있는데 display: block을 설정하게 되면
부모 컨테이너의 한 줄 전체를 차지하여 다른 요소들은 block이 차지한 너비에 배치할 수 없습니다.
block은 width와 height의 값 적용이 가능합니다. 그렇지만 눈에 보이는 크기가 작아졌다고 block 속성의 옆에 다른 block 요소를 둘 수는 없습니다. 항상 block 요소의 다음 요소는 줄이 바뀌어 배치됩니다.
block 요소는 inline 요소를 자식 요소로 포함을 할 수 있습니다. 즉, block 요소의 한 줄에 같이 배치될 수 있습니다.
block의 높이는 들어있는 콘텐츠의 높이만큼, 너비는 viewport 크기가 기본값입니다.
블록 박스를 만드는 태그는 <div>, <p>, <h1>, <ul>, <ol>, <li> 등이 있습니다.
div{ display :inline }
 

notion imagenotion image
인라인스케이트의 바퀴를 본 적 있나요? 일렬로 나란히 바퀴가 달린 인라인스케이트를 기억한다면 display: inline 속성값도 기억하기 좋을 것입니다.
inline 속성값을 가진 요소들은 한 줄로 나란히 왼쪽에서 오른쪽으로 정렬이 되는 특징을 가지고 있습니다.
inline은 width, height 값이 적용이 안 됩니다.
초기값 크기는 컨텐츠만큼의 크기를 가지게 됩니다. 예외적인 상황이 있는데 바로 패딩과 보더 속성을 사용할 수 있지만 마진은 좌우만 조절할 수 있습니다.
인라인 박스를 만드는 태그는 <span>, <a>, <strong>, <img> 등이 있습니다.
💡
블록 박스와 인라인 박스를 구분하는 것은 웹 페이지의 레이아웃과 스타일링을 조절하는 데 중요합니다. 블록 박스는 주로 레이아웃의 구조를 만들고, 인라인 박스는 텍스트를 꾸미고 내용의 일부를 처리하는 데 사용됩니다.
div{ display: inline-block }
notion imagenotion image
block처럼 한 줄로 가득 채우고 싶지 않은데 inline은 크기가 조절이 안 되어 불편함을 느꼈다면 inline-block 속성값을 사용하면 됩니다.
inline의 초기값과 똑같이 컨텐츠 크기가 초기값이고, width, height 값을 적용하여 크기를 조정하는 것이 가능합니다. 또한 padding과 margin도 상하좌우 어디든 적용이 가능합니다.
notion imagenotion image
div{ display: none }
notion imagenotion image
display:none 속성값을 설정하면 사용자에게 보이지 않게 되고 레이아웃에서 공간을 차지하지 않습니다.
display:none의 경우 요소를 렌더링에서 제외가 되어 스크린 리더 등의 보조 기술도 접근할 수 없습니다. 그러므로 요소를 숨기는 방법도 상황에 따라 적절한 속성으로 숨겨야 합니다.

2.3.3 요소를 숨기는 속성

visibility : hidden

notion imagenotion image
속성을 부여하기 전의 박스 모델들입니다.
이 각각의 요소들에 속성값을 넣게 되면 어떻게 적용이 될지 예상해 보시길 바랍니다.
notion imagenotion image
display:none은 요소뿐 아니라 요소가 차지했던 영역까지 전부 사라지게 되는 속성입니다.
레이아웃에 전혀 영향이 없어 다음으로 오는 요소는 none이 있던 자리에 당겨서 배치됩니다.
visibility:hidden은 요소는 숨겨주지만, 요소가 차지했던 영역은 남아있게 됩니다.

A11Y

A11Y라는 단어는 Accessibility의 A와 Y 사이의 11글자를 뜻하고 세계적으로 접근성 규정을 준수하고 장애로 인한 웹서비스 이용의 제약을 받지 않도록 개발하는 것을 의미하는 약어입니다.
레이아웃을 구성하며 요소를 숨길 때 display:none이나 visibility:hidden을 사용하여 요소를 숨기는 것은 스크린 리더가 요소에 접근이 되지 않아 접근성이 떨어지게 됩니다.
화면에는 보이지 않지만 스크린 리더 등 보조 기술로 접근할 수 있게 하는 요소 숨김 기법 코드를 소개하겠습니다.
.a11y-hidden{ clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; }

A11Y-hidden 기법은 개발자마다 다르게 사용하여 한가지가 아니니 다른 사이트는 어떻게 요소를 숨겼는지 찾아보는 것도 학습에 큰 도움이 될 것입니다.
display: none, visibility: hidden, a11y-hidden으로 숨긴 요소의 스크린 리더 테스트
notion imagenotion image
크롬 브라우저의 확장 프로그램 스크린 리더를 이용한 테스트입니다.
display:none과  visibility:hidden이 적용된 요소들은  스크린 리더에 출력이 되지 않았고 a11y-hidden이 적용된 요소만 출력이 되었습니다.
이렇게 요소는 숨겼지만 스크린 리더 등에게는 표현이 가능하게 접근성을 고려한 A11Y-hidden 기법이었습니다.
모든 사용자가 꼭 알아야 할 콘텐츠가 포함이 되어있다면 A11Y-hidden 기법을 사용해야 합니다.

2.4 Float / Position 속성

지금까지 레이아웃이 무엇인지부터 레이아웃을 구성하는 박스들에 대해 자세히 알아보았습니다!
지금부터는 위에서 알아 온 박스들을 직접 배치하고, 레이아웃을 만드는 css속성에 대해 알아보고자 합니다.

2.4.1 Float

float는 “뜨다”라는 뜻을 가진 단어입니다. css속성 또한 단어의 의미 그대로 해당 속성이 적용된 요소는 문서 내부에서 띄워지듯 배치가 되는데요, 이때 요소는 문서의 흐름으로부터 빠져 텍스트 및 인라인 요소가 그 주위를 감싸게 되며, 감싸는 요소는 해당 요소의 좌, 우측에 배치되게 됩니다. 글로만 설명을 보았을 땐, 정확히 어떤 것을 의미하는지 잘 와닿지 않을 수도 있습니다.
아래 예시 이미지를 살펴보며 다시 한번 위 설명을 되짚어 봅시다. 좌측이 float 속성을 적용하지 않았을 때, 우측이 float 속성을 적용하였을 때이며, float 속성을 적용한 경우 요소들의 배치를 보면 float 속성을 적용한 박스 주위로 다른 인라인 요소들이 감싸듯이 배치되고 있습니다.
 
notion imagenotion image
 
이제,  float가 어떤 식으로 요소를 배치하는지 조금은 감이 잡혔을까요?
다음으로는 float를 통해 자유롭게 레이아웃을 구성할 수 있도록 float속성값에 대해 자세히 알아보겠습니다. float의 속성값은 아래와 같이 3가지입니다.
  • float: left : 요소를 왼쪽으로 배치하는 속성 값입니다.
  • float: right : 요소를 오른쪽으로 배치하는 속성 값입니다.
  • float: none : float 속성이 없음을 의미하는 속성 값입니다.
위 속성을 활용하여 아래와 같은 간단한 레이아웃을 만들어 봅시다
 
notion imagenotion image
 
먼저 만들어야 할 레이아웃을 살펴봅시다.
레이아웃의 영역이 크게 3영역으로 나뉘어 있는 걸 볼 수 있습니다. 영역 별 성격을 임의로 생각하여 각각 <header>, <aside>, <main>의 태그로 html을 작성하여 봅시다.
 
<body> <header>header</header> <aside class="box left">aside</aside> <main class="box right">main</main> </body>
 
위와 같이 html 작업이 완료되었다면, 이제 css를 이용하여 요소들을 배치합니다.
여기서 우리는 <aside>태그와 <main>태그를 위에서 알아본 float를 사용하여 배치할 수 있다는 걸 알 수 있습니다. <aside>의 클래스 .left에는 float: left를, <main>의 클래스 .right에는 float: right를 적용해 주겠습니다.
 
/*기본 스타일*/ *{ box-sizing: border-box; margin: 0; padding: 0; } body { padding: 20px; height: 100vh; } header{ margin-bottom: 16px; height: 120px; border-radius: 15px; background-color: #B2C7D3; } .box { height: calc(100% - 140px); border-radius: 15px; background-color: #B2C7D3; } /*main과 aside에 float를 지정하여 레이아웃 배치*/ aside.left{ width: 190px; float: left; background-color: #E0E0F9;; } main.right{ width: calc(100% - 206px); float: right; background-color: #D6E3F8;; }
 
이제 float를 이용해 레이아웃을 잡는 방법에 대해 감이 많이 잡혔을 것입니다. 위 예제에 이어서 아래와 같이 <footer>영역이 추가된 레이아웃을 만들어 봅시다!
 
notion imagenotion image
 
<body> <header>header</header> <aside class="box left">aside</aside> <main class="box right">main</main> <!--footer 추가--> <footer>footer</footer> </body>
<footer>영역이 추가되었으니, 위에서 진행했었던 css스타일에서 박스들의 사이즈를 살짝 조정해 보겠습니다.
/*기본 스타일*/ *{ box-sizing: border-box; margin: 0; padding: 0; } body { padding: 20px; height: 100vh; } header, footer{ margin-bottom: 16px; height: 120px; border-radius: 15px; background-color: #B2C7D3; } .box { /*footer 영역을 위해 height값 조정*/ height: calc(100% - 276px); border-radius: 15px; background-color: #B2C7D3; margin-bottom: 16px; } /*main과 aside에 float를 지정하여 레이아웃 배치*/ aside.left{ width: 190px; float: left; background-color: #e0e0f9aa; } main.right{ width: calc(100% - 206px); float: right; background-color: #D6E3F8aa; }
 
여기까지 실습을 하면서 이상한 점을 눈치채셨나요?
위 코드를 그대로 실행해 보았을 때 결과는 예상과 달리 아래 이미지처럼 <footer>영역이 <aside><main>영역에 겹쳐 보이는 것처럼 보일 것입니다.
 
notion imagenotion image
 
왜 이런 현상이 발생하게 되는 걸까요? float속성은 다음 요소에 영향을 미치기 때문입니다. 이러한 float속성의 영향을 막기 위해서는 영향에서 벗어나야 하는 요소에 clear속성을 사용하면 됩니다.
clear속성의 속성값은 4가지입니다.
  • clear: left: float: left를 해제하는 속성 값 입니다.
  • clear: right: float: right를 해제하는 속성 값 입니다.
  • clear: both : float: left / float: right를 모두 해제하는 속성 값 입니다.
  • clear: none : clear처리를 하지 않는 속성 값 입니다.
💡
clear: leftclear: right가 각각 존재하는데, left와 right를 동시에 지워주는 both속성값은 언제 사용하는 걸까요? 실제 float를 이용한 레이아웃 작업 시 주로 float: left를 사용하여 요소들을 배치하기 때문에 clear의 속성값 또한 left를 사용하여 작업해도 되지만, 중간에 float: right를 사용했을 경우, 영향을 받는 것이 left인지, right인지 정확한 구분이 안될 때 등 clear 처리를 할 때 여러 예외 상황에도 유연하게 처리하기 위할 때 both속성값을 사용하게 됩니다.
 
이제 위에서 실행해 본 예제의 문제점을 해결할 수 있습니다. <footer>영역의 스타일에 clear: both를 추가해 주면 예제 이미지와 같이 깔끔하게 정리된 레이아웃을 확인할 수 있습니다. 마지막으로 float속성을 사용할 때 주의해야 할 사항에 대해 다뤄보겠습니다.
float는 앞에서 먼저 살펴본 것과 같이 속성이 상속되는 것 외 주의해야 할 사항이 한 가지 더 있습니다. 바로, 자식 요소들이 모두 float 속성을 가지고 있을 때, 부모 요소(컨테이너 요소)의 높이에 자식 요소들의 높이값이 포함되지 않게 됩니다.
이러한 현상은 부모 요소에 overflow: hidden을 사용하게 되면 해결할 수 있습니다.
 
notion imagenotion image
 

2.4.2 Position

css의 position속성은 요소가 배치될 때 어떤 식으로 배치될 지 정하는 속성이며, top, left, bottom, right 속성을 함께 사용하여 요소의 위치를 지정합니다. 우선 position의 속성값을 먼저 살펴보겠습니다. 속성 값은 총 5가지로 아래와 같습니다.
 
static
position: static;
position속성의 기본값으로, 요소를 정상적인 문서 흐름에 따라 배치하는 속성 값입니다.
 
relative
position: relative;
요소를 정상적인 문서 흐름에 따라 배치하되, 자기 자신의 위치를 기준으로 상대적(relative)으로 배치하는 속성값입니다. 배치할 때 위치의 값은 top, left, bottom, right속성을 이용하여 지정할 수 있습니다.
예시를 한번 살펴볼까요? 위, 그림과 같이 position: relative속성이 부여된 하늘색 박스가 있습니다.
배치 위치(top, bottom, left, right)를 지정해 주지 않았기 때문에 정상적인 문서 흐름에 따라 배치가 되어 있습니다.
 
notion imagenotion image
 
이때, 하늘색 박스에 top: 20px, right: 20px를 지정해 주면 어떻게 될까요?
위에서 설명한 것과 같이 “자기 자신을 기준으로”, 지정한 위치 값으로 “상대적으로 배치” 되고 있는 것을 볼 수 있습니다.
 
notion imagenotion image
 
absolute
position: absolute
position의 속성 값이 static을 제외한 값을 가지고 있는 가장 가까운 조상을 기준으로 배치하는 속성 값입니다. 정상적인 문서의 흐름에서 자기 자신의 요소를 제거하는 특징이 있으며, 배치할 때 위치의 값은 top, left, bottom, right속성을 이용하여, 지정할 수 있습니다.
위 설명만으로는 absolute의 속성을 이해하기는 어려울 것입니다. 아래 예제를 보면서 이해해 봅시다.
예시에서 부모 요소는 position: relative를 가지게 설정해 놓았고, 가운데 하늘색 박스에 absolute속성값을 갖는 박스를 만들었습니다.
앗, 그런데 relative예제와 달리 하늘색 박스와 오른쪽에 배치되어 있던 박스가 겹치는 현상을 볼 수 있습니다. 이렇게 되는 이유가 바로 위에서 설명된 “문서의 흐름에서 자기 자신의 요소를 제거하는 특징” 때문입니다 하늘색 박스에 absolute속성 값이 추가됨에 따라 문서 흐름에서 하늘색 박스의 요소가 제거되어 오른쪽에 있던 박스가 그 자리를 차지하게 되는 것이죠!
 
notion imagenotion image
 
다음으로는 위치값을 bottom: 0px, right: 0px로 지정해 봅시다
 
notion imagenotion image
 
하늘색 박스의 위치가 부모 요소 즉, 여기 예제에서는 position: relative속성을 가지고 있는 container 박스를 기준으로 배치되고 있는 걸 확인할 수 있습니다.
💡
absolute 속성값의 경우 배치 기준이 될 수 있는 부모 요소를 찾아 상위 요소를 탐색하게 되는 데요, 이때 상위 요소 어디에도 배치 기준에 해당되는 부모 요소가 없을 경우 <body>를 기준으로 배치가 됩니다.
 
fixed
position: fixed;
요소를 브라우저 화면 즉 뷰포트를 기준으로 배치하는 속성값입니다. absolute와 같이 정상적인 문서의 흐름에서 자기 자신의 요소를 제거하는 특징이 있으며, 배치할 때 위치의 값은 top, left, bottom, right속성을 이용하여 지정할 수 있습니다. fixed의 경우 absolute와 달리 배치 기준이 뷰포트로 absolute와 차이를 보입니다.
아래 예제 이미지와 같이 부모 요소(position: relative)안에 위치하였지만 bottom값과 right값이 부모 기준이 아닌 뷰포트 기준으로 배치되고 있는 걸 볼 수 있습니다. 이렇게 fixed속성 값을 갖는 요소는 화면이 스크롤 되어도 지정한 위치값에 고정되어 보입니다.
 
notion imagenotion image
 
이러한 fixed속성은 상단 바, 하단 바와 같이 화면 특정 위치에 고정된 요소를 만들 때 많이 사용합니다.
 
sticky
position: sticky;
position의 속성값이 static을 제외한 값을 가지고 있는 가장 가까운 조상을 기준으로 배치하는 속성값이며, 배치할 때 위치의 값은 top, left, bottom, right속성을 이용하여 지정할 수 있습니다. 이때, sticky속성값을 갖는 요소는 부모 요소의 높이 영역 동안 지정한 위치에 고정이 되어 보입니다. 이렇게만 설명되었을 땐 absolute와 다른 점이 없어 보이는데요, 아래 예시 이미지를 살펴봅시다!
container라는 스크롤이 가능한 부모 요소 안에 sticky값을 갖는 하늘색 박스와 absolute값을 갖는 회색 박스가 있습니다. 두 요소 모두 부모 요소를 기준으로 배치가 된 것이 보이는데요, 여기까지는 absolute와 sticky의 차이가 보이지 않습니다.
 
notion imagenotion image
 
두 속성값의 차이는 부모 요소 내부에 스크롤이 일어났을 때 확연하게 보입니다. 아래 예시 이미지와 같이 스크롤이 일어났을 때는 absolute속성값을 갖는 박스는 스크롤이 일어나자, 위로 올라가져 보이지 않지만 sticky속성을 갖는 박스는 스크롤 영역 안에서 지정된 위치 즉,  상단에서 10px떨어진 채로 고정되고 있는 것을 볼 수 있습니다.
 
notion imagenotion image
 
이렇게 sticky속성값을 이용하면 부모 요소 높이 동안 fixed속성값과 비슷하게 요소 위치를 고정할 수 있습니다. 이러한 점을 이용하여 홈페이지에서 스크롤에 따라 상단 바가 최상단에 고정되도록 하는 등의 기능으로 응용할 수 있습니다.
 
z-index
지금까지 position의 속성값들을 다루어 보았는데요, 여러 속성값의 예시를 보면서 요소들끼리 “겹치는” 현상을 많이 볼 수 있었습니다. 이때, 어떤 요소가 앞에서 보여지는지에 대한 기준은 과연 무엇일까요? 기본적으로는 요소들은 마크업, 즉 html이 나중에 작성된 요소일수록 앞에 보여지지만, position의 속성값이 static을 제외한 값을 가지고 있는 요소에는 z-index속성을 사용하여 요소들이 쌓이는 순서를 지정할 수 있습니다.
z-index의 속성값은 정수로 지정하며, 정숫값이 클수록 위에 쌓이는 요소가 됩니다. 만약 자식 요소의 z-index값을 음수로 지정한다면, 부모 요소의 뒤로 갈 수 있습니다.
 
/*box_1이 box_2보다 위에 쌓이게 됩니다.*/ .box_1 { position: relative; z-index: 10; } .box_2 { position: relative; z-index: 9; }
 
이렇듯 z-index는 서로의 값을 비교하여 요소가 쌓이는 순서를 정하는데, 이때 주의해야 할 점은 z-index가 비교되는 범위입니다. z-index는 문서 내에서 z-index가 적용된 모든 요소가 서로의 값을 비교하는 것이 아닌 특정 범위가 지정되어 있고, 범위 내부에 있는 요소들끼리 서로의 값을 비교하여 요소들이 쌓이는 순서를 정하게 됩니다. 이렇게 요소가 쌓이는 것을 개념화한 것을 쌓임, 맥락(stacking context)이라고 합니다. 조금 더 쉽게 이해하기 위해 예제를 통해 자세히 알아보겠습니다. 우선 아래와 같이 html구조를 만들어 줍니다.
 
<body> <div class="box box1"> box1_z-index: 10 </div> <div class="box box2"> box2_z-index: 9 <div class="children_box">z-index: 100</div> </div> </body>
 
그리고, css를 적용하면서  z-index를 적용해 주겠습니다. 이때, box1의 z-index를 10으로, box2는 9로, 마지막으로 box2의 자식 요소인 children_box의 값을 제일 큰 100으로 지정해 보겠습니다. 그렇다면 결과는 어떻게 나올까요? 위에서 설명한 것처럼 z-index는 큰 값을 갖는 요소가 위에 표시되므로 children_box요소가 가장 위에 표시될까요?
 
.box { width: 200px; height: 200px; position: relative; display: inline-block; } .box1 { background-color: rgba(255, 255, 0, 0.8); position: relative; z-index: 10; } .box2 { background-color: greenyellow; position: relative; right: 100px; z-index: 9; } /*z-index를 가장 큰값으로 지정*/ .box2 .children_box{ width: 80px; height: 80px; background-color: red; color: #fff; position: absolute; z-index: 100; }
 
예상과 달리, children_box는 box1요소 뒤에 보이게 됩니다. 이유는 children_box요소와 box1요소의 z-index비교 범위가 달라서입니다.
 
notion imagenotion image
 
children_box요소는 z-index가 9인 box2의 자식 요소로, children_box의 z-index값은 box2의 자식 요소들끼리 비교가 일어날 것입니다. 따라서 box1과는 비교 범위가 다른 것입니다.
💡
z-index를 사용하지 않았다고 가정했을 때, 요소들이 쌓이는 순서는 기본적으로 나중에 작성된 요소라고 설명을 하였지만, position속성값 여부에 따라 달라지기도 하며, 이 때 말하는 속성값은 static속성값을 제외한 나머지 속성값을 의미합니다. 나중에 작성된 요소가 있더라도 앞에 position속성이 적용된 요소가 있으면 나중에 작성된 요소보다 위에 쌓이게 됩니다.
따라서, z-index가 지정된 요소가 없을 경우 쌓이는 우선순위는 높은 순서대로 아래와 같이 적용됩니다.
 
notion imagenotion image
 
  • position속성값을 갖는 요소들 중에 나중에 작성된 순서
  • position속성값을 갖지 않는 요소들 중에 나중에 작성된 순서
  • root
 
편리하게 요소들의 쌓이는 순서를 조정할 수 있는 z-index지만, z-index를 남용하다 보면, 전체적인 구조 파악이 어려운 결과물을 만들어 낼 수 있으며, 나아가 유지 보수에도 어려움을 줄 수 있습니다. 요소들이 쌓이는 기본 순서와, 쌓임 맥락을 이해하여 적절하게 z-index를 사용한다면, 의도에 맞는 레이아웃을 만들어 가는 데 많은 도움이 될 것입니다.
마지막으로 지금까지 알아본 position속성을 이용하여 레이아웃을 만들어보는 실습을 해보겠습니다.
 
notion imagenotion image
 
레이아웃의 영역이 크게 2영역으로 나눠져있는 걸 볼 수 있습니다. 영역 별 성격을 임의로 생각하여 각각 <header>, <main>의 태그로 html을 작성하여 뼈대를 잡으면 될 것 같으며, 왼쪽 하단에는 스크롤이 발생해도 화면에 고정되는 버튼이 있는 것을 확인 할 수 있습니다.
위에서 살펴본 내용을 바탕으로 html을 작성해 봅시다!
 
<body> <header class="relative_header"> <h1 class="logo">로고영역</h1> <nav class="menu">메뉴 영역</nav> </header> <main> <div class="box">box1</div> <div class="box">box2</div> <button type="button" class="float_btn">float btn</button> </main> </body>
 
css작업을 시작하기 전에 요소들을 배치할 때 어떤 방법으로 배치할 것인지 간단하게 구상하여 봅시다. 이번 파트는 position파트이므로 position속성을 적극적으로 사용해 보면서 실습을 해봅시다!
<header>영역 내부 요소들을 position: absolute를 이용하여 배치가 가능해 보입니다. <header>가 부모 요소가 될 수 있도록 position: relative속성을 지정하겠습니다
또 한 왼쪽 하단 화면에 고정되는 <button>요소는 position: fixed를 사용하여 레이아웃을 완성해 보겠습니다.
 
/*기본 스타일*/ *{ box-sizing: border-box; margin: 0; padding: 0; } body { padding: 20px; height: 100%; } header{ width: 100%; padding: 20px; border-radius: 15px; background-color:#B2C7D3; margin-bottom: 20px; } .box { width: 100%; height: 350px; padding: 20px; margin-bottom: 20px; border-radius: 15px; background-color:#E0E0F9; } button { width: 120px; height: 120px; background-color: #D9D9D9; border-radius: 100%; border: none; box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.25); } /*position을 이용하여 레이아웃 배치*/ .relative_header { position: relative; } .menu { position: absolute; right: 20px; top: 50%; transform: translateY(-50%); } .float_btn { position: fixed; bottom: 20px; left: 20px; }