[CSS In Depth] box model & float

Kyoorim LEE·2023년 3월 2일
0

스스로TIL

목록 보기
17/34

3.5 컨테이너로 요소 간격 주기

  1. 초기 상태
  2. html 코드
    <aside class="sidebar">
      <a href="/twitter" class="button-link">follow us on Twitter</a>
      <a href="/facebook" class="button-link">like us on Facebook</a>
    </aside>
내용코드결과
1. button-linkdisplay:block 처리 하기 전
2. button-linkdisplay:block 처리: container의 width를 채우고 한 줄 전체를 차지하게 됨
3. spacing 처리: margin-top:1.5em을 추가 => button 각각에 margin-top이 적용됨. top 부분에는 이미 적용된 padding값에 margin-top이 중복 적용되어 원하는 결과가 아님
4. 인접 형제 결합자(adjacent sibling combinator, +)를 사용하여 앞에서 지정한 요소의 바로 다음에 위치하는 형제 요소만 선택해서 margin-top을 적용시킴

3.5.1 content가 변화할 것에 대비하기

위 사례의 4번째 해결 방안에 만일 button요소를 더 추가하게 되면 바로 문제가 발생하게 된다. 해당 요소를 선택하여 margin-top을 다시 적용하면 된다고 생각하겠지만 이렇게 건당 처리하는 것보다 좀 더 일괄적으로 적용될 수 있는 솔루션이 필요하다!

내용코드결과
5. button-link 밑에 하위요소로 sponsor-link를 추가하게 되는 순간 해당 요소에 margin-top이 다시 적용되지 않는 것을 볼 수 있음

3.5.2 부엉이 연산자 (lobotomized owl selector)

* + * : 뇌수술 받은 부엉이랑 닮았다고 하여 지어진 이름이란다🦉

*는 일반적으로 모든 요소를 선택할 때 사용한다. 여기에 + 요소를 쓰고 또 한번 *를 쓰게되면 버튼 뒤의 직접적인 하위 버튼 요소만을 타켓하는 것이 아니라 부모의 첫 번째 자식요소를 제외한 모든 뒤따라오는 요소를 타겟한다는 뜻이다.

내용코드결과
6. <body> 내부 전체를 타겟할 수 있도록 다음과 같이 처리

다음 중 body * + *이 적용된 부분을 살펴보겠다. 부모 요소의 첫 번째 자식요소를 제외한 그 이후 자식 요소들이 모두 targeted 되었다.

<body>
  <header>
    <h1>Franklin Running Club</h1>
  </header>
  <div class="container"> /* <-----적용! */
    <main class="main">
      <h2>Come join us!</h2>
      <p> /* <-----적용! */
        The Franklin Running club meets at 6:00pm every Thursday
        at the town square. Runs are three to five miles, at your
        own pace.
      </p>
    </main>
    <aside class="sidebar"> /* <-----적용! */
      <a href="/twitter" class="button-link">
        follow us on Twitter
      </a>
      <a href="/facebook" class="button-link"> /* <-----적용! */
        like us on Facebook
      </a>
      <a href="/sponsors" class="sponsor-link"> /* <-----적용! */
        become a sponsor
      </a>
    </aside>
  </div>

그 결과 원치 않는 문제가 생겼다. 이미 <div class="container">top-margin:1.5em이 적용되었는데 <aside>에도 중복 적용되면서 sidebar의 top-margin이 결과적으로 3em이 되어버린 것이다.

또한 현재 <main class="main">에 padding 적용이 안되어있으므로 padding도 추가해야한다.

내용코드결과
7. <sidebar>에 margin-top:0으로 처리하기 & <main class="main">에 padding값 주기


올빼미 연산자를 쓰게되면 장단점이 있다. **코드 한 줄로 페이지 전체에 한꺼번에 적용할 수 있어 편리하지만, 원하지 않는 부분까지 영향을 주게 되는 경우 그 부분만 추가 수정이 필요하기 때문이다.** 특히 한 부모 요소 맡에 여러 column들이 자식요소로 있는 경우가 이런 경우에 해당한다. 이런 부분들을 잘 고려하여 사용하면 올빼미 연산자도 훌륭한 솔루션이 될 수있다.

4. floats

float
containing block안에서 특정 요소의 오른쪽이나 왼쪽에 위치시키는 것을 뜻한다. float는 3가지 값을 받는다 : left, right, none이다. 기본값은 none으로 float가 적용되지 않은 상태를 뜻한다.


요소를 옆에 위치시키거나 이미지 주변으로 텍스트가 흐르게 하기 위한 목적으로 사용되지만 제대로 사용하지 못할 경우 다른 요소를 overlapping 하거나 부모 요소에 혼란을 주는 등 레이아웃 문제가 발생할 수 있다. 최근에는 flexboxgrid로 많이 대체되었다.

4.1. floats의 목적

float는 요소(주로 이미지)를 컨테이너의 한 쪽 방향(왼쪽 or 오른쪽)으로 오게 위로 끌어올리고 그 나머지 요소들이 그 주변으로 흐르게 만든다. 신문이나 매거진에서 익숙하게 본 그림이다.

위 그림과 같이 요소를 오른쪽이나 왼쪽으로 위치시킬 수 있다. float가 적용된 요소는 원래 document flow에서는 더 이상 고려되지 않고 컨테이너의 한 쪽 자리에 위치하기 되며 나머지 document 요소들은 그 주변을 감싸며 흐르게 된다. 한 개 이상의 요소에 float를 적용하게 되면 다음 그림과 같이 한 쪽 방향으로 쌓이게 된다.

예시) Franklin Running Club 예시

  1. html 코드
<body>
  <div class="container">
    <header>
      <h1>Franklin Running Club</h1>
    </header>

    <main class="main clearfix">
      <h2>Running tips</h2>

      <div>
        <div class="media">
          <img class="media-image" src="runner.png" />
          <div class="media-body">
            <h4>Strength</h4>
            <p>
              Strength training is an important part of injury prevention. Focus
              on your core&mdash; especially your abs and glutes.
            </p>
          </div>
        </div>

        <div class="media">
          <img class="media-image" src="shoes.png" />
          <div class="media-body">
            <h4>Cadence</h4>
            <p>
              Check your stride turnover. The most efficient runners take about
              180 steps per minute.
            </p>
          </div>
        </div>

        <div class="media">
          <img class="media-image" src="shoes.png" />
          <div class="media-body">
            <h4>Change it up</h4>
            <p>
              Don't run the same every time you hit the road. Vary your pace,
              and vary the distance of your runs.
            </p>
          </div>
        </div>

        <div class="media">
          <img class="media-image" src="runner.png" />
          <div class="media-body">
            <h4>Focus on form</h4>
            <p>
              Run tall but relaxed. Your feet should hit the ground beneath your
              hips, not out in front of you.
            </p>
          </div>
        </div>
      </div>
    </main>
  </div>
</body>
Before코드After
.container {
	max-width: 1080px;
    margin: 0 auto;

width 대신에 max-width를 설정하면 뷰포트가 1080px 이하일때 요소가 1080px 보다 더 작아질 수 있으며 최대로 커진 크기는 1080px가 된다는 말이다.

float를 왜 사용해야하는지 알아야할까?
기존에 float를 사용해 만들었던 페이지 레이아웃을 flexbox가 빠르게 대체하고 있다. 물론 모던 브라우저에서는 float 없이 얼마든지 레이아웃을 구성할 수 있다. 하지만 여러분의 서비스가 Internet Explorer를 지원한다면 float를 완전히 무시하고 살긴 어려울 것이다. flexbox가 IE10 과 IE11에서만 지원되며 이마저도 간혹 버그가 발생하기 때문이다.


float를 사용한 레이아웃의 경우 대개 최소한의 마크업이 가능하다는 장점이 있다. 또한 float는 여전히 이미지를 페이지 한쪽에 띄우고 주변으로 텍스트를 흐르게 할 수 있는 유일한 방법이다.


4.2. Container collapsing과 clearfix

float는 원래대로 잘 작동하고 있는데 이로 인해 가끔 문제가 발생하는 경우가 있다.

4.2.1. container collapsing 이해하기

내용코드결과
1. .media div에 float: left 주기

.mediafloat:left를 주었고 width: 50%를 주어 한 줄에 2개의 이미지가 들어가도록 처리했다.

.main에 적용되었던 background-color:white가 더 이상 적용되지 않음을 볼 수 있다. 왜일까?

float가 적용된 요소는 부모 요소에 height를 주지 않기 때문이다.

부모요소인 <div>에 height가 0으로 나온다.

이 현상은 float가 사용되었던 본질적 목적과 관련이 깊다.

만일 이미지의 높이가 텍스트 높이보다 큰 경우, 해당 문단이 이미지의 높이에 맞춰서 커지지 않는다. 다시 말하면, 만일 이미지가 문단의 텍스트 높이보다 큰 경우 다음 문단의 글이 바로 뒤이어 따라오게 된다는 것이다. (4.7 그림 참조)


우리의 예시로 다시 돌아오면 <main> 안의 요소들 중 <h2>인 Running Tips를 제외하고 다른 요소들은 다 float가 적용되어있는 상태다. 따라서 <h2>의 height만 살아있는 상태다.

이를 고치기 위한 해결방법을 알아보자

1. clear 사용하기

내용코드결과
2. 마지막에 <div style="clear: both"></div> 추가하기

.media의 부모요소와 형제가 되도록 빈요소를 다음과 같이 만들어 준다. <div style="clear: both"></div> (clear: both도 동일한 결과가 나온다. 반면 clear: right를 적용하면 해당 div가 <h2> 바로 밑으로 가기 때문에 해당 container가 expand(확장)되지 않는다). 맨 마지막에 <div style="clear: both"></div> 를 넣어줌으로써 float가 적용된 .media 주변을 흐르는 요소가 마지막에 하나 더 생기게 되면서 <main> 컨테이너의 높이가 정해진다.

이렇게 하면 문제가 해결될 수 있으나 사실 이 방법은 불필요한 마크업을 추가해야하기 때문에 그렇게 바람직한 방법이라고는 할 수 없다.

4.2.3. clearfix 이해하기

불필요한 <div>를 추가하는 대신 가상요소(pseudo-element)를 사용하여 처리할 수 있다.

<main>에 clearfix라는 class를 추가한다.

.clearfix::after <main>의 마지막 부분(::after) 가상요소를 추가한다.

※ 주의사항
clearfix는 float를 포함하고 있는 요소에 사용되어한다. float가 직접 적용되어있는 요소에 적용되거나 float를 포함하고 있는 요소의 다음 요소에 적용되는 일이 없도록 하자.


위 코드를 추가하게 하게 되면 <h2> 위에 margin이 아래 그림과 같이 적용된다.

가상요소에 display:table를 적용하게 되면 table row와 table cell이 만들어지게 된다. table row와 table cell에서는 마진이 무너지지 않으므로 display:table이 적용된 가상요소에서도 무너지지 않게 되는 것이다.

display:table-cell도 동일한 효과를 낼 것으로 기대할 수 있지만 우리 예시의 경우 clear 속성은 block 레벨의 요소에만 적용이 되는데, table은 block레벨이지만 table-cell은 block레벨이 아니므로 clear가 적용될 수 없어서 이 경우는 display:table을 사용하는 것이 가장 적절하다.

profile
oneThing

0개의 댓글