FrontEnd/CSS

[CSS] Box Model , Display, Position, float

hayjo 2021. 2. 19. 02:45

BoxModel

Box에는 content, padding, border, margin이 있다.

 

-박스 크기는 이렇게 구해진다.

너비: width + left/padding + left/border + left/margin

높이: height + top/bottom padding + top/border + top/bottom margin

 

-값을 따로 정하지 않으면 기본값 auto가 적용된다. (margin에 auto를 주면 브라우저 중앙에 위치하게 된다.)

-값을 지정할 경우 px, % 등의 단위를 쓴다. 박스모델 관련 속성은 상속되지 않는다.

-top, right, bottom, left가 모두 같다면 margin: 25px; 처럼 한번에 지정해도 된다.

-box-sizing 프로퍼티는 content-box나 border-box을 값으로 받는다. border-box로 지정하는 경우 padding값까지가 박스모델에 포함된다. box-sizing 프로퍼티는 상속되지 않는다.

 

-border-style에는 none | hidden | dotted | dashed(- - -) | solid | double | groove | ridge | inset | outset 가 있다. top, right, bottom, left에 대해 각각 지정도 가능하다. border: none solid dotted dashed라면 순서대로 top 없음 right 일반선 bottm 점선 left - - -선이 나타난다. 3개만 쓰는 경우, right의 속성이 left에도 적용된다.

-모서리를 둥글게 표현하려면 radius를 사용하면 된다. 단위로는 px, em, % 등을 사용한다. 기본적으로는 수평 반지름을 설정하지만, 수직 반지름을 추가해서 여러가지 모양을 만들 수 있다. 각 방향을 표현하려면 border-top-left-radius: 10px;처럼 쓴다. 반지름을 2개 사용해서 border-top-left-radius: 50px 25px; 처럼 표현하거나, border-radius: 50px 0 0 0 / 25px 0 0 0; 처럼 표현한다.

 

-border:로 border-width border-style border-color를 한번에 설정할 수 있다. 5px solid red 처럼 지정하면 된다.

 

 


Position

위치를 정의한다. top, bottom, left, right 프로퍼티와 함께 쓰인다.

-기본값을 static이라고 부른다. 위 >  아래, 왼쪽 > 오른쪽 순으로 배치되고, 자식은 부모의 위치를 기준으로 배치된다. 기존 설정을 초기화할 경우 position: static처럼 쓰면 된다. 이 경우 top, right, bottom, left, z-index의 값은 0이다.

-relative를 주면 top, right, bottom, left, z-index에 준 값이 적용된다. 다른 요소들은 이 요소가 원래 위치에 있는 것처럼 취급된다. 출발 좌표는 부모의 좌표.

-absolute를 주면 부모를 기준으로 출발 좌표가 결정된다. 부모에서 상속 받을 좌표값이 없으면 body에서 상속 받는데, body의 position이 기본값인 static이라면 (0, 0, 0, 0)에서 시작하게 된다.

-position값이 absolute인 경우 다른 요소와의 관계성은 무시된다. 다른 요소들에게는 마치 없는 요소처럼 취급되고, 다른 맥락에서 공간을 점유한다. (absolute를 가지는 요소는 새로운 레이어에 배치되는 느낌?) 다른 요소가 차지하고 있는 자리도 덮어쓸 수 있다.

-absolute인 경우 block 요소더라도 width가 content에 맞게 지정되므로 적절한 width를 줘야한다.

<div class="parent">
  <div class="box relative">relative</div>
  <div class="box relative">relative</div>
  <div class="box absolute">absolute</div>
  <div class="box relative">relative</div>
</div>
.parent {
  position: relative;
  top: 100px;
  left: 100px;
  width: 220px;
  height: 220px;
  border: solid 3px black;
}
.box {
  display: inline-block;
  border: none;
  width: 100px;  /* 안주면 글자 크기만큼 줄어든다 */
  height: 100px;
  background: coral;
  color: white;
}
.relative {
  position: relative;
}
.absolute {
  background: darkgray;
  position: absolute;
}

 

absolute 적용하지 않은 경우

absolute가 적용되지 않으면 다른 요소들이 해당 요소의 맥락을 고려해서 배치되지만

 

 

 

 

 

 

 

 

 

absolute인 경우 해당 요소를 제외하고 배치된다. absolute값을 갖는 요소는 부모 요소의 영역을 벗어날 수도 있다.

 

 

 

 

 

 

 

 

 

 

-fixed: 부모 요소가 아니라 viewport를 기준으로 출발 좌표가 결정된다. fixed값을 갖는 요소는 스크롤이 되더라도 항상 화면의 같은 위치에 위치한다. fixed도 block 요소더라도 width가 content에 맞게 지정되므로 적절한 width를 줘야한다.

 


z-index

겹칠 경우 앞에 보여줄 우선순위를 설정한다. 큰 숫자가 앞에 온다. position이 static인 경우 무시된다.

 

 

<div class="first">First</div>
<div class="second">Second</div>
<div class="third">Third</div>

 

 

div {
  width: 100px;
  height: 100px;
  position: absolute;
  text-align: center;
}

.first {
  background: lightskyblue;
  top: 20px;
  left: 20px;
  z-index: 2;
}

.second {
  background: lightpink;
  top: 40px;
  left: 40px;
  z-index: 1;
}

.third {
  background: lightgray;
  top: 60px;
  left: 60px;
}

 


Overflow

-자식 요소가 너무 커서 영역을 벗어났을 때 처리 방법을 지정한다.

-visible: (기본값) 영역을 벗어나도 표시한다.

-hidden: 영역을 벗어나면 안 보이게 처리한다.

-scroll: 영역을 벗어나면 스크롤을 추가해준다.

-auto: 영역이 벗어난 부분이 있을 때만 스크롤을 추가한다.

 


Display

-block: 줄바꿈O, 기본적으로 라인 전체를 차지, width, height, margin, padding 지정 가능 (div, h1~h6, p, ol, ul, li, hr, table, form ... )

-inline: 줄바꿈X, 다른 요소와 같은 줄에 위치 가능, content 너비만큼 차지, width, height, margin-top, margin-bottom 지정 불가, 상하여백은 line-height을 이용 (span, a, strong, img, br, input, select, textarea, button, ... )

-inline-block: 줄바꿈X, 다른 요소와 같은 줄에 위치 가능, width, height, margin, padding 지정 가능

-none: 안 보이게 하고, 해당 요소가 차지하던 공간도 사라짐

 


Visibility

-visible: (기본값)

-hidden: 안 보이지만 해당 요소가 차지하는 공간은 유지

-collapse/none: table의 행이나 열을 안 보이게 한다.


Opacity

-0.0 ~ 1.0 사이의 값을 받아 투명도를 지정한다.

 


Float

-보통 이미지를 추가하면 글과 다른 문단으로 추가된다. 이때 이미지를 (현재 상태처럼) 글자와 같은 줄에 두고 싶다면, 글 왼쪽 정렬 등의 옵션을 통해 글의 오른쪽에 둘 것인지, 왼쪽에 둘 것인지 정해야 한다.

-float 프로퍼티를 이용하면 text나 inline 요소들과 같은 라인에 표현할 수 있다.

 

-즉, float은 block 요소를 가로정렬하는 데에 쓰인다. block은 기본적으로 해당 라인을 전부 점유하기 때문에(width:  100%), 옆 그림처럼 세로로 표시된다.

-width를 별도로 지정하지 않은 block 요소에 float을 지정하면 width는 content에 맞게 줄어든다.

 

-받을 수 있는 값으로는 none, left, right가 있다.

-right의 경우, 먼저 나온 값이 제일 오른쪽으로 간다.

float: left;

 

float: right;

-float된 block요소와 일반 block 요소를 함께 쓰면, float된 요소의 width는 content 만큼 줄어들고, 일반 block요소는 width: 100%를 유지해서 이런 모양이 된다.

<div class="float">float: left;</div>
<div class="normal">normal div</div>
<div class="float">float: left;</div>

div {
  line-height: 50px;
  padding: 20px;
}
.float {
  float: left;
  background: red;
}
.normal {
  background: skyblue;
  opacity: 0.5;
}

아래의 float: left는 비교용으로 추가했다.

normal div는 여전히 width 100%를 차지하고 있고, float: left가 그 중 일부에 놓여 있는 모양새다.

이런 특징 때문에 몇 가지 문제가 생길 수 있다.

 

1. 둘이 겹쳐 있으면 margin은 어디로?

위와 같은 경우, float-left나 normal div 위에 겹쳐 있는 상태이기 때문에 둘 사이에 공간을 주고 싶어도 제대로 표현이 되지 않는다. div { margin: 0 10px; } 준다고 해도 아래처럼 글자는 밀리지만 공간이 생기지는 않는다.

이 문제를 해결하려면 normal div에 overflow: hidden을 주면 된다.

div {
  line-height: 50px;
  margin: 0 10px;
  padding: 10px;
}
.float {
  float: left;
  background: red;
}
.normal {
  background: skyblue;
  overflow: hidden;
  opacity: 0.5;
}

float: left가 차지하고 있는 부분은 숨겨져서 보이지 않게 되었다!

2. 자식이 float일 때 부모의 높이는?

위 예제에 부모가 있다고 하면

<div class="container">
  <div class="float">float: left;</div>
  <div class="normal">normal div</div>
  <div class="float">float: left;</div>
</div>
.container {
  background-color: lightgray;
}
div {
  line-height: 50px;
  margin: 0 10px;
  padding: 10px;
}
.float {
  float: left;
  background: red;
}
.normal {
  background: skyblue;
  opacity: 0.5;
  overflow: hidden;
}

아래처럼 2번째 float이 부모 영역 바깥으로 나가는 문제가 생긴다. float 요소의 높이가 제대로 반영되지 않는다.

(*float이 없는 경우 아래처럼 정상적으로 표시된다.)

(*normal div가 없으면 아래 같은 상황이 생긴다.)

이 문제는 부모에 overflow:hidden을 지정해주면 해결된다.

왜인지 궁금해서 찾아보니 MDN의 Block_formatting_context 부분에 보면 Contain internal floats 예제가 있다.

overflow값이 초깃값인 visible만 아니면 float을 잡아주는 새로운 BFC가 생성된다고 한다. 새로운 BFC > 회색 컨테이너가 되는 것.

다만 overflow 처리 관련해서 예상치 못한 결과(갑자기 스크롤?)가 생길 수도 있고, overflow 부분이 float를 잡아두려고 쓰였다는 게 분명하지 않기도 하니까 주석을 달아주라고 권해준다.

이 문제를 해결하기 위해 display: flow-root가 추가되었다고 하니, 부수적인 효과 없이 BFC만 생성하고 싶다면 이 옵션을 쓰면 된다.

 


Inheritance

부모 요소에 적용된 프로퍼티 중에는 자식에게 상속되는 것이 있고, 안 되는 것이 있다.

width/height이나 margin, padding, border, box-sizing, display, top/right/bottom/left, postion 같은 요소는 상속이 되지 않고,

font, color, line-height, text-align 등은 상속이 된다.

상세되지 않는 프로퍼티라도, width: inherit;을 지정하면 상속받도록 할 수 있다.

상세 내용은 이쪽을 살펴보면 된다. www.w3.org/TR/CSS21/propidx

 


Cascading

한 요소는 여러 CSS문에 영향을 받을 수 있다. class, id가 모두 있는 p태그라면 세 선택자에서 모두 영향을 받는다.

이때 충돌을 해결하기 위해 우선순위(Cascading Order)가 필요하다.

 

Origin of CSS declarations (선언 장소에 따라 우선)

HTML <head> 내의 <style> 태그 > <link href="file.css" rel="stylesheet"> > 브라우저 디폴트 스타일시트

 

Specificity (구체적으로 선택할수록 우선)

!important > (html 요소 태그 내에 사용되는) 인라인 스타일 > 아이디 선택자 > 클래스/어트리뷰트/가상 선택자 > 태그 선택자 > 전체 선택자 > 상위 요소에 의해 상속된 속성

아래 페이지에 보면 specificity 정도를 결정하는 표가 있다. inline은 1000점, 아이디 선택자는 100점, 일반 태그는 1점 등이다.

developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance태그는

 

Source Order

중요도가 같다면 나중에 선언한 속성이 적용된다.