【CSS】 width: auto와 height: auto 당신이 몰랐던 작동 원리

width: auto와 height: auto

[ CSS 목록 보기 ]

widthheight는 CSS에서 정말로 많이 쓰이고, 그래서 매우 익숙한 프로퍼티 중에 하나입니다. 하지만 이러한 익숙함에 비해서, 속성값 auto에 대해서는 크게 다뤄지지는 않은듯싶습니다. auto에 대해 한 번쯤 생각해 보지 않으면, 그로 인한 이해 부재로 CSS가 깨지는 경우가 발생합니다. 따라서 이번 포스트에서는 width와 height의 기본속성 auto의 메커니즘을 이해하고, 우리가 오해하고 있었던 건 없는지에 대해 알아보겠습니다.

혹시 독자 중에 “저는 width나 height에 auto로 설정 안 하는데요?”라고 반문하시는 사람도 있을진 모르겠지만, 아래와 같이 width와 height를 설정하지 않았을 때, 기본적으로 auto 속성값이 들어갑니다. 따라서 이번 포스트에서 다루는 내용은 모든 사람들이 경험하게 되는 문제이기 때문에 매우 중요하고, 잘못 이해하고 있다면 잠재적으로 CSS 오류를 발생시키게 될 뿐만 아니라, 또 디버깅하는데 시간이 오래 걸리기 때문에 반드시 이해하고 넘어가야 합니다.

1
2
3
4
선택자 {
 
 
}
cs
=
1
2
3
4
선택자 {
  width: auto;
  height: auto;
}
cs
차례
[1] Inline-Block과 Block 요소에서 width: auto와 height: auto의 의미
  [1.1] Inline-Block
    [1.1.1] Inline-Block에서 width: auto와 height: auto의 의미
    [1.1.2] 딜레마 문제: 부모의 width: auto와 자식의 width: 100%
  [1.2] Block
    [1.2.1] Block 요소에서 width: auto와 height: auto의 의미
    [1.2.2] Block 요소의 작동 원리
    [1.2.3] Block의 width: auto는 width:100%가 아니다.
[2] 부모요소가 height: auto이면, 자식요소의 top: %는 사용할 수 없다.
[3] 위치속성과 transform의 차이점
[4] 정리

1. Inline-Block과 Block 요소에서 width: auto와 height: auto의 의미

inline-block 요소에서 width: auto와 height: auto는 내용물의 크기에 맞혀 자동 크기 조절의 의미를 가집니다. 하지만 block 요소에서는 내용물에 맞게 크기가 자동 조절되지 않음을 볼 수 있는데요, 어떠한 메커니즘으로 작동하는지 이번 섹션에서 알아보겠습니다. 참고로 inline 요소를 고려하지 않는 이유는, inline 요소 경우에는 크기 속성(width와 height)을 설정할 수 없기 때문입니다. inline 요소의 크기를 설정할 수 없게 디자인 된 이유는 줄의 개념을 이해할 필요가 있습니다. 관련 부분이 궁금하신 분은 [CSS] 줄의 개념 포스트에서 inline 요소 안의 줄을 읽어봐주시기 바랍니다.

[1.1] Inline-Block

[1.1.1] Inline-Block에서 width: auto와 height: auto의 의미

inline-block 요소에서의 auto 의미는 자식 요소들 크기에 자동으로 맞춤하라는 것입니다. 여기서 크기란 margin + border + padding + width 또는 height를 의미합니다.

<style>
    .wrapper {
        margin: 0 auto;
        width: 100px; height: 100px;
        border: 1px solid darkblue;
        background-color: lightblue;
    }
    .target {
        border: 1px dashed red;
        display: inline-block;
    }
    .child {
        width: 70px; height: 22px;
        background-color: lightpink;
        font-size: 15px;
        line-height: 22px;
        text-align: center;
    }
</style>
<div class=“wrapper”>
    <div class=“target”>
        <div class=“child”>자식요소</div>
    </div>
</div>
자식요소
  • 목표
    • inline-block 요소에 width: auto와 height: auto가 설정되면, 너비와 높이가 어떻게 적용되는지 확인해 보겠습니다.
  • 코드 분석
    • HTML 코드
      • 먼저 코드 아래에 위치한 HTML 파트를 보겠습니다.
      • <div class=”wrapper”></div>
        • 래퍼 요소(div.wrapper)를 먼저 작성하고, 그 안에 원하는 HTML을 넣어줍니다. 래퍼를 활용하면, 복잡한 코드에서도 요소들을 정렬하는데 편리해집니다. 래퍼에 관한 내용은 [CSS] Wrapper 포스트를 참조해 주시기 바랍니다.
      • <div class=”target”></div>
        • 래퍼 요소 안에 타겟 요소(div.target)를 작성해 주었습니다. 이 타겟 요소를 inline-block을 설정할 예정인데, 자식 요소를 어떻게 감싸는지 확인해 보겠습니다.
      • <div class=”child”>자식요소</div>
        • 타겟 요소 안에 자식 요소(div.child)를 작성해 주었습니다. 그리고 그 안에 “자식요소”라는 글자는 넣었습니다.
    • CSS 코드
      • .wrapper의 CSS
        • margin: 0 auto; 래퍼 요소를 가로 가운데 정렬을 합니다. 2번째 값으로 auto를 넣었는데, auto의 의미는 좌/우 여백의 크기를 같게 설정하라는 것입니다. 결과적으로 래퍼 요소는 가운데 정렬을 하게 됩니다.
        • width: 100px; height: 100px; 래퍼 요소의 크기를 100 x 100 px로 설정합니다.
        • border: 1px solid darkblue; 래퍼 요소의 테두리선을 1px 두께의 파란 실선으로 표시합니다.
        • background-color: lightblue; 래퍼 요소의 배경색을 하늘색으로 설정합니다.
      • .target의 CSS
        • border: 1px dashed red; 타겟 요소의 테두리선을 1px 두께의 빨간 점선으로 표시합니다.
        • display: inline-block; 타겟 요소를 inline-block 형식으로 설정합니다. inline-block으로 설정된 타겟 요소의 크기가 어떻게 설정되는지 관찰합니다.
        • width: auto; height: auto; 위 코드에는 없지만, width와 height의 기본값이 auto이기 때문에 따로 작성하지 않아도 width: auto와 height: auto와 동일한 결과가 나옵니다.
      • .child의 CSS
        • width: 70px height: 22px; 자식 요소의 크기를 70 x 22 px로 설정합니다.
        • background-color: lightpink; 자식 요소의 배경색을 밝은 핑크색으로 설정합니다.
        • font-size: 15px; 자식 요소의 글자 크기를 15px로 설정합니다.
        • line-height: 22px; 줄의 높이를 22px로 설정해 줍니다. 줄의 높이를 height (22px)와 같게 만들어 줌으로써 글자를 세로 가운데로 정렬시킬 수 있습니다. 글자를 세로 가운데로 정렬은 따로 프로퍼티가 존재하지 않기 때문에 몇 가지 트릭으로 구현해야 합니다. 관련된 자세한 내용은 [CSS] 글자 세로 가운데 정렬하기 포스트에서 다루고 있습니다.
        • text-align: center; 글자를 세로 가운데로 정렬하는 방법이 어렵다고 했지만, 가로 방향으로의 정렬은 쉽게 할 수 있습니다. text-align 프로퍼티 값을 center로 설정해주기만 하면 가로 가운데 정렬이 됩니다.
  • 구현 결과
    • inline-block인 타겟요소(div.target)의 테두리선(빨간 점선)을 보면, 자식요소(div.child)의 크기에 맞춰 자동적으로 height와 width를 조절한 것을 확인할 수 있습니다. 이와 같이 inline-block 요소에서 width: auto와 height: auto의 의미는 자식 요소에 크기 자동 맞춤으로 이해할 수 있다.
  • TIP
    • 내용물의 크기에 딱 맞는 div 박스를 만들고 싶을 땐, inline-block 설정을 해주면 된다는 것을 팁으로 기억해 두시면 좋습니다.

[1.1.2] 딜레마 문제

width: auto와 width: 100%의 의미를 집어볼 겸 재밌는 문제를 한번 생각해 보겠습니다. inline-block의 width: auto자식 요소의 크기를 기준으로 너비를 설정하는 반면, width: 100%부모 요소의 크기를 기준으로 너비를 설정합니다. 그렇다면 부모 요소(inline-block)에 width: auto를 설정하고, 자식 요소에 width: 100%를 설정하면 어떻게 될까요? 서로의 크기를 기준으로 잡기 때문에, 약간의 딜레마 같은 문제가 발생할 수 있습니다.

<style>
    .parent {
        width: auto;
        display: inline-block;
        border: 2px solid black;
        background-color: lightblue;
    }
    .child {
        width: 100%;
        border: 1px dashed red;
        margin: 0 10px;
        height: 40px;
    }
</style>
<div class=“parent”>
    <div class=“child”></div>
</div>
  • 목표
    • 부모 요소(inline-block)에 width: auto로 설정하고, 자식 요소에 width: 100%로 설정할 때, 각각의 너비는 어떻게 설정하는지 알아보겠습니다. 앞에서 말씀드린 것처럼, width: auto는 자식 요소의 크기를 기준으로 너비를 설정하는 반면, width: 100%는 부모 요소의 크기를 기준으로 너비를 설정하기 때문에, 이런 설정에는 딜레마가 발생합니다. 이런 경우 CSS는 어떻게 계산하는지 확인해 보겠습니다.
  • 코드 분석
    • HTML 코드
      • 먼저 코드 아래에 위치한 HTML 파트부터 보겠습니다.
      • <div class=”parent”> <div class=”child”> </div> </div>
        • 부모 요소인 div.parent를 생성하고, 그 안에 자식 요소인 div.child를 생성합니다.
    • CSS 코드
      • .parent의 CSS
        • width: auto; 부모 요소인 div.parent의 width를 auto로 설정합니다. width: auto로 설정하면, 자식 요소 크기를 기준으로 같은 너비가 할당됩니다.
      • .child의 CSS
        • width: 100%; 자식 요소인 div.child의 width를 100%로 설정하여, 부모 요소 크기를 기준으로 동일한 너비로 설정합니다.
  • 구현 결과
    • 부모 요소(div.parent)의 width가 22px로 설정되었고, 자식 요소(div.child)의 width도 22px로 설정된 것을 확인할 수 있습니다. 이렇게 설정된 메커니즘을 이해하기 위해서는 CSS 속성 적용이 Top-down 방식, 즉 부모에서 자식 방향으로 적용되어진다는 것을 알고 있어야 합니다.
    •  먼저 부모 요소의 width: auto를 결정하기 위해서는 자식 요소의 크기를 계산해야 되는데, 자식 요소 div.child의 총 크기는 2px (좌/우 border) + 20px (좌/우 margin) + 0px (padding) + 100% (width) = 22px + 100% 입니다. 여기서 딜레마는 100%를 어떻게 계산하는가 입니다. 계산하는 시점에 부모 요소의 width는 auto로 설정되어져 있기 때문에 0으로 처리되어서, 총 크기는 22px이 됩니다. 따라서 부모 요소의 width = 22px로 설정되어집니다.
    •  다음으로 자식 요소의 CSS 속성들이 적용됩니다. 자식 요소 div.child의 width는 100%로 설정되어져 있기 때문에, 부모 요소의 width 22px를 적용받게 되어서, 동일한 값이 22px가 설정되어집니다. 실제로 이런 코드를 작성할 일이 많지는 않겠지만, 작동 원리를 알 수 있는 재밌는 문제라서 소개합니다.

[1.2] Block

block 요소는 inline 요소와 다르게 작동하는데, width: auto와 height: auto를 분리해서 생각해야 합니다. block 요소의 height: auto는 inline-block과 마찬가지로 자식 요소 크기를 기준으로 설정하지만, width: auto의 경우에는 부모 요소 크기를 기준으로 설정합니다. width: auto의 경우, 부모 요소의 크기와 동일하게 설정되기 때문에 width: 100%로 설정된다고 생각하실 수도 있는데, 사실은 잘못된 생각입니다. 정확히 말해서는 width = 100% – margin(좌/우)으로 설정됩니다. block 요소들의 [1.2.1] width: auto와 height: auto의 의미와 [1.2.2] 작동원리, 그리고 [1.2.3] width: auto는 width: 100%와 어떻게 다른지를 아래에서 알아보겠습니다.

[1.2.1] Block 요소에서 width: auto와 height: auto의 의미

<style>
    .wrapper {
        margin: 0 auto;
        width: 100px; height: 100px;
        border: 1px solid darkblue;
        background-color: lightblue;
    }
    .target {
        border: 1px dashed red;
        display: block;
    }
    .child {
        width: 70px; height: 22px;
        background-color: lightpink;
        font-size: 15px;
        line-height: 22px;
        text-align: center;
    }
</style>
<div class=“wrapper”>
    <div class=“target”>
        <div class=“child”>자식요소</div>
    </div>
</div>
자식요소
  • 목표
    • block 요소에 width: auto와 height: auto를 적용하면, 자식요소 크기에 대비해서 어떻게 설정되는지 확인해 보겠습니다.
  • 코드 분석
    • HTML 코드
      • [1.1] 예제와 동일한 코드에 대한 중복 설명은 생략하겠습니다.
    • CSS 코드
      • [1.1] 예제와 동일한 부분의 설명은 생략하였습니다.
      • .target의 CSS
        • display: block; [1.1] 예제에서는 inline-block으로 설정하였지만, 여기에서는 div.target 요소를 block 형식으로 설정합니다. div는 기본적으로 block 형식을 가지고 있기 때문에 따로 display: block을 지정할 필요가 없기는 하지만, 명확한 설명을 위해서 넣어 주었습니다. 타겟 요소(div.target)의 크기가 자식 요소 div.child의 크기에 대비해서 어떻게 설정되는지 관찰해 보겠습니다.
  • 구현 결과
    • 타겟 요소(div.target)의 테두리선(빨간 점선)과 자식요소(div.child)의 크기를 비교함으로써, block 요소에서 width: auto와 height: auto가 어떻게 설정되는지 확인해 보겠습니다.
    • (1) 먼저 높이의 경우, 타겟 요소의 높이는 자식 요소의 높이만큼 크기 자동 조절되었음을 확인할 수 있습니다. inline-block 요소와 동일하게, block 요소의 height: auto는 자식 요소의 높이에 자동 맞춤임을 알 수 있습니다.
    • (2) 반면, 너비의 경우, 자식 요소의 너비만큼 크기 자동 조절된 것이 아니라, 한 줄을 다 차지하고 있음을 확인할 수 있습니다. inline-block 요소와는 대조적으로, block의 width: auto는 한 줄을 다 차지하게 설정하라는 의미입니다. 한 줄을 다 차지하라는 의미는 타겟 요소의 width를 부모 요소(div.wrapper)의 width와 동일하게 설정하라는 의미로 생각할 수 있습니다. 아래는 추가적으로 부모 요소인 div.wrapper의 width를 다르게 설정했을 때의 결과입니다. 결과에서 볼 수 있듯이, block 요소는 자식 요소의 크기에 상관없이 부모 요소의 너비와 동일하게 설정됩니다.

[1.2.2] Block 요소의 작동 원리

  • block 요소의 동작 방식을 inline-block 요소와 다르게 만든 이유는 무엇일까요?
    • 그 이유는 block과 inline 형식의 출생의 비밀(?)이 다르기 때문입니다.
    • (1) inline-block은 inline 형식을 따르게 되는데, inline 요소의 기본 존재 목적은 줄(line)입니다. 줄 안에서 글자를 입력하게 되면 글자들은 옆으로 나열됩니다. 이와 유사하게, (아래 그림 왼쪽) 여러 개의 inline 요소(span 요소)들을 생성하면, 마치 줄 안에 글자를 입력하듯이 옆으로 나열됩니다. 이를 위해 inline 요소의 크기도 내용물에 맞게 자동으로 조절합니다.
    • (2) block 요소는 아래 그림 오른쪽처럼 요소들을 세로 방향으로 정렬시키기 위해 만들어졌습니다. 그렇다면 CSS는 어떻게 요소들을 세로방향으로 쌓이게 만들 수 있을까요? 다음 카드에서 block 요소들의 동작 원리에 대해서 알아보겠습니다.
SPAN 1 SPAN 2 SPAN 3
←옆으로 나열→
BLOCK 1
BLOCK 2
BLOCK 3
밑으로 쌓임
<style>
    .wrapper {
        margin: 0 auto;
        width: 100px; height: 100px;
        border: 1px solid darkblue;
        background-color: lightblue;
    }
    .target {
        border: 1px dashed red;
        height: 22px;
        
        width: 20%;
        margin-left: 10%;
        margin-right: 10%;
    }
</style>
<div class=“wrapper”>
    <div class=“target”></div>
    <div class=“target”></div>
</div>
  • 목표
    • CSS가 block 요소를 세로 방향으로 쌓기 위해 취한 방법에 대해 알아보겠습니다. 결과부터 말씀드리면, CSS는 block 요소를 세로 방향으로 쌓이게 하기 위해서 “width + margin(좌/우) = 100%”의 공식을 강제합니다. 만약 사용자가 임의로 width와 margin(좌/우)을 100% 보다 작게 설정하게 된다면, CSS는 오른쪽 여백(margin-right)을 조절하여 100%로 만들어 버립니다.
  • 코드 분석
    • HTML 코드
      • 먼저 코드 아래에 위치한 HTML 파트를 보겠습니다.
      • <div class=”wrapper”></div>
        • 래퍼 요소 div.wrapper를 먼저 만들어 주었습니다. 그리고 래퍼 요소 안에 원하는 HTML들을 넣어 주게 되면 정렬면에서 편리해집니다. CSS 래퍼 포스트에서 자세히 설명하고 있습니다.
      • <div class=”target”></div>
        <div class=”target”></div>
        • 래퍼 요소 안에 div.target 요소를 2개 만들어 주었습니다. CSS 파트에서 타겟 요소들의 width와 margin을 설정하여, width + margin 합이 50% 보다 작아지게 만들 것입니다. 총 너비가 50% 작기 때문에 두 타겟 요소는 한 줄에 나란히 나열되어야 할 것 같지만, 실제 결과는 위 아래로 쌓이게 됩니다. 자세한 내용은 아래에서 설명드리겠습니다.
    • CSS 코드
      • .wrapper의 CSS
        • 관련 설명은 앞 예제들에서 했으므로 생략하겠습니다.
      • .traget의 CSS
        • border: 1px dashed red; div.target 요소의 테두리선을 1px 빨간 점선으로 설정합니다.
        • height: 22px; div.target의 높이를 22px로 설정합니다.
        • width: 20%; div.target의 너비를 20%로 설정합니다.
        • margin-left: 10%; div.target의 왼쪽 여백을 10%로 설정합니다.
        • margin-right: 10%; div.target의 오른쪽 여백을 10%로 설정합니다.
  • 구현 결과
    • 결과에서 빨간 점선이 타겟 요소(div.target)에 해당합니다. 높이가 22px로 설정되고, 너비가 부모 요소(div.wrapper)의 20%로 설정되었음을 확인할 수 있습니다. 그리고 왼쪽 margin이 부모 요소 div.wrapper의 10%로 설정되어져 있음을 확인할 수 있습니다. 여기까지는 예상에 부합합니다.
    •  만약 오른쪽 margin이 10%로 설정되어져 있다면, 하나의 타겟 요소가 차지하는 총 공간은 20% (width) + 10% (margin-left) + 10% (margin-right) = 40%가 됩니다. 이처럼 두 타겟 요소가 차지하는 공간이 80%가 되기 때문에, 두 타겟 요소는 한 줄에 나란히 배열되어야만 합니다. 하지만, 실제 결과에서는 두 타겟 요소가 서로 다른 줄에 위치한 것을 확인할 수 있습니다. 이는 앞에서도 설명드렸지만, block 형식은 요소들을 위 아래로 쌓이게 하기 위해서 디자인되었기 때문입니다. 이를 구현하기 위해 CSS는 width + margin(좌/우) = 100%를 강제하게 디자인되었고, 우리가 임의로 width와 margin을 작게 설정하더라도, CSS는 오른쪽 margin을 조절하여 총 합을 100%로 맞추어 버립니다. 위 결과를 보면 핑크색으로 표시된 부분이 margin에 해당하는데 (코드에는 없지만 이해를 돕고자 넣었습니다), 오른쪽 margin은 10%가 아니라 나머지 여백인 70%로 설정됐음을 확인할 수 있습니다. 즉, 총 합이 20% (width) + 10% (margin-left) + 70% (margin-right)가 되어 100%를 달성하게 됩니다. 따라서 첫 번째 타겟 요소는 한 줄을 다 채우게 되고, 두 번째 타겟 요소는 다음 줄에 위치하게 됩니다. 이것에 block 요소가 세로 방향으로 쌓이게 되는 작동 원리 입니다.
<style>
    .parent {
        width: 100px; height: 100px;
        border: 2px solid black;
        background-color: lightblue;
    }
    .target {
        border: 1px dashed red;
    }
</style>
<div class=“parent”>
    <div class=“target”></div>
</div>
  • 목표
    • 내용물(자식요소)이 없는 요소를 만들게 되면, 이 요소는 내용물이 없으므로 크기가 0이 되어야 합니다. 하지만 block 요소의 width = 100% – 좌/우 margin으로 설정되기 때문에 한 줄을 다 채우는 테두리선이 나오게 됩니다.
  • 코드 분석
    • HTML 파트
      • <div class=”parent”> <div class=”target”></div> </div>
        • 먼저 코드 아래에 위치한 HTML 파트부터 보면, div.parent 요소안에 타겟 요소 div.target을 넣었습니다. 여기서 타겟 요소안에는 아무 내용물도 넣지 않았음을 기억해 주세요.
    • CSS 파트
      • .parent의 CSS
        • width: 100px; height: 100px; div.parent의 크기를 100x100px로 설정해줍니다.
        • border: 2px solid black; div.parent의 테두리선을 1px 검정 실선으로 설정해줍니다.
        • background-color: lightblue; div.parent의 배경 색깔을 하늘색으로 설정합니다.
      • .target의 CSS
        • border: 1px dashed red; div.target의 테두리선을 1px 두께의 빨간 점선으로 설정합니다. div.target에 내용물을 넣지 않았기 때문에 크기가 0x0 px로 나와야 할 것 같지만, width: 100%로 설정되는 것을 결과에서 확인해보겠습니다.
  • 구현 결과
    • div.target 요소에 내용물이 없음에도 불구하고 빨간 점선이 나타납니다. 신기하지 않습니까? 내용물에 상관없이 block 요소들은 무조건 한 줄을 다 차지하게 디자인되었고, 이를 위해 width + 좌/우 margin = 100%가 되도록 강제되었습니다. 강제되었다고 표현한 이유는 사용자가 임의로 width와 좌/우 margin의 합이 100%가 되지 않게 설정하게 되더라도, CSS는 margin을 조절하여 100%가 되게 설정합니다.
  • TIP
    • block 요소들은 width: auto로 내용물을 크기를 둘러싼 박스를 만들 수 없습니다. 만약 block 요소를 내용물을 둘러싸게 만들고 싶다면, (1) dispaly: inline-block으로 설정하거나, (2) position: absolute를 이용하는 방법, (3) display: flex, 또는 (4) display: float을 사용할 수 있습니다.

[1.2.3] Block의 width: auto는 width: 100%가 아니다.

Block 요소들은 한 줄을 다 채우면서 세로 방향으로 나열하게 되는데, 이러한 성질 때문에 width: auto를 width: 100%로 이해하는 경향이 생깁니다. 하지만, 정확히 말해서 width: auto는 width: 100%가 아니라 width = 100% – margin(좌/우) 입니다. 아래 예제에서는 (1) block 요소가 세로 방향으로 쌓이는 작동 원리(2) width: auto는 width: 100%와 왜 다른지 알아보겠습니다.

<style>
    .wrapper {
        margin: 0 auto;
        width: 100px; height: 100px;
 
        border: 1px solid darkblue;
        background-color: lightblue;
    }
    .target{
        border: 1px dashed red;
        height: 22px;
        color: red;
        font-size: 15px;
        line-height: 22px;
        text-align: center;
 
        width: auto;
        margin-left: 10%;
        margin-right: 10%;
    }
</style>
<div class=“wrapper”>
    <div class=“target”>타겟요소</div>
</div>
타겟요소
  • 목표
    • block 요소에서 width: auto는 width: 100%가 아니라, width: 100% – margin(좌/우) 임을 확인해 보겠습니다.
  • 코드 분석
    • HTML 코드
      • 먼저 코드 아래에 위치한 HTML 파트부터 보겠습니다.
      • <div class=”wrapper”> <div class=”target”> 타겟요소 </div> </div>
        • 래퍼 요소를 만들고, 그 안에 타겟 요소 div.target을 생성합니다. 타겟 요소 안에 “타겟요소”라는 글자를 넣었습니다.
    • CSS 코드
      • .wrapper의 CSS
        • 앞 예제들과 동일하여, 중복 설명은 생략합니다.
      • .target의 CSS
        • 앞 예제들과 동일한 부분은 중복 설명이므로 생략합니다.
        • width: auto; div.target의 width를 auto로 설정합니다. 이번 예제에서는 block 요소에 width: auto가 설정되었을 때, width에 실제로 어떤 수치가 들어가는지 확인할 예정입니다.
        • margin-left: 10%; div.target의 왼쪽 여백을 10%로 설정했습니다. 이는 부모 요소인 div.wrapper의 width 대비 10%에 해당합니다.
        • margin-right: 10%; div.target의 오른쪽 여백을 10%로 설정했습니다. 이는 부모 요소인 div.wrapper의 width 대비 10%에 해당합니다.
  • 구현 결과
    • 위 구현 결과를 보면, 타겟요소(빨간 점선 박스)의 좌/우로 여백 10%가 들어가 있음을 확인할 수 있습니다. 그리고 이 여백을 제외한 나머지 공간이 타겟요소의 width에 해당함을 확인할 수 있습니다. 이를 수식으로 표현하자면 width = 100% – margin(좌/우)가 됩니다. 이처럼 margin(좌/우)을 고려 해야하기 때문에 width: auto는 width: 100%와 다릅니다. 뭐 당연한 이야기를 하냐고 생각하시겠지만, (실제로도 당연한 이야기지만) 아래 예제를 보시면 저의 의도가 조금이나마 더 명확하게 와닿으실 겁니다.
    •  만약 위 코드 .target CSS에 설정된 width: auto를 width: 100%로 바꿔서 출력하면 아래와 같이 나옵니다. 타겟 요소의 왼쪽 여백은 10%로 설정된 것을 볼 수 있고, width는 부모 요소인 div.wrapper의 100%로 설정되어서 div.wrapper를 벗어난 것을 확인할 수 있습니다. CSS는 width + margin = 100% 공식을 강제하기 때문에, (width 100% + margin-left 10% = 110% 이므로) margin-right를 자동으로 -10%로 설정해서 총 합이 100%가 되게 만듭니다. 이와 같이 width: 100%는 width: auto와 전혀 다른 결과가 출력됩니다.
타겟요소

2. 부모요소가 height: auto이면, 자식요소의 top: %는 사용할 수 없다.

이 부분이 많이 헷갈리는 부분입니다. 만약 부모 요소의 width와 height가 auto로 지정되어 있을 때, 자식 요소의 위치속성(left, right, top, bottom)을 %로 지정하게 되면, left와 right는 제대로 동작하지만 top과 bottom은 동작하지 않습니다. 위치 속성을 %값으로 지정하면, 부모 요소의 크기를 기준으로 %를 계산하게 되는데, 부모 요소의 크기가 auto로 설정되어져 있기 때문에 계산에 문제점들이 발생합니다. 만약 상대값(%)이 아니라 절대값(px)로 설정하게 되면, 부모의 크기에 상관없이 움직일 수 있으므로 정상적으로 작동합니다.

<style>
    .wrapper {
        margin: 0 auto;
        max-width: 1180px;
 
        width: 100px; height: 100px;
        background-color: lightblue;
        border: 2px solid black;
    }
    .parent {
        border: 1px dashed red;
    }
    .child {
        background-color: lightpink;
        width: 70px; height: 22px;
 
        font-size: 15px; line-height: 22px;
        text-align: center;
 
        position: relative;
        left: 50%;
        top: 50%;
    }
</style>
<div class=“wrapper”>
    <div class=“parent”>
        <div class=“child”>자식요소</div>
    </div>
</div>
자식요소
이동→

이동X
  • 구현 목표
    • 부모 요소의 width와 height가 auto로 설정되어져 있을 때, 자식 요소의 위치 속성(left, right, top, bottom)이 어떻게 적용되는지 확인해 봅니다. 결과를 먼저 말씀드리면, 부모 요소에 width: auto와 height: auto가 설정되어져 있을 경우, 자식 요소의 left와 right는 제대로 작동하지만, top과 bottom은 작동하지 않습니다.
  • 코드 분석
    • HTML 코드
      • 먼저 코드 아래 부분에 위치하고 있는 HTML 파트를 보겠습니다.
      • <div class=”wrapper”></div>
        • 여기서는 래퍼 요소 div.wrapper를 먼저 만들어 주는데, 래퍼 요소 안에 원하는 HTML들을 넣어 주게 되면 정렬면에서 편리해집니다. CSS 래퍼 포스트에서 자세히 설명하고 있습니다.
      • <div class=”parent”> <div class=”child”> </div> </div>
        • 래퍼 요소(div.wrapper) 안에 원하는 HTML 파트를 작성해 보겠습니다. 먼저 부모 요소 div.parent를 만들고 그 안에 자식 요소 div.child를 만듭니다. 아래 CSS 코드에서 부모 요소에 width: auto, height: auto를 적용하고, 자식 요소를 left와 top으로 옮겼을 때 어떻게 작동하는지 확인해 볼 예정입니다.
    • CSS 코드
      • .wrapper의 CSS
        • margin: 0 auto; margin에 2개의 값을 설정하였는데, 첫 번째 값은 위/아래 여백에 해당하고, 두 번째 값은 좌/우 여백에 해당합니다. 여기서 auto의 의미는 좌/우 여백을 동일하게 설정하라는 의미입니다. 결론적으로 div.wrapper는 가로 방향 가운데로 정렬하게 됩니다.
        • max-width: 1180px; 최대 너비를 1180px로 설정합니다. 이렇게 설정하는 이유는, 매우 넓은 디바이스나 모니터에서 결과를 출력하게 될 때 div.wrapper는 무한정 옆으로 늘어나게 될 것입니다. 이 경우에는 사람의 눈이 인지할 수 있는 너비를 넘어서게 되고, 가독성이 크게 떨어지게 됩니다. 이를 방지하기 위해 1180px 이상으로 늘어나지 않게 합니다. margin과 max-width는 래퍼 요소에 설정하는 기본 프로퍼티 중에 하나인데, 어떤 다른 프로퍼티들을 래퍼에 설정하는지가 궁금하시다면 CSS 래퍼 포스트를 참조하시길 바랍니다.
        • width: 100px; height: 100px; div.wrapper의 크기를 100x100px로 설정합니다.
        • background-color: lightblue; 배경색을 하늘색으로 설정합니다.
        • border: 2px solid black; 테두리선을 2px 두께의 검정 실선으로 설정합니다.
      • .parent의 CSS
        • border: 1px dashed red; div.parent의 테두리선을 1px 두께의 빨간 점선으로 설정하여 시각화 시킵니다. 이 점선 테두리 대비하여 자식 요소 div.child가 어떻게 움직이는지 확인할 예정입니다.
        • width: auto; height: auto; 위 코드에서는 적혀 있진 않지만, width와 height의 기본값이 auto이기 때문에 이렇게 설정된 것과 동일한 결과가 나옵니다.
      • .child의 CSS
        • background-color: lightpink; div.child의 배경색을 핑크색으로 설정합니다.
        • width: 70px; height: 22px; div.child의 크기를 70 x 22 px로 설정합니다.
        • font-size: 15px; line-height: 22px; div.child의 글자 크기를 15px로 설정하고, 줄 높이를 22px로 설정합니다. 줄 높이를 22px로 설정하는 이유는, 줄의 높이를 div.child의 height인 22px로 같게 설정함으로써 글자를 세로 가운데 정렬할 수 있기 때문입니다. CSS에는 글자를 세로 가운데 정렬할 수 있는 프로퍼티가 존재하지 않기 때문에, 이러한 트릭을 사용해야 하는데 CSS 글자 세로 가운데 정렬 포스트에 잘 설명되어져 있습니다.
        • text-align: center; 글자를 가로 가운데 정렬합니다.
        • position: relative; position을 relative로 설정하는 이유는, 위치 속성(top, bottom, left, right)를 사용할 때 위치 기준을 어디로 할지 설정해줘야 하기 때문입니다. 여기서는 relative로 설정하였기 때문에 앞에 위치한 형제 요소를 기준으로 위치를 잡게 되는데, div.child의 형제 요소가 없으므로 부모 요소 기준으로 이동한 것과 같습니다. 공식처럼 기억해야 할 것은 위치 속성을 사용할 땐, position(relative 또는 absolute)을 설정!
        • left: 50%; div.child 요소를 오른쪽으로 50% 이동 시킵니다.
        • top: 50%; div.child 요소를 아래로 50% 이동 시킵니다.
  • 구현 결과
    • 자식 요소 div.child를 left: 50%와 top: 50%로 설정하였기 때문에, div.child(pink색 박스)는 부모 요소(빨간 점선)를 기준으로 오른쪽으로 50%, 그리고 아래로 50%만큼 이동할 것으로 예상됩니다. 하지만 구현결과를 보면 세로방향으로는 전혀 움직이지 않고, 가로방향으로만 50% 움직였습니다. 여기서 우리가 정확히 기억해야 할 점은, 부모요소에 height: auto가 지정되어 있으면, 자식 요소에는 top: %를 쓸 수 없다는 것입니다.
  • 다르게 작동하는 이유
    • 그러면 왜 left와 top은 서로 다르게 작동할까요? 우리는 가로와 세로 방향 이동이 동일한 메커니즘으로 작동할 것으로 자연스럽게 기대하지만, 섹션 [1]에서 설명드린 것처럼 가로와 세로 방향의 작동 메커니즘이 다릅니다. 다시 말해서, 부모 요소에 width: auto가 설정되면 “width = 100 % – margin(좌/우)”의 특정 수치로 설정되는 반면, “height = 자동맞춤” 이라는 불특정 값으로 설정됩니다. 따라서 width의 경우에는 특정 수치가 들어가 있기 때문에 자식 요소의 left와 right를 정확히 계산할 수 있는 반면, height의 경우에는 불특정 값을 가지기 때문에 자식 요소의 top과 bottom은 계산할 수 없어서 이동을 할 수 없는 것입니다. 그렇다면 부모 요소의 height에 특정값을 설정하게 되면 자식 요소의 top이 작동할까요? 다음 카드에서 확인해 보겠습니다.
<style>
    .wrapper {
        margin: 0 auto;
        max-width: 1180px;
 
        width: 100px; height: 100px;
        background-color: lightblue;
        border: 2px solid black;
    }
    .parent {
        border: 1px dashed red;
        height: 22px;
    }
    .child {
        background-color: lightpink;
        width: 70px; height: 22px;
 
        font-size: 15px; line-height: 22px;
        text-align: center;
 
        position: relative;
        left: 50%;
        top: 50%;
    }
</style>
<div class=“wrapper”>
    <div class=“parent”>
        <div class=“child”>자식요소</div>
    </div>
</div>
자식요소
이동→
이동↓↓
  • 구현 목표
    • 부모 요소의 height 프로퍼티에 특정값을 넣게 되면, 자식 요소의 top이 정상적으로 작동함을 확인해 보겠습니다.
  • 코드 분석
    • CSS 코드
      • 동일한 코드의 중복 설명은 생략합니다.
      • .parent의 CSS
        • width: auto; 위 코드에서는 따로 width 프로퍼티를 작성하지 않았지만, 기본값이 auto이기 때문에 width: auto로 설정된 것과 같은 결과가 나옵니다.
        • height: 22px; div.parent의 높이를 22px로 설정합니다. 이는 height: auto라는 불특정 값 대신에 특정값을 넣었을 때, 자식 요소의 top 속성이 잘 작동하는지 확인하기 위함입니다.
  • 출력 결과
    • 자식 요소 div.child는 가로, 세로 방향 모두 50%씩 이동했음을 확인할 수 있습니다.
    • 총정리해 보자면,
    • (1) 부모 요소의 height가 auto로 설정되어져 있으면, height는 “자동맞춤”이라는 불특정 값으로 설정됩니다. 따라서 자식 요소의 top과 bottom에 %를 사용할 수 없습니다. 왜냐하면 부모 요소 크기 대비하여 %를 계산 해야하는데, 부모 요소의 크기가 불특정한 값으로 되어져 있기 때문입니다. 만약 부모 요소의 height에 특정값을 넣게 되면, 자식 요소의 top과 bottom의 %를 계산할 수 있게 되어 정상적으로 작동하게 됩니다.
    • (2) 부모 요소의 width가 auto로 설정되어져 있으면, width에는 “100% – margin(좌/우)”이라는 특정값으로 설정됩니다. 따라서 자식 요소의 left와 right에 %를 사용할 수 있습니다.

3. 위치속성과 transform의 차이점

위치 속성과 마찬가지로 transform 속성은 요소의 모양을 이동시킬 때 사용할 수 있다는 점에서 공통점을 가집니다. 하지만 이 둘에는 다음과 같은 중요한 차이가 있습니다.

  1. 좌표 기준
    위치 속성: 부모요소의 크기를 기준으로 좌표 이동
    transform 속성: 자신의 크기를 기준으로 좌표 이동
  2. 기준 요소의 height: auto
    위치 속성 top: 부모 요소가 height: auto로 설정 되어 있다면, 세로 방향으로 이동하지 않음
    transform 속성: 자신 요소가 height: auto로 설정되어 있을 지라도, 세로방향으로 이동함

아래에서 예제와 함께 자세히 알아보겠습니다.

첫 번째 차이점: 좌표기준

<!– 1번 코드 –>
<style>
    .parent{
        width: 100px; height: 100px;
        background-color: cadetBlue;
        border: 2px solid black;
    }
    .target {
        background-color: fireBrick;
        width: 80px; height: 22px;
        font-size: 16px;
        line-hegith: 22px;
        color: white;
        text-align: center;
 
        position: relative;
        left: 50%; top: 50%;
    }
</style>
<div class=“parent”>
    <div class=“target”>타겟요소</div>
</div>
<!– 2번 코드 –>
<style>
    .parent{
        width: 100px; height: 100px;
        background-color: cadetBlue;
        border: 2px solid black;
    }
    .target {
        background-color: fireBrick;
        width: 80px; height: 22px;
        font-size: 16px;
        line-hegith: 22px;
        color: white;
        text-align: center;
 
        position: relative;
        transform: translate(50%, 50%);
    }
</style>
<div class=“parent”>
    <div class=“target”>타겟요소</div>
</div>
  • 목표
    • (1번 코드 예제) left: 50%; height: 50%;(2번 코드 예제) transform: translate(50%, 50%);를 제외하고는 동일합니다. 이 두 코드의 결과값이 어떻게 달라지는 확인하겠습니다.
  • 출력 결과
타겟요소
1번 코드 결과
타겟요소
2번 코드 결과
  • 1번 코드
    • 타겟 요소 div.target은 부모 요소 div.parent 크기를 기준으로 50%씩 가로, 세로방향으로 움직인 것을 확인할 수 있습니다. 흰색 점선은 이해를 돕고자 첨가한 것으로, 타겟요소의 이동 전의 위치를 나타냅니다.
  • 2번 코드
    • 타겟요소 div.target 자신의 크기를 기준으로 50%씩 가로, 세로방향으로 움직한 것을 볼 수 있습니다.이 메커니즘을 이해하고 있다면 transform으로 요소를 옮길 때는 부모요소가 필요 없다는 것을 이해할 수 있을 것입니다.

두 번째 차이점: height: auto일 때 세로 방향 이동 유무

<!– 1번 코드 –>
<style>
    .wrapper {
        max-width: 1180px;
        margin: 0 auto;
        padding: 10px;
    }
    .parent{
        width: 100px;
        height: auto;
        background-color: cadetBlue;
        border: 2px solid black;
    }
    .target {
        background-color: fireBrick;
        width: 80px; height: 22px;
        font-size: 16px;
        line-hegith: 22px;
        color: white;
        text-align: center;
        position: relative;
        top: 50%;
    }
</style>
<div class=“wrapper”>
    <div class=“parent”>
        <div class=“target”>타겟요소</div>
    </div>
</div>
<!– 2번 코드 –>
<style>
    .wrapper {
        max-width: 1180px;
        margin: 0 auto;
        padding: 10px;
    }
    .parent{
        width: 100px;
        height: auto;
        background-color: cadetBlue;
        border: 2px solid black;
    }
    .target {
        background-color: fireBrick;
        width: 80px; height: 22px;
        font-size: 16px;
        line-hegith: 22px;
        color: white;
        text-align: center;
        position: relative;
        height: auto;
        transform: translate(0, 50%);
    }
</style>
<div class=“wrapper”>
    <div class=“parent”>
        <div class=“target”>타겟요소</div>
    </div>
</div>
  • 목표
    • 1번 코드에서는 부모 요소를 height: auto로 설정하여 불특정값을 넣고, 자식 요소를 top: 50%로 설정했을 때 어떻게 이동하는지를 확인하겠습니다.
    • 2번 코드에서는 자식 요소를 height: auto로 설정하여 불특정값을 넣고, transform으로 y축 방향으로 50% 이동시켰을 어떻게 되는지 확인하겠습니다.
  • 출력 결과
1번 코드 결과
타겟요소
2번 코드 결과
타겟요소
  • 1번 코드
    • top 속성은 부모 요소의 height를 기준으로 계산됩니다. 부모 요소가 height: auto로 설정되어 있으면 이 값은 특정값이 아니기 때문에, 자식 요소의 top을 계산할 수가 없어서 세로방향으로 이동하지 않습니다.
  • 2번 코드
    • 앞에서 설명드린 것처럼 transform은 자기 자신의 크기를 기준으로 이동합니다. 만약 자신의 height를 auto로 설정하여 불특정값을 넣게 되면 어떻게 될까요? 결과를 보시면, 자기 자신의 height: auto일지라도 y축 방향으로 50% 이동했음을 볼 수 있습니다. 즉, transform은 CSS에 선언된 값을 기준으로 잡는게 아니라, 실제 크기를 계산하여 그 값을 기준으로 잡기 때문에, auto 선언과는 상관없이 가로/세로 방향으로 이동합니다.
    •  자바스크립트를 보면 CSS의 선언된 값과 계산된 값이 다르다는 것을 알수 있습니다. 예를 들어 선언된 CSS는 <style></style>에서 선언된 CSS로써 HTML요소.style에서 볼 수 있고, 계산된 CSS는 실제로 표시된 요소의 크기를 연산에 의해서 표시된 값으로 window.getComputedStyle()을 이용해서 볼 수 있습니다. 비슷한 원리로 이해하시면 될 것 같습니다.

[4] 정리

  • auto의 의미
    • 원리: width: auto와 height: auto의 의미는 내용물(자식 요소)의 크기에 맞춰 자동 크기 조절입니다.
    • 주의할 점: block 요소는 width: auto 설정시에도 내용물 크기에 맞춰 자동 조절되지 않습니다. block 요소의 width: auto의 의미는 부모 요소의 한 줄을 다 채우라는 뜻으로, 조금 더 수치적으로 설명하자면 width = 100% – (좌/우)margin으로 이해할 수 있습니다.
  • auto 설정 시, width와 height의 값
    • 원리: width에 내용물 너비값이 들어가고, height에는 특정값이 들어가지 않습니다.
    • 주의할 점: 부모요소를 height: auto로 설정 시에는 위치속성 top을 이용하여도 세로방향으로 움직이지 않습니다.
  • transform 세로 방향
    • 원리: transform은 CSS 선언값이 아니라, 실제 계산된 값을 기준으로 삼습니다.
    • 주의할 점: height: auto 설정시에도 transform을 이용하여 세로방향으로 움직일 수 있습니다.

참고
[1] 요소란?
[ CSS 목록 보기 ]

8 thoughts on “【CSS】 width: auto와 height: auto 당신이 몰랐던 작동 원리”

  1. 자세한 정리 감사합니다 ㅎㅎ
    그냥 아무생각없이 사용하고는 했는데 자세히 알고가요

    1. 도움이 되었다니 기쁘네요. 그리고 댓글까지 달아주셔서 감사합니다 🙂

  2. 평상시 너무 별생각안하고 쓰다가 문뜩 궁금해져서 구글링했는데 훌륭한 글을 보게 됐네요!
    자세하게 설명해주셔서 완벽하게 숙지 할 수 있었습니다 😀

    1. 블로그에 방문해주셔서 감사합니다. 도움이 되어서 기쁘네요 ????

  3. Pingback: 【CSS】 글자 세로 가운데 정렬하는 4가지 방법 ⋆ Our Small Joy

  4. 이렇게 정확한 설명과 쉽게 이해 할 수 있는 글은 처음입니다!
    많은 도움되었습니다. 감사합니다!

Leave a Reply