본문 바로가기

FrontEnd

[CSS] 레이아웃 Wrapper 만들기

반응형
웹 사이트는 콘텐츠를 쉽게 읽을 수 있는 너비로 감싸거나(wrapping) 포함(containing)해야 합니다.
이를 달성하기 위해 래퍼 또는 컨테이너라고 하는 것을 사용할 수 있습니다.
CSS에서 래퍼는 여러 방식으로 구현할 수 있으나, 이로 인해 몇 가지 문제가 발생할 수 있습니다.

이 기사에서는 CSS의 레이아웃 Wrapper, 동작 방식, 사용 방법 및 Wrapper를 사용하지 않는 경우에 대해 설명합니다.
이 기사 전체에서 래퍼와 컨테이너라는 용어를 언급할 수 있으며 둘 다 같은 의미입니다.


Wrapper에 대한 간단한 설명

래퍼 또는 컨테이너라는 용어는 요소 그룹이 다른 요소 안에 감싸져있거나 포함되어 있음을 의미합니다.
추가 요소를 사용하지 않고 아래와 같이 <body> 요소를 래퍼로 사용할 수 있습니다.

body {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

그러나 <body> 요소를 래퍼로 사용하는 것은 오늘날의 작업에는 실용적이지 않을 수 있습니다.
래퍼 요소는 하위 항목이 경계를 벗어나는 것을 방지할 수 있습니다. 다음 그림을 고려하십시오.

페이지 래퍼

우리는 aside, main 요소를 가지고 있으며 그것들을 감싸는 다른 요소 안에 있습니다.
 물론 .wrapper 요소 또한너비가 있습니다.

<div class="wrapper">
  <aside>...</aside>
  <main>...</main>
</div>

래퍼가 없으면 하위 요소가 화면 가장자리에 달라붙습니다.
이것은 특히 큰 화면에서 사용자에게 매우 성가실 수 있습니다.

화면 가장자리에 요소가 달라붙은 모습

위의 그림은 요소를 감싸는 요소가 없을 때 요소가 늘어나는 모습을 보여줍니다.


왜 페이지 Wrapper가 필수인가요?

페이지 래퍼를 사용할 때,
디자이너나 개발자가 알고 있어야 하는 많은 이점이 있습니다. 다음은 몇 가지 이점입니다.

  1. 콘텐츠의 가독성을 높입니다.
    • 래퍼가 없으면 텍스트 및 이미지와 같은 콘텐츠가 늘어나서 화면 전체 너비를 채울 수 있습니다.
    • 작은 화면의 경우 괜찮을 수 있습니다. 그러나 큰 화면의 경우 이는 매우 성가신 일입니다.
  2. 디자인 요소를 그룹화하는 것이 간격을 추가하는 데 더 좋습니다.
  3. 디자인 요소를 열로 나누는 작업은 래퍼 없이는 쉽게 수행할 수 없습니다.

CSS로 Wrapper 구현하기

이제 래퍼의 기본 사항과 이점을 이해했으므로,
CSS에서 래퍼를 빌드하는 방법을 살펴보겠습니다.

너비 추가하기

너비 추가

래퍼를 구현할 때 가장 먼저 결정해야 할 것은 너비입니다.
래퍼 너비를 어떻게 하시겠습니까? 당신의 디자인에 달려 있습니다만,
1000px - 1300px 사이 값이 가장 일반적으로 사용됩니다.
예를 들어 인기 있는 프레임워크 Bootstrap은 1170px의 너비를 사용합니다.
.wrapper {
  width: 1170px;
}

단, 화면 크기가 1170px 미만일 경우 가로 스크롤이 발생하므로 width 속성을 사용하지 않는 것이 좋습니다.
하지만 max-width를 추가하면 해결할 수 있습니다.

.wrapper {
  width: 1170px;
  max-width: 100%;
}

위의 코드는 동작하지만, 아래와 같이 최대 너비만 사용할 수도 있습니다.

.wrapper {
  max-width: 1170px;
}

 

래퍼의 너비를 추가했습니다. 센터링으로 넘어 갑시다.

Wrapper 중앙 정렬하기

래퍼를 중앙에 배치하려면 왼쪽, 오른쪽에 auto 여백을 추가해야 합니다.

래퍼를 중앙에 배치하려면 왼쪽, 오른쪽에 auto 여백을 추가해야 합니다.

.wrapper {
  max-width: 1170px;
  margin: 0 auto;
}
CSS 사양에 따르면 auto 마진(detailed article)이 작동하는 방식은 다음과 같습니다.
'margin-left'와 'margin-right'가 모두 'auto'이면 사용되는 값은 동일합니다.
컨테이닝 블록의 가장자리를 기준으로 요소를 가로로 중앙에 배치합니다.
저는 margin: 0 auto를 사용했습니다.
이것은 기본적으로 위쪽과 아래쪽의 여백을 0으로 재설정하고 왼쪽과 오른쪽 마진을 자동으로 만듭니다.
해당 방법은 해당 기사의 가장 마지막에서 자세히 다룹니다.
.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}

Wrapper 좌우 패딩

왼쪽과 오른쪽에 패딩

다음 고려해야 할 중요한 사항은 왼쪽과 오른쪽에 패딩을 추가하는 것입니다.
뷰포트 크기가 래퍼의 최대 너비보다 작으면 래퍼 가장자리가 뷰포트에 고정됩니다.

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}
패딩을 추가하면 뷰포트 크기가 최대 너비보다 작은 경우에도 왼쪽과 오른쪽에서 16px 오프셋이 있는지 확인할 수 있습니다.
패딩은 공간이 충분하지 않을 때 래퍼가 뷰포트 가장자리에 달라붙는 것을 방지하는 방어 전략 역할을 합니다.

패딩 대신 Wrapper의 퍼센티지 너비(Bad)

미디어 쿼리를 사용해 너비를 뷰포트의 퍼센티지로 적용할 수 있습니다.

미디어 쿼리를 사용해 너비를 뷰포트의 퍼센티지로 적용할 수 있습니다.

이는 효과가 있으나, 뷰포트 너비의 90%는 큰화면에선 너무 넓습니다.

미디어 쿼리를 활용해 큰 화면에선 max-width로 재정의할 수 있습니다.

.wrapper {
  max-width: 90%;
  margin-left: auto;
  margin-right: auto;
}

/* A media query for a large screen */
@media (min-width: 1170px) {
  .wrapper {
    max-width: 1170px;
  }
}

백분율 너비를 사용하여 미디어 쿼리를 사용하는 단계를 추가했습니다
고정 너비 값을 사용하면 이 단계가 필요 없습니다.
또 다른 솔루션은 width: 90%를 max-width: 1170px 속성과 결합하는 것입니다.

.wrapper {
  width: 90%;
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}

이는 흥미로운 접근 방식이지만 백분율 너비에 의존하는 대신 패딩을 직접 추가하는 것을 선호합니다.


Wrapper의 Display type 

래퍼는 <div>이므로 기본적으로 블록 수준 요소입니다.
문제는 래퍼 내부의 콘텐츠를 그리드에 배치해야 할 때 디스플레이 타입을 그리드로 변경하려면 어떻게 해야 하느냐입니다.

관심사 분리 개념에 위배되므로 권장하지 않습니다.
래퍼는 다른 내용을 래핑하기 위한 것입니다. 그게 전부입니다.
그리드 래퍼가 필요한 경우 래퍼 내부에 다른 <div>를 추가하세요
<div class="wrapper">
  <div class="featured-news">
    <!-- Elements that needs to be placed in a grid -->
  </div>
</div>
.featured-news {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 16px;
}

Wrapper 사이에 마진 추가하기

래퍼 요소를 중앙에 배치하기 위해 단축 버전을 사용하는 것을 권장하지 않습니다.

.wrapper {
  margin: 0 auto;
}
페이지에 래퍼가 여러 개 있고 래퍼 사이에 간격을 추가해야 하는 경우 혼란스러울 수 있습니다.
어떤 이유로 .wrapper에 다른 변형 클래스를 추가한 경우 특이도 때문에 마진 추가가 동작하지 않을 수 있습니다.
.wrapper-variation {
  margin-top: 50px;
}

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}​

.wrapper-variation 요소의 마진은 margin: 0 auto로 재정의되기 때문에 동작하지 않습니다.
즉, 속기 속성은 긴 속성을 재정의합니다.

이러한 혼동을 피하기 위해 이러한 경우에는 긴 이름을 사용하는 것이 좋습니다.

 

이제 마진을 추가해 보겠습니다.
각 프로젝트에서 마진과 패딩에 대한 유틸리티 클래스 세트를 준비하고 필요할 때 사용합니다.

<div class="wrapper mb-5"></div>
<section>
  <div class="wrapper"></div>
</section>
<div class="wrapper"></div>
.mb-5 {
  margin-bottom: 3rem !important;
}

유틸리티 클래스를 적용해 마진, 패딩 추가

이렇게 하면 단 한개의 Wrapper 클래스만 있으면 됩니다.

여기에서는 !important를 사용하는 것이 좋습니다.
유틸리티 클래스의 요점은 속성을 강제하는 것이고
!important를 추가하면 이를 보장할 수 있습니다.


전체 화면 섹션 내부의 Wrapper

뷰포트 너비 100%인 배경이 있는 섹션이 있고 그 안에 래퍼가 있는 경우가 있을 수 있습니다.

페이지 HTML 구조는 다음과 같을 수 있습니다.

<section>
  <div class="wrapper"></div>
</section>
<section>
  <div class="wrapper"></div>
</section>

<secion>은 뷰포트의 100% 너비를 갖습니다.

해당 섹션에 배경색이나 이미지를 추가할 수 있습니다.
내부에서 래퍼는 콘텐츠가 뷰포트의 전체 너비를 차지하는 것을 방지합니다.

내부에서 래퍼는 콘텐츠가 뷰포트의 전체 너비를 차지하는 것을 방지합니다.

위의 그림에서 섹션에는 배경 이미지가 있고 뷰포트의 전체 너비를 차지합니다.
내부 컨텐츠의 너비는 래퍼의 너비에 의해 제한됩니다.


Hero 섹션에 Wrapper가 필요할까요?

그때 그떄 다릅니다.

가장 일반적으로 사용되는 히어로 섹션 디자인을 살펴보겠습니다.

첫 번째 예시는 중앙에 콘텐츠가 있고 특정 너비로 ​​제한되는 경우입니다.

첫 번째 예시는 중앙에 콘텐츠가 있고 특정 너비로 ​​제한되는 경우입니다.

두 번째는 기본 래퍼 너비로 콘텐츠가 펼쳐져 있는 경우입니다.
두 패턴을 더 잘 이해하기 위해 각 패턴을 빌드하는 방법을 살펴보겠습니다.
두 패턴을 더 잘 이해하기 위해 각 패턴을 빌드하는 방법을 살펴보겠습니다.

중앙에 컨텐츠가 정렬된 Hero 영역

Wrapper 없이 모든 컨텐츠를 중앙에 배치하고 싶은 유혹을 느낄 수 있습니다.

<section class="hero">
  <h2>How to make bread at home</h2>
  <p>....</p>
  <p><a href="/sign-up">Sign up</a></p>
</section>
text-align을 사용하여 콘텐츠를 중앙에 배치할 수 있습니다.
.hero {
  text-align: center;
}
이는 브라우저 창의 크기를 조정할 때까지 별 문제가 없습니다.

모서리에 달라붙는 컨텐츠

왼쪽과 오른쪽에 패딩이 없기 때문에 적절한 간격이 없으면 콘텐츠가 가장자리에 붙습니다.
이는 가독성을 떨어뜨리므로 사용자에게 좋지 않습니다.

The Content Is Stick To The Edges.

큰 화면에서 너무 긴 한 줄 길이

큰 화면에서는 줄 길이가 너무 길어 단락 텍스트를 읽기가 매우 어려울 수 있습니다.
The Elements of Typographic Style Applied to the Web에 따르면 한 줄에 권장되는 문자 수는 45~75자입니다.
이 범위에서 벗어나면 읽기가 더 어려워집니다.
큰 화면에서 너무 긴 한 줄 길이

위의 문제를 피하기 위해 Wrapper를 사용하여 텍스트 길이가 너무 길어지는 것을 방지하고
모바일에서와 같은 작은 환경에서는 엣지와 컨텐츠 사이 간격을 추가할 수 있습니다.

<section class="hero">
  <div class="hero__wrapper">
    <h2>How to make bread at home</h2>
    <p>...</p>
    <p><a href="/sign-up">Sign up</a></p>
  </div>
</section>

이 hero__wrapper는 hero를 위하여 사용자 정의되어 있습니다.

일반적인 요소들보다 더 작은 너비를 가질 수 있씁니다.

.hero__wrapper {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

콘텐츠를 중앙에 배치하기 위해 사용 사례에 따라 여러 기술을 사용할 수 있습니다.
이 예에서는 text-align: center를 사용하면 충분합니다.


Wrapper를 중앙 정렬해야 하나요? 왼쪽 정렬해야 하나요?

랩탑 화면 중앙에 래퍼를 배치하고 데스크톱 크기에서는 왼쪽 정렬하는 웹사이트를 본 적이 있습니다.
Techcrunch 웹 사이트가 이에 대한 예입니다. 대형 화면에서 웹사이트가 어떻게 왼쪽 정렬되는지 보세요

개인적으로는 항상 중앙 정렬되는 레이아웃을 선호합니다.


Wrapper 변형에 CSS 변수 사용

한 가지 크기의 래퍼만 필요한 경우는 드뭅니다.
Wrapper 너비는 콘텐츠 및 사용 사례에 따라 작거나 클 수 있습니다.
<div class="wrapper"></div>
.wrapper {
  max-width: var(--wrapper-width, 1170px);
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

 

var에는 두 개의 값이 있습니다. 첫 번째 값은 --wrapper-width 변수이고 두 번째 값은 1170px입니다. 
두 번째 변수는 폴백입니다. 즉 --wrapper-width 변수의 값이 설정되지 않은 경우 두 번째 변수가 사용됩니다.

아래와 같이 --wrapper-width를 재정의하여 래퍼의 변형을 만들 수 있습니다.
<div class="wrapper" style="--wrapper-width: 720px"></div>
  • 새 클래스 추가가 필요없습니다.
  • 스타일 복사가 필요없습니다.
  • devtool에서 값을 쉽게 변경할 수 있습니다.
CSS 변수를 재정의하기 위해 인라인 스타일을 추가하는 솔루션이 마음에 들지 않으면 대신 새 클래스를 추가할 수 있습니다.
<div class="wrapper wrapper--small"></div>
.wrapper--small {
  --wrapper-width: 720px;
  /* this will override the default wrapper width. */
}

 

 


CSS Display: Contents 사용

CSS의 각 요소는 상자이며 해당 상자에는 콘텐츠, 패딩, 마진 및 테두리가 포함됩니다.

 display: contents를 사용하면 해당 상자가 흐름에서 제거됩니다.

주변 여는 태그와 닫는 태그를 제거하는 것으로 상상할 수 있습니다.

<header class="site-header">
    <div class="wrapper site-header__wrapper">
            <!-- Header content -->
    </div>
</header>
.site-header__wrapper {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

display: contents를 사용하면 해당 상자가 흐름에서 제거됩니다.

이렇게 하면 .wrapper 요소가 없는 것처럼 됩니다.
즉, display: flex가 .site-header 요소에 적용되면 .wrapper의 하위 항목은 .site-header의 하위 항목이 됩니다.

.site-header__wrapper {
  display: contents;
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.site-header.내부 컨텐츠는 전체 너비를 차지합니다.


유동적인 배경, 고정된 컨텐츠

그녀의 CSS Secrets 책에서 Lea Verou는
내부에 래퍼가 있는 유동적인 배경(전체 뷰포트 너비 사용)이 있는 섹션에 사용할 수 있는 흥미로운 기술을 소개했습니다.
일반적인 방법을 검토해 보겠습니다.

<section>
  <div class="wrapper"></div>
</section>
section {
  background-color: #ccc;
}

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

margin-left: auto 및 margin-right: auto는 뷰포트 너비의 절반에서 콘텐츠 너비를 뺀 값을 계산하는 방식으로 동작합니다.
패딩을 사용하여 동일한 작업을 수행할 수 있습니다.

section {
  padding: 1rem calc(50% - 585px);
}
아직 끝나지 않았습니다. 콘텐츠는 모바일에서 가장자리에 고정됩니다. 이에 대한 해결책은 다음과 같습니다.
section {
  padding: 1rem;
}

@media (min-width: 1170px) {
  section {
    padding: 1rem calc(50% - 585px);
  }
}

대체 솔루션은 새로운 CSS max() 함수를 사용하는 것입니다.
간단히 최소 패딩을 1rem으로 설정하고 50% - 585px 계산을 다른 값으로 사용할 수 있습니다.

section {
  padding: 1rem max(1rem, (50% - 585px));
}
min(), max() 및 clamp()에 대해 자세히 알고 싶다면 해당 기사(detailed)를 참고하세요

참고

 

반응형