코드잇 스프린트의 css강의를 듣던 평화로운 어느날..

문제가 발생했다.

아래의 코드로 구현해낸 화면

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>로그인</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <form>
      <h1>로그인</h1>
      <label>아이디</label>
      <input
        name="username"
        type="text"
        placeholder="Email 또는 전화번호"
      />
      <label>비밀번호</label>
      <input
        name="password"
        type="password"
        placeholder="비밀번호"
      />
      <div>
        <a href="#" class="forget">비밀번호를 잊으셨나요?</a>
      </div>
      <button>로그인</button>
      <div class="join">
        회원이 아니신가요?
        <a href="#">가입하기</a>
      </div>
    </form>
  </body>
</html>
html {
  font-family: 'Noto Sans KR', sans-serif;
  font-size: 16px;
  font-weight: 400;
  box-sizing: border-box;
}

form{
  width: 360px;
  text-align: center;
  margin: 0 auto;
}

label {
  display: block;
  margin: 16px 0 8px;
  width: 100%;
  text-align: left;
  font-size: 16px;
  font-weight: 400;
  color: #2c2c2c;
}

input {
  display: block;
  width: 100%;
  padding: 16px 24px;
  margin: 0 auto;
  border: 1px solid #d1d1d1;
  box-sizing: border-box;
}

이하 생략

코드의 css부분을 보면 html에 box-sizing: border-box;와 input 부분에 box-sizing: border-box;이 적혀있다.

나는 처음에 코드를 작성할 때 전체를 감싸고 있는 html 태그가 css의 첫번째 코드에 와 있길래 (html부분 내가 작성한것 아님) "전체를 뜻하는 태그이구나..!"라는 생각에 box-sizing: border-box를 주었는데 자꾸 input부분이 지정해준 너비 밖으로 삐져나왔다.

input 부분이 눈에 거슬리게 튀어나와있는 모습

너비 값을 100%도 줘보고, 정해진 px로도 줘봤지만 input의 너비는 줄어들지 않았고 overflow : hidden까지 들먹여가며 머리를 싸맸던 나는 input 값에 box-sizing: border-box;를 재부여하고 나서야 해결을 할수 있었다.

왜 html 태그에 작성한 box-sizing: border-box;은 적용되지 않았던걸까? box-sizing의 작동 방식은 이렇다.

  1. 기본 적용: box-sizing: border-box;를 html 태그에 적용하면, 모든 요소가 기본적으로 border-box 모델로 계산되도록 설정해야하지만 이 설정이 모든 요소에 자동으로 적용되지 않거나, 특정 요소에 대해 다른 스타일이 정의되어 있을 경우, 이러한 스타일이 우선시될 수 있다.
  2. 상속: CSS 속성은 기본적으로 상속되지 않는다. box-sizing은 상속되는 속성이 아니기 때문에, 각 요소에 대해 명시적으로 설정해주지 않으면 기본값인 content-box가 적용될 수 있다.
  3. 스타일 우선순위: 만약 어떤 요소에 대해 box-sizing을 따로 설정한 경우, 그 설정이 우선적으로 적용된다. 그래서 각 요소에 대해 box-sizing: border-box;를 명시적으로 설정해주면, 그 요소에 대해서는 border-box 모델이 적용되는 것.

1. *선택자 :

  • *는 모든 요소를 선택하는 와일드카드 선택자이다. 즉, 문서 내의 모든 HTML 요소에 적용할 스타일을 정의할 수 있다.
  • 예를 들어, * { margin: 0; }는 모든 요소의 마진을 0으로 설정한다.

2. html 선택자 :

  • html 선택자는 <html> 태그에만 적용된다. 따라서 html에 설정한 스타일은 오직 <html> 요소에만 영향을 미친다.
  • 예를 들어, html { font-size: 16px; }는 문서의 루트 요소인 <html>에만 적용되고, 다른 요소에는 직접적인 영향을 주지 않는다.

html 태그에 box-sizing: border-box;를 설정했어도, 그 설정이 모든 요소에 영향을 주지 않거나, 다른 스타일이 우선시될 경우 원하는 효과를 얻지 못할 수 있다. 그래서 모든 요소에 대해 * 선택자를 사용하여 적용하는 것이 일반적인 방법이다.

 

*이해를 위해 도움 주신 팀원 ㅇㄱ님과 chatGPT 고맙습니다.

'코린이 개념잡기 > CSS' 카테고리의 다른 글

flex box  (0) 2024.12.02
BOX Model  (0) 2024.12.01
마진 상쇄(margin collapsing)  (1) 2024.11.29
미디어 쿼리(media query)  (0) 2024.02.09
inset과 gap  (0) 2023.03.17

마진상쇄 : 마진 상쇄는 인접한 블록 요소의 마진이 서로 겹칠 때, 두 마진 중 큰 값이 적용되고 작은 값은 무시되는 현상. 예를 들어, 두 개의 요소가 서로 인접해 있을 때, 아래의 규칙이 적용된다.

  1. 인접한 블록 요소의 수직 마진이 겹칠 때: 두 요소의 마진이 서로 겹치면, 더 큰 마진값만 적용되고 작은 마진은 사라진다. 이 경우, 두 요소의 마진은 서로 합쳐지지 않고, 그 중 큰 값만 사용된다.
  2. 부모 요소와 자식 요소의 마진 상쇄: 만약 자식 요소가 마진을 가지고 있고, 그 자식 요소의 마진과 부모 요소의 마진이 겹친다면, 자식 요소의 마진이 부모의 마진과 합쳐지지 않고, 부모 요소의 마진만 적용될 수 있다. 이는 자식 요소가 화면의 상단이나 하단과 접촉할 때 발생한다. (중요! 세로로만 마진 상쇄가 일어난다.)
<div class="parent">
  <div class="child1"></div>
  <div class="child2"></div>
</div>
.parent {
  margin: 20px; /* 부모의 마진 */
}

.child1 {
  margin: 30px; /* 첫 번째 자식의 마진 */
}

.child2 {
  margin: 40px; /* 두 번째 자식의 마진 */
}

예를 들어 이런 HTML과 CSS 코드를 작성했다고 생각해보자. 

하나씩 풀어서 생각해보면,

  1. 부모요소 : .parent의 마진은 20px이다.
  2. 자식요소 : 자식1의 마진은 30px, 자식2의 마진은 40px이다.

마진 상쇄 과정 

  • 자식1과 자식2의 마진 : 자식 1의 하단 마진 30px과 자식2의 상단 마진 40px이 겹쳐져서 더 큰 마진인 자식2의 마진인 40px만 적용되고 자식1의 하단 마진은 무시된다.
  • 부모 자식의 마진 : 자식2의 하단 마진 40px과 부모요소의 하단 마진 20px이 겹쳐질 때 자식 2의 마진이 더 크기 때문에 최종적으로 자식 2의 마진 40px이 적용된다. 이와 마찬가지로 자식1의 상단 마진 30px과 부모요소의 상단 마진 20px이 겹쳐질 때 자식 1의 마진이 더 크기 때문에 최종적으로 자식 1의 마진 30px이 적용된다.

그리고, 마진 상쇄에는 여러 규칙이 있다.

다음의 경우엔 자식 요소의 마진이 부모요소의 바깥으로 전파가 된다.

  1. border가 없을 경우
  2. padding이 없을 경우
  3. overflow가 없을 경우

여기 두 가지의 문제가 있다. 질문은 같으나 답은 다르다.

Q1. 아래 코드에서 #a와 #b 사이의 세로 마진은 몇 px일까요?

<div id="a">
  a
  <div id="c">
    c
  </div>
</div>
<div id="b">
  b
</div>
#a {
  margin: 30px;
}

#b {
  margin: 20px;
}

#c {
  margin: 40px;
}
더보기

정답 : 40px

Q2. 아래 코드에서 #a와 #b 사이의 세로 마진은 몇 px일까요?

<div id="a">
  a
  <div id="c">
    c
  </div>
</div>
<div id="b">
  b
</div>
#a {
  padding: 10px;
  margin: 30px;
}

#b {
  margin: 20px;
}

#c {
  margin: 40px;
}
더보기

정답 : 30px

두 문제의 차이는 #a에 padding : 10px이라는 코드의 유무밖에 차이가 없는데 왜 정답에서 차이가 있는걸까?

그림으로 풀어보자면 이렇다.

문제 1의 경우와 문제 2의 경우를 그림으로 만들었을 때

문제1은 a의 자식 요소인 c가 a의 마진 30px 보다 큰 40px이라 상쇄가 일어났다. 하지만 문제2의 경우는 부모요소인 a가 패딩값을 10px 주었다. 때문에 자식 요소인 c가 패딩 값을 뚫고 마진을 행사 할 수 없기 때문에 문제 2에서 a와 b 사이의 마진 값은 b의 마진 값보다 큰 a의 마진값 30px이 된다. padding 뿐만 아니라 border나 overflow로 자식요소의 마진이 부모요소의 마진에 영향을 끼치지 못하게 할 수 있다.

위의 문제 외에도 마진 상쇄에는 다양한 경우들이 있는데 다음의 경우엔 마진 상쇄가 일어나지 않는다.

  1. 요소가 position : absolute 일 때
  2. 요소가 float : left / right 일 때
  3. dipaly : flex 일 때
  4. display : grid 일 때

참고자료 :  Kimaramy님 블로그, 코드잇 스프린트 CSS 핵심개념 강의 中 "마진 상쇄"

'코린이 개념잡기 > CSS' 카테고리의 다른 글

BOX Model  (0) 2024.12.01
전체 선택자  (0) 2024.11.29
미디어 쿼리(media query)  (0) 2024.02.09
inset과 gap  (0) 2023.03.17
flex 2  (0) 2023.03.16

+ Recent posts