프로그래밍/css 심화

CSS 심화 공부(6) - 플렉스 컨테이너의 속성(2) 정렬 방식 : justify-content, align-items, align-content

lamarcK 2025. 3. 12. 17:38

플렉스 컨테이너의 속성(2) - 정렬 속성

이전에 플렉스 컨테이너의 레이아웃 방식을 정하는 속성을 알아봤다.

이번에 알아볼 것은 플렉스 컨테이너의 정렬 속성이다. 

1. justify-content (주축 정렬)

플렉스 컨테이너의 주축(main axis) 방향으로 플렉스 아이템을 정렬한다.

더보기
  • flex-start: 아이템을 주축 시작점에 정렬합니다.
  • flex-end: 아이템을 주축 끝점에 정렬합니다.
  • center: 아이템을 주축 중앙에 정렬합니다.
  • space-between: 첫 번째 아이템은 시작점에, 마지막 아이템은 끝점에 정렬하고 나머지 아이템은 균등하게 분할합니다.
  • space-around: 아이템 주변에 균등한 여백을 추가합니다.
  • space-evenly: 아이템 사이와 양 끝에 균등한 여백을 추가합니다

 

justify-content의 경우 다음 그림과 같이 적용된다.

보다시피 '내용(content)'의 정렬 방법이다. 텍스트를 양쪽 정렬, 왼쪽 정렬, 오른쪽 정렬 하는 것과 근본적으로 차이는 없는 방식이다.

2. align-items (교차축 단일 행/열 정렬)

교차축 방향으로 단일 행 또는 단일 열의 플렉스 아이템을 정렬한다.

교차축은 주축에 수직인 방향이며, 주축이 가로 방향일 경우 세로 방향, 세로 방향일 경우 가로 방향이 된다.

더보기
  • flex-start: 아이템을 교차축 시작점에 정렬합니다.
  • flex-end: 아이템을 교차축 끝점에 정렬합니다.
  • center: 아이템을 교차축 중앙에 정렬합니다.
  • stretch: 아이템을 교차축 방향으로 늘려 컨테이너를 채웁니다. (기본값)
  • baseline: 아이템의 베이스라인을 기준으로 정렬합니다.

align-items의 경우 다음과 같이 적용된다.

stretch 같은 경우에는 플렉스 컨테이너(부모 요소)만큼 늘어나는 기능이다.

baseline의 경우 조금 특이한데 베이스 라인을 기준으로 정렬을 한다.

 

베이스라인(baseline)이란?

  • 텍스트를 포함하는 요소에서 텍스트의 아래쪽 기준선을 의미합니다.
  • 폰트의 종류와 크기에 따라 베이스라인의 위치가 달라집니다.
  • 일반적으로 텍스트가 포함된 요소는 베이스라인을 기준으로 정렬됩니다.

즉 텍스트의 아래쪽 선을 기준으로 정렬이 된다는 얘기인데 패딩으로 여백을 주거나 font-size가 다른 경우 텍스트의 위치가 제각각이 되지만 베이스라인(baseline)을 사용할 경우 텍스트의 아래쪽을 기준선으로 삼아서 아이템이 정렬이 되기 때문에 텍스트 크기나 스타일이 다르더라도 시각적으로 안정적인 레이아웃을 만들 수 있다.

3. align-content (교차축 여러 행/열 정렬)

 

교차축 방향으로 여러 행 또는 여러 열의 플렉스 아이템을 정렬한다.

flex-wrap: wrap; 속성이 설정되어 여러 줄의 아이템이 생성될 때 사용한다.

단일 행 또는 단일 열에서는 적용되지 않는다.

더보기
  • flex-start: 아이템 줄들을 교차축 시작점에 정렬합니다.
  • flex-end: 아이템 줄들을 교차축 끝점에 정렬합니다.
  • center: 아이템 줄들을 교차축 중앙에 정렬합니다.
  • space-between: 첫 번째 아이템 줄은 시작점에, 마지막 아이템 줄은 끝점에 정렬하고 나머지 줄은 균등하게 분할합니다.
  • space-around: 아이템 줄 주변에 균등한 여백을 추가합니다.
  • stretch: 아이템 줄들을 교차축 방향으로 늘려 컨테이너를 채웁니다.

작동하는 방식은 위에 나온 속성과 동일하지만 align-content는 반드시 wrap으로 여러 행 또는 여러 열의 플렉스 아이템이 있어야만 적용된다. 1행 혹은 1열일 경우 속성이 작동하지 않는다.


그렇다면 왜 1행이나 1열에 align-content가 작동하지 않도록 설계했을까?

그 이유는 다음과 같다.

 

1. 정렬 대상의 부재

align-content는 플렉스 컨테이너 내의 여러 줄 또는 여러 열의 플렉스 아이템 그룹(줄/열)을 정렬하는 데 사용된다. 1줄 또는 1열의 경우, 아이템 그룹이 하나밖에 존재하지 않으므로 align-content가 정렬할 대상 자체가 아니라는 것이다.

 

2. 명확한 역할 분담

CSS 플렉스박스 레이아웃은 각 속성의 역할을 명확하게 분리하여 설계되었다.

align-items는 각 아이템을 개별적으로 정렬하는 데 사용되고 align-content는 아이템 그룹(줄/열)을 정렬하는 데 사용되도록 역할을 분담한 것이다.

 

3. 불필요한 복잡성 방지

만약 1줄 또는 1열에도 align-content가 작동하도록 설계되었다면, 개발자는 불필요한 속성을 설정해야 하는 경우가 발생할 수 있다. 다중 행, 열이 특정 상황에서 1줄이나 1열로 바뀔 경우 align-content의 속성이 적용되면 그것이 적용되지 않도록 다시 코드를 짜야해서 코드의 복잡성이 증가할 수 있다.

 

4. 일관성 유지

CSS 플렉스박스 레이아웃은 다양한 레이아웃 상황에서 일관된 동작을 보장하도록 설계되었는데 align-content의 동작 방식을 제한함으로써 개발자가 예측 가능한 레이아웃을 만들 수 있다.


4. align-self

위에서 나온 정렬 기능들은 전부 아이템 전체를 대상으로 하고 있다. 하지만 실제 웹페이지를 보면 반드시 컨테이너 상의 아이템이 모두 동일한 형식을 가지게 디자인 되는 것은 아니다.

다양한 디자인 요구사항을 충족하기 위해 아이템들의 크기, 모양, 정렬 방식 등을 다르게 설정해야 하는 경우가 있는데 그럴 경우 사용할 수 있는 것이 바로 align-self 속성이다.

align-self 속성 값

더보기
  • auto (기본값):
    • 플렉스 컨테이너의 align-items 속성 값을 상속받습니다.
    • 만약 부모 컨테이너에 align-items가 설정되어 있지 않다면 stretch처럼 작동합니다.
  • flex-start:
    • 아이템을 컨테이너의 시작 부분에 정렬합니다.
  • flex-end:
    • 아이템을 컨테이너의 끝 부분에 정렬합니다.
  • center:
    • 아이템을 컨테이너의 가운데에 정렬합니다.
  • stretch:
    • 아이템을 컨테이너의 교차축 방향으로 늘려 컨테이너를 채웁니다.
  • baseline:
    • 아이템의 베이스라인을 기준으로 정렬합니다.

다만 align-self 속성은 align-content 속성이 있을 경우 제대로 작동을 하지 않는다.

두 속성이 서로 다른 방식으로 플렉스 아이템의 정렬을 제어하기 때문이다.

 

원본 박스에 각각 end와 center를 적용해서 하나의 요소만 별개로 움직인 예시이다.

.box1{align-self:flex-end}
.box1{align-self:center}

참고점

align-self 속성은 개별 요소에게 적용하는 것은 물론 이렇게 하나하나 요소에 속성을 적용해서 따로따로 놀게 만들 수도 있다.

역으로 말하자면 self 속성을 모두 동일하게 하면 모두 동일한 모양을 취하게 만들 수도 있다는 것이다.

즉, align-items 속성은 플렉스 컨테이너 안의 모든 아이템에 align-self 속성을 적용한 것과 거의 동일한 결과를 나타낸다고도 할 수 있다.


실제 예제

사실 위에서 나온 이미지들은 이번 글에서 설명한 요소를 적당히 사용해서 이미지를 만든 것이다.

실제 사용한 코드는 다음과 같다.

CSS

더보기
.container1 {width: 1200px;
height: 800px;
display: flex;
border: 2px solid black;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
align-content: flex-start;
background-color: #fffeed;
}

.container2 {width: 1200px;
  height: fit-content;
  display: flex;
  flex-direction: row;
  align-content: flex-start;
  justify-content: center;
  font-size: 50px;
  margin-bottom: 10px;
  font-weight: bold;
  }

.m1{width: fit-content;
  height:fit-content;
  display: flex;
  justify-content: center;
  position: relative;
  flex-direction: column;
  align-items: center;
  padding-top: 30px;

  }

  .mbox1, .mbox2, .mbox3, .mbox4, .mbox5, .mbox6{
    width: 500px;
    height: 100px;
    margin: 10px;
    display: flex;
    align-items: center;
    background-color: white;
    border: 4px solid orange;
    padding: 2px;
    position: relative;
  }

.mbox2, .mbox4, .mbox6{margin-left: 50px;}

.mbox1{justify-content: flex-start;}
.mbox2{justify-content: flex-end;}
.mbox3{justify-content:center;}
.mbox4{justify-content: space-between;}
.mbox5{justify-content: space-around;}
.mbox6{justify-content: space-evenly;}

.box1 {background-color: #5a80ff;}
.box2 {background-color: #006e09;}
.box3 {background-color: #ffbc02;}

.box1, .box2, .box3{color: white;
  width: 80px;
  height: 80px;
  font-size: 40px;
  justify-content: center;
  align-items: center;
  display: flex;
  border: 2px solid black;
  margin: 2px;
}

.label2 { /* 추가 */
  margin-left: 50px;
}

.label, .label2{
  font-size: 35px;
  font-weight: bold;
}

HTML

더보기
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container2">justify-content</div>
  <div class="container1">
    <div class="m1">
      <div class="label">flex-start</div> 
        <div class="mbox1">
          <div class="box1">A</div>
          <div class="box2">B</div>
          <div class="box3">C</div>
      </div>
    </div>

    <div class="m1">
      <div class="label2">flex-end</div> 
        <div class="mbox2">
          <div class="box1">A</div>
          <div class="box2">B</div>
          <div class="box3">C</div>
      </div>
    </div>

    <div class="m1">
      <div class="label">center</div> 
        <div class="mbox3">
          <div class="box1">A</div>
          <div class="box2">B</div>
          <div class="box3">C</div>
      </div>
    </div>

    <div class="m1">
      <div class="label2">space-between</div> 
        <div class="mbox4">
          <div class="box1">A</div>
          <div class="box2">B</div>
          <div class="box3">C</div>
      </div>
    </div>

    <div class="m1">
      <div class="label">space-around</div> 
        <div class="mbox5">
        <div class="box1">A</div>
        <div class="box2">B</div>
        <div class="box3">C</div>
      </div>
    </div>

    <div class="m1">
      <div class="label2">space-evenly</div> 
        <div class="mbox6">
        <div class="box1">A</div>
        <div class="box2">B</div>
        <div class="box3">C</div>
      </div>
    </div>
  
  </div> <!-- container1 끝 -->

</body>