HTML CSS

html/css) 플렉스 flex

조충희 2025. 6. 4. 20:04

flexbox

플렉스박스


css3에서 도입된 레이아웃 모델이다.
요소를 수평 수직으로 정렬하고 공간을 분리한다.

display: flex
부모 컨테이너가 flex 속성이어야 한다
flexbox의 유효범위는 자식 요소까지만 유효하다

그러면 주축 방향, 교차축 방향이라는 개념이 생긴다

flex-directon: row, column..

주축 방향 정렬: justify
교차축 방향 정렬: align

 

flex wrap
화면이 작아지만 자동으로 요소 줄바꿈하기

 

css의 상속
부모요소의 스타일이 자식에 전달되는 것
color, font.. 등은 상속된다.

우선순위는
!important
인라인
id
class
tag 순이다

 

Flexbox의 기본 개념

Flexbox를 잘 사용하려면 몇 가지 기본 개념을 먼저 이해해야 합니다.

Flex Container와 Flex Item

  • Flex Container (플렉스 컨테이너): Flexbox를 적용하는 부모 요소입니다. display: flex;를 설정하면 이 요소가 Flex Container가 됩니다.
  • Flex Item (플렉스 아이템): Flex Container의 직계 자식 요소들입니다. 이 아이템들이 Flexbox 규칙에 따라 배치됩니다.

Main Axis와 Cross Axis

  • Main Axis (주축): Flex Item이 배치되는 기본 방향입니다. flex-direction 속성에 따라 주축이 수평(row) 또는 수직(column)으로 결정됩니다.
  • Cross Axis (교차축): 주축과 수직인 방향입니다. 예를 들어, 주축이 수평이면 교차축은 수직이 됩니다.

Flex Direction

  • flex-direction 속성은 Flex Item이 배치되는 방향을 결정합니다. 값은 다음과 같습니다:
    • row: 왼쪽에서 오른쪽 (기본값).
    • row-reverse: 오른쪽에서 왼쪽.
    • column: 위에서 아래.
    • column-reverse: 아래에서 위.

 

Flexbox의 주요 속성

 

Flexbox에는 레이아웃을 더 세밀하게 조정할 수 있는 다양한 속성이 있습니다. 몇 가지 주요 속성을 배워보겠습니다.

justify-content: 주축 정렬

justify-content는 주축(main-axis)을 기준으로 Flex Item을 정렬합니다.

  • flex-start: 주축의 시작점에 정렬.
  • flex-end: 주축의 끝점에 정렬.
  • center: 주축의 중앙에 정렬.
  • space-between: 첫 아이템과 마지막 아이템을 양 끝에 배치하고 나머지 공간을 균등 분배.
  • space-around: 모든 아이템 주위에 동일한 여백을 둠.
  • space-evenly: 모든 아이템 사이와 양 끝에 동일한 간격을 둠.

align-items: 교차축 정렬

align-items는 교차축(cross-axis)을 기준으로 Flex Item을 정렬합니다.

  • flex-start: 교차축의 시작점에 정렬.
  • flex-end: 교차축의 끝점에 정렬.
  • center: 교차축의 중앙에 정렬.
  • stretch: 교차축 방향으로 아이템을 늘림(기본값).
  • baseline: 아이템의 텍스트 기준선에 맞춰 정렬.

 

예제)

  <body>
    <!-- flex 레이아웃을 쓰기 위해서는 부모요소가 반드시 flex.. 이어야 한다 -->
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
  </body>
      .container {
        /* flex container 설정 */
        display: flex;
        border: 2px solid darkolivegreen;
      }
      .item{
        width: 100px;
        height: 100px;
        margin: 5px;
        border: 2px solid darkolivegreen;
        text-align: center;
      }

 

예제2)

  <body>
    <h3>flex-direction: row</h3>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
    <h3>flex-direction: column</h3>
    <div class="container column">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
    <h3>flex-direction: row-reverse</h3>
    <div class="container row-reverse">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
  </body>
      .container {
        display: flex;
        /* 기본값: row */
        flex-direction: row;
        margin: 10px;
      }
      .container.column {
        /* 주축 방향을 column 으로 선택 */
        flex-direction: column;
        background-color: darkslategray;
      }
      .container.row-reverse {
        /* 주축 방향을 row-reverse 으로 선택 */
        flex-direction: row-reverse;
      }

      .item {
        width: 100px;
        height: 100px;
        margin: 5px;
        border: 2px solid darkolivegreen;
        text-align: center;
        color: darkseagreen;
      }
      .column {
      }
      .row-reverse {
      }

 

예제3)

 

<body>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
  </body>
      .container {
        display: flex;
        flex-direction: row;
        /* 주축 방향 정렬 */
        justify-content: space-evenly;
        border: 1px solid darkolivegreen;
        padding: 10px;
      }

      .item {
        width: 100px;
        height: 100px;
        margin: 5px;
        background-color: darkolivegreen;
        color: wheat;
        text-align: center;
      }

      html {
        background-color: black;
        color: darkseagreen;
      }

 

예제4)

  <body>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
  </body>
      /* 교차축 방향에 대한 정렬 기법 */
      .container {
        display: flex;
        flex-direction: row;
        /* 교차축 방향 정렬
        팁: 주축 방향은 기본적으로 화면의 끝까지 차지하는 영역 생성 */
        height: 400px;
        align-items: flex-end;
        border: 5px solid darkslategray;
        border-radius: 10px;
        padding: 10px;
      }
      .item {
        width: 100px;
        height: 100px;
        margin: 5px;
        background-color: darkslategray;
        color: wheat;
        text-align: center;
      }

 

예제5)

  <body>
    <div class="container">
      <div class="item child">
        <div class="item-child">item-child</div>
      </div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      /* flex item 개념을 사용하려면
      부모요소가 flex container 이어야 한다*/
      .container {
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;

        width: 100vw;
        height: 100vh;
      }
      .item {
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;

        background-color: darkslategray;
        width: 42vw;
        height: 42vh;
        border-radius: 10px;
      }
      .item-child {
        background-color: darkolivegreen;
        width: 21vw;
        height: 21vh;

        font-size: 21px;
        font-weight: bold;
        text-align: center;
        line-height: 21vh;
        border-radius: 10px;
      }

 

예제6)

  <body>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      /* flex item 개념을 사용하려면
      부모요소가 flex container 이어야 한다*/
      .container {
        /* 기본값 row / start */
        display: flex;
        flex-direction: row;
        justify-content: start;

        /* 줄바꿈 활성화 wrap.. 기본값 nowrap */
        flex-wrap: nowrap;
        flex-wrap: wrap;
        border: 2px solid darkslategray;
        border-radius: 10px;
      }
      .item {
        width: 200px;
        height: 200px;
        background-color: darkslategray;
        margin: 5px;
        border: 2px solid darkolivegreen;
        border-radius: 10px;

        text-align: center;
        line-height: 200px;
      }

 

예제7)

  <body>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      /* flex item 개념을 사용하려면
      부모요소가 flex container 이어야 한다*/
      .container {
        display: flex;
        /* flex-direction: row;
        flex-wrap: nowrap;
        단축 속성 */
        flex-flow: row wrap;
      }
      .item {
        width: 100px;
        height: 100px;
        background-color: darkslategray;
        margin: 5px;
        border: 2px solid darkolivegreen;
        border-radius: 10px;

        display: flex;
        justify-content: center;
        align-items: center;
      }

 

예제8)

  <body>
    <div class="container">
      <div class="item item1">1</div>
      <div class="item item2">2</div>
      <div class="item item3">3</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      .container {
        display: flex;
        border: 2px solid darkslategray;
        padding: 10px;
      }
      .item {
        width: 100px;
        height: 100px;
        margin: 5px;
        border: 2px solid darkslategray;
        border-radius: 10px;

        display: flex;
        justify-content: center;
        align-items: center;
      }
      /* 1.flex-grow 속성이란
      값의 비율에 따라 남는 공간을 분배한다 */
      .item1 {
        flex-grow: 1;
      }
      .item2 {
        flex-grow: 2;
      }
      .item3 {
        flex-grow: 3;
      }

 

예제9)

  <body>
    <div class="container">
      <div class="item item1">1</div>
      <div class="item item1">1</div>
      <div class="item item1">1</div>
      <div class="item item2">2</div>
      <div class="item item2">2</div>
      <div class="item item2">2</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      .container {
        display: flex;
        border: 2px solid darkslategray;
        padding: 10px;
      }
      .item {
        width: 150px;
        height: 150px;
        margin: 5px;
        border: 2px solid darkslategray;
        border-radius: 10px;

        display: flex;
        justify-content: center;
        align-items: center;
      }
      /* 2.flex-shrink 속성
      화면의 크기가 작아질 때 값의 비율에 따라 축소된다.
      즉, 공간이 부족할 때 얼마나 flex 요소가 축소될 지 결정한다
      기본값은 1이다. 숫자가 클수록 더 작아진다. */
      .item1 {
        flex-shrink: 1;
      }
      .item2 {
        flex-shrink: 2;
      }

 

예제10)

  <body>
    <div class="container">
      <div class="item item1">1</div>
      <div class="item item2">2</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      .container {
        display: flex;
        border: 5px solid darkslategray;
        padding: 10px;
      }
      .item {
        width: 150px;
        height: 150px;
        margin: 5px;
        border: 5px solid darkslategray;
        border-radius: 10px;

        display: flex;
        justify-content: center;
        align-items: center;
      }
      /* 3.flwx-basis 속성
      flex 요소의 기본크기를 설정한다 */
      .item1 {
        flex-basis: 300px;
        flex-grow: 1;
      }
      .item2 {
        flex-basis: 150px;
      }

 

예제11)

  <body>
    <div class="container">
      <div class="item item1">1</div>
      <div class="item item2">2</div>
      <div class="item item3">3</div>
    </div>
  </body>
      body {
        margin: 0;
        padding: 0;
        height: 100vh;
        width: 100vw;
        box-sizing: border-box;
      }
      .container {
        display: flex;
        border: 5px solid darkolivegreen;
        padding: 10px;
      }
      .item {
        width: 150px;
        height: 150px;
        margin: 5px;
        border: 5px solid darkolivegreen;
        border-radius: 10px;

        display: flex;
        justify-content: center;
        align-items: center;
      }
      /* 4.flex 단축속성
      1.flex-grow, 2.flex-shrink, .3flex-basis 순서대로
      한번에 정의한다
      flex:1
      flex-grow:1, flex-shrink:1, flex-basis:0
      flex:2
      flex-grow:2, flex-shrink:1, flex-basis:0
      */
      .item1 {
        flex: 1;
      }
      .item2 {
        flex: 2;
      }
      .item3 {
        flex: 3;
      }

 

예제12)

  <body>
    <h3>align-content 속성을 알아보자</h3>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
      <div class="item">8</div>
      <div class="item">9</div>
      <div class="item">10</div>
    </div>
  </body>
      .container {
        height: 800px;
        background-color: darkslategray;

        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        align-content: space-between;
        /* align-items
        한 줄에 대한 교차축 정렬의 설정
        align-contnet
        wrap 속성이 발동했을 때 정렬의 설정*/
      }
      .item {
        width: 100px;
        height: 100px;
        margin: 2px;
        background-color: darkolivegreen;
        border-radius: 20px;

        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
      }

 

예제13)

  <body>
    <div class="container">
      <div class="up">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
      </div>
      <div class="middle">
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
      </div>
      <div class="down">
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
      </div>
      </div>
    </div>
  </body>
      .container {
            display: flex;
            justify-content: space-between;
            height: 100vh;
      }
      .up {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            background-color: darkolivegreen;
      }
      .middle {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            background-color: darkolivegreen;
      }
      .down {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            background-color: darkolivegreen;
      }
      .item {
        width: 100px;
        height: 100px;
        margin: 10px;
        background-color: darkolivegreen;
        border-radius: 20px;
        font-size: 30px;

        display: flex;
        justify-content: center;
        align-items: center;
      }

 

도전과제)

<body>
    <header>
      <div class="inner">
        <!-- 내가 만든 css 네이밍은 하이픈 두개를 사용한다
         탬플릿과 충돌을 피하기 위해서다 -->
        <div class="head--container">
          <div class="head--brand">
            <a href="https://naver.com">텐코딩</a>
          </div>
          <div class="head--brand">
            <a href="https://naver.com">텐코딩 블로그</a>
          </div>
        </div>
      </div>
    </header>

    <!-- 메인 이미지 섹션
     너비가 화면의 100%를 차지하게 된다  -->
    <section class="main">
      <div class="main--container">
        <div class="inner">
          <div class="title--container">
            <div class="title">주도적 학습에 집중합니다</div>
            <div class="message">
              스스로 문제를 해결하는 능력<br />
              스스로 재미를 찾아내는 능력<br />
              스스로 찾아서 학습하는 능력<br />
            </div>
          </div>
        </div>
      </div>
    </section>

    <!-- 스킬 섹션 -->
    <section>
      <div class="inner">
        <div class="skill--container">
          <div class="skill">
            <i class="fa-brands fa-java skill--icon"></i>
            <div class="sill--title">
              <div class="skill--name">백엔드</div>
              <div class="skill--usage">ERP/WEB/APP</div>
            </div>
          </div>
          <div class="skill">
            <i class="fa-solid fa-mobile-screen skill--icon"></i>
            <div class="sill--title">
              <div class="skill--name">백엔드</div>
              <div class="skill--usage">Mobile/Web/Desktop</div>
            </div>
          </div>
          <div class="skill">
            <i class="fa-solid fa-database skill--icon"></i>
            <div class="sill--title">
              <div class="skill--name">백엔드</div>
              <div class="skill--usage">데이터분석</div>
            </div>
          </div>
          <div class="skill">
            <i class="fa-brands fa-python skill--icon"></i>
            <div class="sill--title">
              <div class="skill--name">백엔드</div>
              <div class="skill--usage">크롤링/데이터분석</div>
            </div>
          </div>
        </div>
      </div>
    </section>
    <!-- 로드맵 섹션 -->
    <section>
      <div class="inner">
        <!-- 상단 -->
        <div class="roadmap--container">
          <div class="roadmap--title--container">
            <div class="roadmap--title">블로그 및 서적</div>
            <div class="arrow--container">
              <i class="fa-solid fa-circle-chevron-left slide--prev"></i>
              <i class="fa-solid fa-circle-chevron-right slide--next"></i>
            </div>
          </div>
        </div>
        <!-- 하단1 -->
        <ul class="class--list">
          <li class="class--card">
            <img src="https://picsum.photos/id/10/300/300" alt="샘플이미지" />
            <a href="https://naver.com" target="_blank">
              <div class="class--container">
                <div class="class--skill">
                  <div class="class--type">학습방법</div>
                  <div class="class--format">블로그</div>
                </div>
                <div class="class--desc">
                  <div class="class--title">IT는 배우는 방법을 익혀야 합니다</div>
                  <div class="class--title">IT를 배우는 전략</div>
                </div>
              </div>
            </a>
          </li>
          <!-- 하단2 -->
          <li class="class--card">
            <img src="https://picsum.photos/id/11/300/300" alt="샘플이미지" />
            <a href="https://naver.com" target="_blank">
              <div class="class--container">
                <div class="class--skill">
                  <div class="class--type">출판서적</div>
                  <div class="class--format">서적</div>
                </div>
                <div class="class--desc">
                  <div class="class--title">비전공자를 위한 파이썬</div>
                  <div class="class--title">파이썬 프로그래밍</div>
                </div>
              </div>
            </a>
          </li>
          <!-- 하단3 -->
          <li class="class--card">
            <img src="https://picsum.photos/id/12/300/300" alt="샘플이미지" />
            <a href="https://naver.com" target="_blank">
              <div class="class--container">
                <div class="class--skill">
                  <div class="class--type">학습방법</div>
                  <div class="class--format">블로그</div>
                </div>
                <div class="class--desc">
                  <div class="class--title">객체지향 프로그래밍 자바</div>
                  <div class="class--title">SOLID 원칙이란</div>
                </div>
              </div>
            </a>
          </li>
          <!-- 하단4 -->
          <li class="class--card">
            <img src="https://picsum.photos/id/13/300/300" alt="샘플이미지" />
            <a href="https://naver.com" target="_blank">
              <div class="class--container">
                <div class="class--skill">
                  <div class="class--type">출판서적</div>
                  <div class="class--format">서적</div>
                </div>
                <div class="class--desc">
                  <div class="class--title">데이터분석 및 DBA</div>
                  <div class="class--title">관계형 데이터베이스</div>
                </div>
              </div>
            </a>
          </li>
          <!-- 하단5 -->
          <li class="class--card">
            <img src="https://picsum.photos/id/14/300/300" alt="샘플이미지" />
            <a href="https://naver.com" target="_blank">
              <div class="class--container">
                <div class="class--skill">
                  <div class="class--type">학습방법</div>
                  <div class="class--format">블로그</div>
                </div>
                <div class="class--desc">
                  <div class="class--title">플러터 프레임워크</div>
                  <div class="class--title">크로스플랫폼이란</div>
                </div>
              </div>
            </a>
          </li>
          <!-- 하단 끝 -->
        </ul>
      </div>
    </section>
  </body>
* {
    box-sizing: border-box;
}
/* a 하이퍼링크 태그 스타일 초기화 */
a {
    /* 모든 요소 초기화 */
    all: unset;
}
a:link {
    text-decoration: none;
    color: dimgray;
}
a:visited {
    text-decoration: none;
    color: dimgray;
}
a:active {
    text-decoration: none;
    color: dimgray;
}
a:hover {
    text-decoration: none;
    color: dimgray;
}
.inner {
    /* 가로 사이즈가 1200px 넘는 해상도에서
    미디어쿼리 max-width 설정할 것 */
    width: 100%;
    /* align-items 등으로 수직 가운데 정렬을 위해
    미리 height 크기를 설정한다 */
    height: 100%;
    /* 가운데 정렬 */
    margin: 0 auto;
    /* 좌우 패딩 값을 주어 좌우에 딱 붙지 않도록 설정 */
    padding: 0 2rem;
    /* 넘치는 영역에 대해서 표시가 안되도록 설정 */
    overflow: hidden;
}
header {
    width: 100%;
    height: 60px;
    background-color: #fff;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1000;
}
.head--container {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
/* 자손선택자(공백 중요)
head-containder 내 모든 자손요소들 중
.head--brand 클래스인 요소들만 선택 */
.head--container .head--brand {
    font-weight: bold;
    font-size: 1.2rem;
}
.head--container .head--brand a:hover {
    cursor: pointer;
    color: salmon;
}
section {
    width: 100%;
    background-color: #fff;
}
.main {
    height: 360px;
    background-repeat: no-repeat;
    /* x축 y축 */
    background-position: center 20%;
    background-size: cover;
    z-index: 1;
}
.main--container {
    width: 100%;
    height: 100%;
    background-color: royalblue;
    opacity: 0.5;
    z-index: 2;
}
.title--container {
    margin-top: 100px;
}
.title {
    font-size: 2rem;
    font-weight: bold;
    color: #fff;
    margin-bottom: 0.5rem;
}
.message {
    font-size: 1.4rem;
    font-weight: normal;
    color: #fff;
    line-height: 2rem;
}
.skill--container {
    width: 100%;
    height: 100%;
    margin: 1rem;

    display: flex;
    justify-content: space-around;
    align-items: center;

    flex-wrap: wrap;
    /* 상하 좌우 */
    padding: 1rem, 0;
    /* 다음줄로 넘어가면 여백 */
    gap: 30px;
}
.skill {
    width: 22%;
    height: 100%;
    background-color: #fff;
    display: flex;
    border: 1px solid lightgray;
    border-radius: 10px;
    padding: 0.5rem 1rem;
    /* x축 y축 blur-radius 색상 */
    box-shadow: 10px 5px 5px rgb(0, 0, 0, 0.5);
    min-width: 200px;
    transition: 0.2s;
}
.skill:hover {
    transform: translate(0, -3px);
}
.skill--icon {
    font-size: 2rem;
    margin: 0 10px;
    color: royalblue;
}
.skill--title {
    display: flex;
    flex-direction: column;
    align-content: center;
}
.skill--name {
    font-size: 0.9rem;
    font-weight: 400;
    margin-bottom: 0.2rem;
    color: dimgray;
}
.skill--usage {
    font-size: 0.8rem;
    color: dimgray;
}
.roadmap--container {
    width: 100%;
    margin-top: 1rem;
}
.roadmap--title--container {
    display: flex;
    justify-content: space-between;
}
.roadmap--title {
    font-size: 1.3rem;
    font-weight: bold;
    color: dimgray;
}
.slide--prev {
    font-size: 2rem;
    font-size: 2rem;
    color: lightgray;
}
.slide--next {
    font-size: 2rem;
    font-size: 2rem;
    color: lightgray;
}
/* ul 태그 초기화 */
ul {
    list-style: none;
    padding: 0;
    margin: 0 0;
}
/* 직접 해보기 */
.class--list {
    display: flex;
    flex-wrap: nowrap;
    justify-content: start;
}
.class--card {
    border-radius: 10px;
    margin: 10px 10px;
    overflow: hidden;
    flex-shrink:0;
    border: 0px solid black;
    box-shadow: 5px 5px 5px rgb(0, 0, 0, 0.5);
}
.class--skill {
    display: flex;
    justify-content: space-between;
    margin: 1rem;
}
.class--type {
    font-size: 1.2rem;
    font-weight: bold;
    color: dimgray;
}
.class--format {
    font-size: 1rem;
    color: white;
    background-color: royalblue;
}
.class--desc {
    margin: 1rem 1rem;
    color: dimgray;
}
/* 미디어쿼리 사용 */
@media (min-width: 1200px) {
    /* 화면의 크기가 1200px보다 크면 */
    .inner {
        max-width: 1200px;
    }
}