NeatCoder's Lab

CSS positioning tricks 본문

Web Development/HTML&CSS

CSS positioning tricks

NeatCoder 2021. 1. 2. 21:24

CSS에서는 많은 방법으로 요소들을 배치시킬 수 있다.
HTML은 normal flow상 모든 것들이 위에서 아래로 배치된다. 그렇다면 우리는 어떻게 수평으로 요소들을 정렬 시킬 수 있을까? 그렇게 배치하기 위해서 대표적으로 네가지 방법을 알아보도록 하자.

Float를 이용한 수평정렬

본래 Float는 그림을 텍스트들이 감싸게하기 위해서 만들어진 방법이다. 먼저 어떻게 사용하는지 보자.

float라는 단어처럼 원래 웹페이지에서 이미지를 어떻게 띄워서 텍스트와 함께 배치할 것인가에 대한 속성이다.

  • inherit : 부모 요소에서 상속한다.
  • left: 왼쪽에 부유하는 블록 박스를 생성, 페이지 내용은 박스 오른쪽에 위치하고 위에서 아래로 흐른다.
  • right: 오른쪽에 부유하는 블록 박스를 생성하고 페이지 내용은 박스 왼쪽에 위치하며 위에서 아래로 흐른다. 이후 요소에 clear속성이 있으면 페이지 흐름이 달라진다. none이 아니라면 display 속성은 무시된다. 고 한다.
  • none: 요소를 부유시키지 않는다. 이게 default값이다.
  • inline-start: 요소가 그것을 포함하고 있는 block의 시작 부분에서 부유한다.
  • inline-end: 요소가 그것을 포함하고 있는 block의 끝 부분에서 부유한다.
    dispaly값이 none인 요소에는 아무런 효과가 없다.

레이아웃에서의 float

float라는 속성은 원래 이미지와 텍스트 배치 용도로 등장했지만, 요즘은 레이아웃용으로 많이 사용하고 있다고 한다. float는 기본적으로 오른쪽, 왼쪽으로 객체를 띄워서 정렬하는 속성이다. 정렬하면 그 주위로 텍스트가 둘러싸는 형태가 되게되는데 이때 글자가 따라 붙지 않게 하기 위해서 clear라는 속성을 사용한다.

float시킨 요소는 normal flow에서 벗어나서 존재하게 되는데 그것을 담고 있는 box나 또다른 부유된 요소를 만나기전까지 왼쪽이나 오른쪽으로 이동된다.

float를 해서 부유시킨 요소는 같은 box안에서 부유된 요소들과 같은 높이를 가진다.

이것은 display의 속성을 바꾸지 않는다. block요소가 inline이 되었다거나 그런 개념은 아니다.

Position을 이용하기

CSS에서 position property를 사용해서 요소를 배치할 수 있다. 먼저 position property의 value는 5가지가 있다. static, relative, absolute, fixed, sticky. 이제 각각에 대해서 알아보자.

static

요소는 계속해서 HTML상의 normal flow상에 위치하게되며 offset으로 줄 수 있는 top, right, bottom, left 그리고 z-index 가 아무런 효과를 가지지 않는다. 그리고 static이 default값이다.

relative

요소는 계속해서 문서의 normal flow상에 위차하게 된다. 다른 점은 이전 자신의 static 당시의 위치에 대해서 offset값들이 들어가서 움직이게 할 수 있다. 기억해야할 부분은 기준이 원래 자신의 위치라는 것이다.

absolute

absolute는 요소가 문서의 normal flow로부터 벗어나게 한다. 그리고 페이지 layout에서 요소를 위해서 따로 공간을 만들어주지 않는다. 즉 없는 것처럼 처리해버린다. 중요한 부분은 absolute로 요소의 position property를 설정할 경우 그것의 가장 가까운 조상 중에 position이 static이 아닌 것을 기준으로 위치된다는 것이다. 만약 없다면 가장 상위에 있는 요소의 block을 기준으로 삼게된다. 그리고 top, right, bottom, left를 이용해서 설정할 수 있다.

absolute로 설정할 경우 z-index가 auto가 아닐때 새로운 stacking context를 생성한다. 그래서 absolute으로 position된 box들의 margin과 collapse하지 않는다.

fixed

fixed 또한 요소가 문서의 normal flow로부터 벗어난다. 그리고 absolute와 마찬가지로 normal flow상에서 요소를 위해서 따로 공간을 만들어주지 않는다. fixed의 경우 기준점 그 조상 요소 중에 transform, perspective 또는 조상 요소가 스스로 containing block처럼 행동하는 filter의 value가 none이 아닌 값으로 설정되었을때를 제외하면 viewport에 의해 만들어진 초기 containing block이다. 이부분은 브라우저마다 inconsistencies가 있다고한다… 그러고 나서 top, right, bottom, left로 조정할 수 있다.

sticky

sticky의 경우 요소는 normal flow상에 위치한다. 가장 가까운 조상 중에 스크롤이 있는 조상과 table-related 요소들을 담고 있는 containing block을 기준으로 위치하게 된다. 그러고나서 top, right, bottom, left를 통해서 조정할 수 있는데 이 offset들은 다른 요소들에 영향을 미치지 않는다.

이 value의 경우 항상 stacking context를 만들어낸다. 그리고 쉽게 이해하면 sticky의 경우 가장 가까운 조상 중에 “scrolling mechanism”이 있는 요소에 “붙는다”

scrolling element가 fixed 또는 sticky를 포함할 경우 성능과 접근성에 문제가 있을 수 있다는걸 꼭 알아두자.

Flex

flex라는 속성을 이용해서 이제는 많은 것들을 수평 정렬을 시킬 수 있게되었다.
수평 정렬뿐만 아니라 정렬된 item들을 제어하는 것까지 굉장히 쉬워졌다.

기본적인 문법은 css에서 다음과 같다.

flex: auto;
flex: initial;
flex: none;

display: flex;

flex 속성은 1개에서 3개까지의 값을 써서 사용할 수 있다.

  • 한개의 value 를 사용할 경우의 syntax는 flex-grow의 속성으로 받아들여진다. 그리고 정수만 올 수 있는데 그 정수가 2일경우 flex-grow가 2로 설정되는 것이다.
  • 만약 단위가 뒤에 붙게된다면.. 예를 들어 flex: 10em; 그렇다면 그 value는 flex-basis의 width또는 height로 받아들여진다.
  • 만약 2개의 value가 올 경우 두개의 value는 각각 flex-grow, flex-shrink의 속성 값으로 받아들여지게 된다. 하지만 다음처럼 flex:1 30px 처럼 단위가 붙게되면 그 값은 flex-basis의 값으로 들어가게 된다.
  • flex가 세개의 value가 들어가있으면 각각 flex-grow, flex-shrink, flex-basis로 값이 받아들여진다.

Two-value syntax:

  • The first value must be:
    • a <number> and it is interpreted as <flex-grow>
  • The second value must be one of:
    • a <number>: them it is interpreted as <flex-shrink>
    • a valid value for width: then it is interpreted as flex-basis

Three-value syntax: the values must be in following order:

  1. flex-grow
  2. flex-shrink
  3. a valid value for width for <flex-basis>

각각에 따라서 쓸 수 있는 값(value)들은 다음과 같다

  • initial - item이 그 기존 속성대로 width, height가 sizing된다. 또한 container를 맞추기 위해서 줄어들기도 한다. 하지만 flex container의 빈 공간을 흡수하기위해서 커지지는 않는다.
  • auto - item이 그 기존 속성대로 width, height가 sizing된다. 하지만 initial과는 다른 점은 만약 자신의 크기보다 flex container가 크다면 그 여유 공간까지 흡수하기 위해서 커지기도 한다는 것이다. 또 줄어들기도 한다.
  • none - none으로 설정할 겨우 inflexible해져서 정해진 width과 height대로만 sizing을 하게 된다.
  • flew-grow - item의 grow를 설정할 수 있는 속성이다. 음수는 사용할 수 없고 1이 default value로 설정되어 있다.
  • flex-shrink - item의 shrink하는 정도를 설정하는 속성이다. 음수를 값으로 사용할 수 없고 default는 1이다.
  • flex-basis - 0으로 default가 되어 있다. item의 기본 너비를 설정한다. auto일 경우 width, height등의 속성으로 Item의 너비를 설정할수 있다.

flex에 대해서는 따로 포스팅을 한번 더 정리해서 해보는 것도 좋을 것 같다.. flex에 대해서는 알아야할 것이 너무도 많기 때문에..일단 flex를 이용해서 수평정렬이 대단히 쉬워졌다는 것만 기억하고 flex는 현재 모든 브라우저에서 지원하고 IE의 경우 11이상 부터 가능하다.

inline-block

display: inline-block;

이런식으로 display의 속성을 지정하는 것으로 시작된다. inline 요소처럼 전후 줄바꿈이 전혀 없이 수평으로 배치도니다. 그렇지만 block요소처럼 가로방향 width, height과 margin, padding을 지정할 수 있다. 보통 inline-block을 많이 쓰는 요소로는 button이 있다.

이렇게 네가지 css positioning trick들에 대해서 알아보았다. 기본적으로 이렇게 알고 있으면 배치시킬때 4가지를 사용해서 할수 있다.물론 flex와 grid에 대해서는 더 많이 알아보아야 한다.

그렇다면 이제 우리가 알아본 방법으로 다음과 같은 layout을 만들어보자.

float 이용하기

먼저 float를 이용하려면 마크업이 필요한데 다음과 같이 html을 짰다고 가정하자.

 <div class="Parent">
    <div class="child child1">1</div>
    <div class="child child2">2</div>
    <div class="child child3">3</div>
    <div class="child child4">4</div>
    <div class="child child5">5</div>
</div>

보통은 이렇게 마크업되어있지 않지만 그래도 가장 간단한 것부터 해보도록 하자.

.parent {
  background: white;
  width: 300px;
  padding: 0;
  margin: 0;
}
.child {
  margin: 10px;
}
.child1,
.child2 {
  margin: 6px;
  width: 66%;
  height: 150px;
  float: left;
}
.child1 {
  background: #f1a90e;
}
.child2 {
  background-color: #685f22;
}
.child3,
.child4,
.child5 {
  width: 30%;
  height: 100px;
  margin-left: 68%;
}
.child3 {
  background-color: #f9f2e3;
}
.child4 {
  background-color: #e4797f;
}
.child5 {
  background-color: tomato;
}

위에서 보이는 것과 같이 float를 두번 사용하였다. 먼저 float를 사용하기 전에 각각에 대해서 width를 정해놓는 것이 좋다. 그러고나서 float를 이용해서 child1, child2를 왼쪽으로 부유시킨다. 그렇다면 각각의 요소들은 그래도 순서대로 normal-flow에 존재하게된다. float에서의 trick은 결국 다른 하나가 부유되면 다른 하나는 그것이 없는것처럼 취급해 위로 올라가는 것을 이용하는 것이다. 그래서 float로 배치시킬 것이면 markup에서 각각이 나오는 순서를 파악할 필요가 있다.

아무튼 child1, child2를 먼저 부유시켜서 왼쪽으로 붙여주면 그것들은 알아서 왼쪽으로 붙게되고 child3,4,5는 child1,2의 밑으로 들어가게된다. child3,4,5는 block요소이기때문에 아래로 쌓이고 그래서 margin-left 일정 거리만큼줘서 배치를 완성시킬 수 있다.

결국 조합은 하나를 float를 시켜서 margin이나 width를 조정하는 것이다. 다음과 같은 결과물이 완성된다.

inline-block 이용하기

이번에는 inline-block을 이용해보자. 이 display:inline-block을 쓰는 방법은 생각보다 간단하다.

.child {
  margin: 5px;
  display: inline-block;
}
.child2,
.child4,
.child5 {
  float: right;
}

inline-block으로 묶을경우 html 마크업상 순서를 생각해야한다. inline처럼 왼쪽에서 오른쪽으로 순서를 count해야하기 때문에 배치는

child1|child2
child3|child4
|child5

와 같다. 모든 것에 inline-block의 속성으로 주게되면 block이지만 inline처럼 수평으로 쌓이기 때문에 위에서 아래로, 그렇지만 왼쪽에서 오른쪽으로 쌓이기 때문에 아까처럼 건드려야할 것이 달라진다. 다시 말하지만 이것은 연습이기 때문에 이것을 맹신할 수는 없다. 마크업에 따라서 많이 변하고 또 그에 맞춰서 그때그때 유연하게 대처해야한다. 아무튼 이번에는 inline-block을 주고나서 float:right로 줌으로써 이것을 해결했다. 그림은 다음과 같다.

position으로 해결하기

position으로 해결하는 방법은 간단하다. child1과 child2를 묶어서 position:absolute 그리고 left:0를 주면 된다. 그러고나서 child2는 margin-top을 줘서 밑으로 옮겨주면되고 child3,4,5는 margin-left를 설정해줘서 그저 오른쪽으로 밀어주기만하면 된다. 결과 코드는 다음과 같다.

.parent {
    background: white;
    width: 400px;
    padding: 0;
    margin: 0;
    position: relative;
  }
  .child {
    margin: 5px;
    width: 100px;
    height: 60px;
  }
  .child1,
  .child2 {
      position: absolute;
      left:0;
      width: 40%;
      height: 80px;
  }
  .child2 {
    background-color: #685f22;
    margin-top: 90px;
  }
  .child3,
  .child4,
  .child5 {
      margin-left: 45%;
  }

이 역시 부모에 position:relative 그리고 하위에 position:absolute를 주는 방식으로 해결할 수 있다.
마지막으로 얻게 되는 결과물은 다음과 같다.

이렇게해서 각각에 대해서 알아보았다. 각각의 장단점이 다 있다는 것을 유념하고 배치와 element를 보면서 어떠한 방법을 쓰는 것이 가장 유용할지 그때그때 유연하게 대처하도록하자.

'Web Development > HTML&CSS' 카테고리의 다른 글

input 그리고 form에 대해서  (0) 2021.01.05
CSS Basic Syntax  (0) 2021.01.04
Hide content, Box-sizing, BFC  (0) 2021.01.04
HTML Basic syntax 2  (0) 2021.01.04
HTML Basic Syntax 1  (0) 2021.01.01
Comments