[CSS, 책리뷰] 새로운 CSS 레이아웃 - 살펴보기#1 (CSS LAYOUT, float, flex-box, BFC, grid)

하수도키

·

2021. 11. 4. 16:51

728x90
반응형
SMALL

새로운 CSS 레이아웃 표지

CSS 전체를 다루는 책이 아닌 CSS 레이아웃에 대한 책이다.

지인 추천과 목차를 보고 마음에 들어 구매하게 되었다.

http://www.yes24.com/Product/goods/60715949

float, flex, grid 등을 다루면서 CSS 레이아웃 과거부터 현재 그리고 미래를 다룬다.

목차 순서대로 리뷰해보겠다.

이번 포스팅은 1장, 2장 3장을 정리했다.

제1장 우리가 지나온 길

float 문제

.cards li {
  float: left;
  width: calc(33.333333333% - 20px);
  margin: 0 10px 20px 10px;
  background-color: darkorange;
}
<ul class="cards">
  <li>
    <h1>card1</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
  </li>
  <li>
    <h1>card2</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
    <p>컨텐츠 추가</p>
  </li>
  <li>
    <h1>card3</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
  </li>
  <li>
    <h1>card4</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
  </li>
  <li>
    <h1>card5</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
  </li>
  <li>
    <h1>card6</h1>
    <p>테스트입니다.테스트입니다.테스트입니다.테스트입니다.</p>
  </li>
</ul>
  • 높이가 같은 요소일 때는 문제가 발생하지 않지만 내용이 많아 높이가 길어지는 경우 문제가 발생한다.
    • 높이가 일정한 요소들(정상)
    • 높이가 다른 요소들(문제)
      • card2의 컨텐츠 내용이 추가되어 높이가 길어질 경우

float 문제 해결 방법

  • card1, card2, card3card4, card5, card6을 각각 1줄씩 하나의 요소로 감싸고 clearfix 적용하기 각각 요소가 서로의 공간을 침범하지 않게 만든다.
    // html
    <ul class="cards">...</ul>
    <ul class="cards">...</ul>
    // style
    .cards {
      clear: both;
    }
    .cards li {
      list-style: none;
      float: left;
      width: calc(33.333333333% - 20px);
      margin: 0 10px 20px 10px;
      background-color: darkorange;
    }​
     
    • 문제 : 마크업 구조를 변경해야 한다.

- float대신 display: inline-block을 사용

.cards li {
  /*float: left;*/
  display: inline-block;
  width: calc(33.333333333% - 20px);
  margin: 0 10px 20px 10px;
  background-color: darkorange;
}
  • 문제 : inline요소에는 공백(4px)을 그대로 유지한다는 특성(HTML 코드의 개행의 문제라고 한다.)을 가지고 있다.(공백을 유지하지 않으면 inline요소는 띄어쓰기 없이 붙어서 표시) 따라서 공백 유지 때문에 한 줄에 2개의 요소만 표시된다.(margin값 수정하거나, 마크업을 붙여서 작성하는 방법 등을 이용하여 수정 가능)
  • inline-block 4px 해결 방법은 https://m.blog.naver.com/altmshfkgudtjr/221767823027 참고
    display: inline-block 문제

float대신 display: inline-table을 사용

  • display: table를 사용해서 테이블 레이아웃의 형태로 변경한다. 자식 요소들도 tr요소처럼 display: table-row, td처럼 display :table-cell을 추가한다. 또한 각 줄마다 요소로 감싸줘야 한다. vertical-align으로 수직정렬 가능
    #wrap {
      margin-top: 100px;
      width: 900px;
      background-color: antiquewhite;
      display: table;
      border-spacing: 10px;
    }
    .cards {
      display: table-row;
    }
    .cards li {
      /* float: left; */
      /* display: inline-block; */
      display: table-cell;
      width: calc(33.333333333% - 20px);
      margin: 0 10px 20px 10px;
      background-color: darkorange;
    }
    <div id="wrap">
      <ul class="cards">...</ul>
      <ul class="cards">...</ul>
    </div>
    • 문제 : 마크업 구조를 변경해야 함. 그리고 테이블의 줄과 칸은 margin이 적용되지 않아 border-spacing을 사용해야 한다.

제2장 레이아웃 제작의 현재

CSS 아키텍처

  • CSS 아키텍처는 OOCSS, SMACSS, BEM 등이 있는데 혼자 작업하면 굳이 이런 방식을 사용하면 필요성을 느끼지 못할 수도 있다. 다른 동료들과 협업을 할 경우 아키텍처의 필요성을 느낄 것이다.
  • 하지만 CSS 아키텍처의 CSS클래스 네임을 사용하다 보면 CSS가 마크업 하고 더 강하게 결합되는 부작용이 존재한다.
    • 위치와 상관없이 클래스만으로 요소 선택 가능, 하지만 아래(BEM 사용)와 같이 HTML의 양이 증가된다.
      // CSS 아키텍처를 사용하지 않은 경우
      <style>
      .menu {}
      .menu ul {}
      .menu ul li {}
      .menu ul li a {}
      </style>
      
      <div class="menu">
        <ul>
          <li>
            <a href="#">Menu</a>
          </li>
        </ul>
      </div>
      
      // CSS BEM 아키텍처를 사용한 경우
      <style>
      .menu {}
      .menu__list {}
      .menu__item {}
      .menu__link {}
      </style>
      
      <div class="menu">
        <ul class="menu__list">
          <li class="menu__item">
            <a class="menu__link" href="#">Menu</a>
          </li>
        </ul>
      </div>
       

 

전처리기와 후처리기

  • 전처리기 : LSES, SASS와 같이 CSS가 아닌 언어로 CSS를 작성하면 CSS로 컴파일해주는 도구
    • 장점
      • 강력한 문법 제공 : 변수 사용, Nesting(중첩), 상속, 함수, mixin 등
      • 재사용 용이
    • 단점
      • 러닝 커브 : 문법을 별도로 배워야 한다.
  • 후처리기 : CSS 파일이 작성된 후에 적용된다.(Javasciprt 플러그인을 사용하여 CSS를 변환하는 도구 CSS의 Babel 느낌) AUTOPREFIXER를 사용하면 구식 브라우저에 필요한 제조사 접두어를 추가
    • 장점
      • 모듈식 사용 : 필요한 플러그인만 사용 가능, 전체를 포함하지 않아도 되므로 속도가 빠르다.
      • Javascipt 기반 : 필요한 플러그인을 직접 개발할 수 있다.
      • CSS 표준 문법 기반 : CSS 작성을 위해 별도의 문법을 배울 필요가 없다.
    • 단점
      • (전처리기에 비해) 강력한 문법을 제공하지 않는다.
      • 필요한 플러그인을 찾아서 직접 조립해야 한다.
      • 플러그인의 지원이 중단될 수 있다.
  • 전처리기, 후처리기 참고 : https://still-growing.tistory.com/entry/PostCSS-vs-Scss
  • 이러한 도구를 사용하면 시간을 상당히 아낄 수 있다. 전처리기 같은 경우는 여러 사람이 각자 맡은 부분을 작업하고 이 모든 파일을 취합해 하나로 컴파일하는 방식으로 많이 사용된다. 하지만 CSS 명세와 동떨어져 버려 새로운 CSS 신기술을 간과할 수 있다.
  • 후처리기를 이용하여 불필요한 접두사를 추가할 수도 있다.

 

컴포넌트 우선 디자인

  • 아토믹 디자인(Atomic Design) : 빈 페이지부터 시작해서 디자인을 완성해가는 대신 가장 작은 구성 요소부터 시작해서 점차 바깥으로 확장하면 디자인할 것을 권장한다. 이 방식은 프론트 개발자가 1명인 팀에는 조금 과한 면이 있다.

 

프레임워크

  • 부트스트랩 : 디자이너, 개발자들이 최소한의 지식을 가지고 웹사이트를 만들 수 있게 해 준다. 개성 있진 않지만 개발자가 만든 사이트처럼 끔찍하지는 않다.
  • 모든 프레임워크에는 만든 사람의 의도와 요구 사항이 담겨 있고 그러한 의도와 요구 사항이 자신의 요구 사항과 일치할 수도 그렇지 않을 수도 있다.

 

기타

  • 성능 : HTTP 아카이브는 2016년 12월에 웹 페이지 평균 다운로드 크기가 2.4MB 이상이라고 한다. 인터넷 속도가 느린 곳도 생각하여 속도도 염두에 두는 것이 좋다.
  • 접근성 : 새로운 명세 덕분에 시각적인 표현 선수를 재배열할 수 있게 된 만큼 이를 세심하게 주의를 기울여서 사용해야 한다.
  • 자동으로 업데이트되는 브라우저 : 크롬, 파폭 등 자동으로 업데이트 되는 브라우저가 많아졌으나 내부 정책 때문에 사용할 수 있는 브라우저가 정해진 곳이 여전히 존재한다. 추후 언젠가 업데이트를 대비해 코드를 추가로 작성하지 않고도 브라우저가 업데이트될 때 스스로 진화하는 듯 보이는 웹사이트를 제작해야 한다.

제3장 새로운 레이아웃

CSS의 양식화 문맥

  • https://drafts.CSSwg.org/CSS-display-3/#formatting-context
  • 양식화 문맥이 다르면 다른 규칙에 따라 상자를 배치합니다. 예를 들어, 플렉스 양식화 문맥은 CSS3 FLEXBOX라는 플렉스 레이아웃 규칙에 따라 상자를 배치하고, 블록 양식화 문맥은 CSS2의 블록과 인라인 레이아웃 규칙에 따라 상자를 배치합니다.
  • 블록 양식화 문맥(BFC) : 요소에 새로운 블록 양식화 문맥을 작성하면 그 요소의 자식 요소에 적용할 독립적인 레이아웃 환경을 만들 수 있다.
  • 아래와 같은 조건을 만족하면 새로운 BFC가 만들어진다.
    • root 요소일 때
    • float값이 none이 아닐 때
    • position: static, relative이 아닐 때
    • overflow: visible이 아닐 때
    • display: table-cell, table-caption, inline-block, flex, inline-flex, grid 일 때
  • boxfloat: left인 상태일 때
    // html
    <body>
      <h1>Block Formatting Context</h1>
      <div class="container">
        <div class="box">
          <p>I am floated left.</p>
        </div>
      </div>
    </body>
    
    // style
    <style>
    .container {
      border: 4px solid red;
    }
    .box {
      border: 4px solid darkorchid;
      float: left;
    }
    </style>
    Block Formatting Context I am not floated
    Block Formatting Context I am floated left.
    • box가 floating 되면 새로운 BFC가 만들어진다.(독릭적인 레이아웃) 따라서 box 영역이 별도로 구분되면서 부모인 container 높이가 줄어든다.
    • 위에서 말한 container에 BFC를 만들어주면 요소의 자식 요소에 적용할 독립적인 레이아웃을 만들면서 모든 것을 내부에 표현합니다. 따라서 boxcontainer안으로 들어갑니다.
    • BFC를 만들기 위해 overflow: hidden, float:left를 사용할 수 있다.
    • overflow: hidden 적용 코드
    .container {
      border: 4px solid red;
      overflow: hidden;
    }
    .box {
      border: 4px solid darkorchid;
      float: left;
    }
    Block Formatting Context container overflow: hidden
    • 하지만 overflow: hidden은 플로팅을 제거할 목적으로 만들어진 것이 아니라서 box-shadow가 잘리는 현상이 있다.
    • 따라서 새로운 BFC를 만들 목적으로 나온 display: flow-root를 사용하면 된다. 이 값을 지원하는 브라우저에서는 새로우 BFC만 만들고 다른 부작용은 없다.
      .container {
        border: 4px solid red;
        display: flow-root;
      }
      .box {
        border: 4px solid darkorchid;
        float: left;
      }
       

Block Formatting Context container display: flow-root;

흐름 내부과 외부

  • 요소(element)를 floating하거나 position: absolute, fixed하면 흐름에서 벗어난다.(새로운 BFC를 만들어 독립적인 레이아웃을 만든다.)
  • 양식화 모델에 따르면 블록 요소는 컨테이너의 너비만큼 넓어지고 새로운 줄에 표현
  • 인라인 요소는 공간이 있을 경우 다른 요소 바로 뒤에 표시
  • 플로팅 된 요소는 블록 수준의 요소(부모)를 만날 때까지 위로 이동하고  그 뒤에 요소들은 플로팅 된 요소 옆으로 늘어섭니다.
  • 블록요소 텍스트는 플로팅 된 요소 주변으로 배치되고 배경색은 너비만큼 차지한다.
    <div class="container">
      <div class="box">
        <p>I am floated left. I am out of flow.</p>
      </div>
      <p>I am a paragraph of text inside the container. I am in-flow. My text wraps around the float but my background color extends behind the floated item.</p>
    </div>
    
    <style>
    .container {
      width: 400px;
      border: 2px solid #d0bfff;
      border-radius: 5px;
      overflow: hidden;
    }
    .box {
      float: left;
      width: 200px;
      border: 2px solid #d0bfff;
      border-radius: 5px;
      padding: 10px;
    }
    .box > p {
      background-color: khaki;
    }
    .container > p {
      background-color: orange;
    }
    
    </style>
     
    Flow as applied to Floats

플렉스박스(flex-box)

  • 6개의 목록을 가진 요소에 display: flex를 설정하면 6개의 목록이 flex-item으로 바뀐다. flexitem은 기본값으로 한 줄로 배열되고 플렉스 컨테이너 높이(가장 긴 요소)만큼 길이가 늘어난다. 모든 아이템은 그 안에 콘텐츠의 길이와 상관없이 높이가 똑같아진다.
  • 목록이 추가되면 min-content로 정해진 너비보다 작아질 수 없으므로 플렉스 컨테이너를 벗어나게 된다. min-content는 단어 중 가장 긴 것을 기준으로 한다.
    <style>
    .flex-wrap {
      display: flex;
    }
    .flex-item {
      padding: 10px;
      border: 1px solid cadetblue;
      list-style: none;
    }
    </style>
    <div class="container">
      <h1>flex box</h1>
      <ul class="flex-wrap">
        <li class="flex-item">
          <h2 class="flex-item-card">flex-item-card</h2>
          <p class="flex-item-content">Free shipping on millions of items. Get the best of Shopping and Entertainment with Prime. Enjoy low prices and great deals on the largest selection of ...</p>
        </li>
        <li class="flex-item">
          <h2 class="flex-item-card">flex-item-card</h2>
    	  <p class="flex-item-content">en.news has suspended operation. Despite an incredible response from English-learners around the world, we have been unable to sustain the operation of ...</p>
    	</li>
    	<li class="flex-item">
    	  <h2 class="flex-item-card">flex-item-card</h2>
    	  <p class="flex-item-content">목록이 추가되면 min-content로 정해진 너비보다 작아질 수 없으므로 플렉스 컨테이너를 벗어나게 된다. min-content는 단어중 가장 긴 것을 기준으로 한다.</p>
    	</li>
    	<li class="flex-item">
    	  <h2 class="flex-item-card">flex-item-card</h2>
    	  <p class="flex-item-content">마다 개별적으로 사용 가능한 공간을 할당한다는 뜻입니다. 플렉스박스는 바로 위나 아래에 있는 다른 플렉스 박스와 선을 맞추어 정렬하지 않습니다. 이를 가리켜 1차원 레이아웃이라고 부릅니다.</p>
    	</li>
      </ul>
    </div>​

    display: flex min-content Entertainment
  • 이럴 땐 flex-wrap: wrap;을 사용하면 콘텐츠 길이만큼 늘어나서 1줄로 나오게 된다.
    .flex-wrap {
      display: flex;
      flex-wrap: wrap;
    }​

    flex-wrap: wrap
  • 줄 바꿈을 하기 위해서는 플렉스 아이템에도 flex속성을 추가한다. flex: 1 1 200px; 너비가 최소 200px로 맞춰져서 200px이하로 될 경우 줄 바꿈이 된다. flex 관련은 추후 설명
    .flex-item {
      flex: 1 1 200px;
      padding: 10px;
      border: 1px solid cadetblue;
      list-style: none;
    }​

    flex-item에 flex: 1 1 200px;
  • 만약 1개라도 목록이 삭제되면 그리드 효과는 사라지고 삭제된 자리는 나머지 목록이 채웁니다. 다음 줄로 넘어가면 새로운 줄이 플렉스 컨테이너가 됩니다. column도 마찬가지 즉, 플렉스 아이템이 다음 칼럼으로 넘어가면 새로운 칼럼이 플렉스 컨테이너가 됩니다. 이는 곧 각 줄마다 개별적으로 사용 가능한 공간을 할당한다는 뜻입니다. 플렉스 박스는 바로 위나 아래에 있는 다른 플렉스 박스와 선을 맞추어 정렬하지 않습니다. 이를 가리켜 1차원 레이아웃이라고 부릅니다.
  • 플렉스 박스가 그리드처럼 동작하게 하려면 유연성을 제한해야 합니다. 1장에서 살펴본 float 기반 레이아웃을 만들려면 flex-grow, flex-shrink 값을 0으로 변경하고 flex-basis: auto로 설정합니다. 이 설정은 플렉스 아이템에 주어진 퍼센트(width) 너비 이상으로 커지거나 줄어들지 않습니다. 다시 말해 한 줄에 플렉스 아이템이 2개밖에 없더라도 나머지 공간을 다 차지하기 위해 넓어지지 않습니다. float을 사용한 그리드처럼 각 플렉스 아이템 사이의 간격도 포함해야 합니다.
    .flex-wrap {
      display: flex;
      flex-wrap: wrap;
    }
    .flex-item {
      flex: 1 1 200px;
      width: calc(50% - 40px);
      /* flex: 0 0 auto; */
      padding: 10px;
      border: 1px solid cadetblue;
      list-style: none;
    }​

Grid Layout(그리드 레이아웃)

  • 이 명세는 2차원 레이아웃을 다루고 있다. 즉, row, column을 동시에 제어하고 배치할 수 있다. display: grid가 적용되어 잇고 grid-template-columns: 1fr 1fr 1fr로 3개의 column을 생성하고 새로운 단위인 fr를 이용해 사용 가능한 공간을 3개로 나누되 균등한 비율로 나누었다.
  • 별도로 너비 설정 안 해도 되고, margin 대신 grid-gap을 이용
    <div class="container">
      <ul class="cards">
        <li class="card1">
          <h2>Card 1</h2>
          <p>These cards have been laid out using grid layout. By setting <code>display: grid</code> on the
              parent, all direct children become grid items.</p>
        </li>
        <li class="card2">
          <h2>Card 2</h2>
          <p>These cards have been laid out using grid layout. By setting <code>display: grid</code> on the
              parent, all direct children become grid items.</p>
        </li>
        <li class="card3">
          <h2>Card 3</h2>
          <p>These cards have been laid out using grid layout. By setting <code>display: grid</code> on the
              parent, all direct children become grid items.</p>
        </li>
        <li class="card4">
          <h2>Card 4</h2>
          <p>These cards have been laid out using grid layout. By setting <code>display: grid</code> on the
              parent, all direct children become grid items.</p>
        </li>
        <li class="card5">
          <h2>Card 5</h2>
          <p>These cards have been laid out using grid layout. By setting <code>display: grid</code> on the
              parent, all direct children become grid items.</p>
        </li>
      </ul>
    </div>
    
    <style>
    .cards {
      margin: 0;
      padding: 0;
      list-style: none;
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      grid-gap: 20px;
    }
    
    .cards li {
      background-color: #e5dbff;
      border: 1px solid #d0bfff;
      padding: 10px;
      border-radius: 5px;
    }
    </style>
    Grid Items - 1
    • 그리드를 사용한 아이템 배치
    • 오른쪽으로 읽는 언어(LTR), 왼쪽으로 읽는 언어(RTL)에 따라 번호의 순서가 달라진다.
    • grid-column, grid-row를 사용해 2차원 그리드의 장점인 row, column영역 조절이 가능하다.
      .card1 {
        grid-column: 1 / 3; /*1컬럼부터 2컬럼까지*/
        grid-row: 1;
      }
      .card2 {
        grid-column: 3; /*3컬럼만*/
        grid-row: 1;
      }
      .card3 {
        grid-column: 1; /*1컬럼만*/
        grid-row: 2 / 4; /*2로우에서 3로우까지*/
      }
      .card4 {
        grid-column: 2 / 4; /* 2컬럼에서 3컬럼까지 */
        grid-row: 2;
      }
      .card5 {
        grid-column: 2 / 4;
        grid-row: 3;
      }​

      Grid-items - 2
    • 그리드 아이템에 이름을 지어줄 수 있다.
    • grid-template-areas에서 .은 공백을 나타낸다.
      .cards {
        margin: 0;
        padding: 0;
        list-style: none;
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-gap: 20px;
        grid-template-areas:
          "a a b"
          ". d d"
          "c e e";
      }
      
      .cards li {
        background-color: #e5dbff;
        border: 1px solid #d0bfff;
        padding: 10px;
        border-radius: 5px;
      }
      
      .card1 {
        grid-area: a;
      }
      .card2 {
        grid-area: b;
      }
      .card3 {
        grid-area: c;
      }
      .card4 {
        grid-area: d;
      }
      .card5 {
        grid-area: e;
      }​

      Grid items - 3

결론

float, flex, grid 그리고 BFC 양식화 문맥을 통해 CSS 레이아웃에 대한 개념을 살펴봤다.

728x90
반응형
LIST