html-css 과제를 하다가 a태그에 문제 발생.
<!--내가 짠 html -->
<a href="/">
<div>
<img src=""/>
</div>
</a>
<!--브라우저에서 확인되는 html-->
<a href="/">
</a>
<div>
<img src=""/>
</div>
a태그 내부에 다른 태그들을 넣었더니 실제 브라우저에서는 a만 뽑혀서 따로 있었다. 왜이럴까.
왜그러니 싶어서 찾아보니,
?? : 하하! a 안에 다른 태그들이 오면 닫힌단다.
나 : 근데 img 만 넣었을 때는 또 되는데요?
해서 혼자 a 하나 놓고 이렇게 저렇게 만져보고 있었다.
그러다 알게 된 또다른 사실.
<style>
body{
margin: 0;
}
a{
border: 1px solid #000;
margin: 10px;
padding: 10px;
}
</style>
<body>
<a href="/">여기는 a태그 입니다.</a>
</body>
난 분명 margin과 padding을 전부 다 줬는데 왜 위는 저렇게 꽉막혀 있는 걸까?
값이 들어가긴 다 들어감.
대체 a자식이 왜 이런건가 싶었다.
나는 해당 문제의 원인이 1) 내가 거지같이 짠 html 구조 + 2) a태그의 특성을 이해 못한 채 사용한 것 으로 생각했다.
결과적으로 2)가 어느정도는 맞았다.
내가 간과한 점은 하나. a 태그는 inline 요소 라는 점이다.
inline 요소의 기본적인 특징은 다음과 같다.
📍 이로인해 내가 처음 맞닥뜨린 문제
문제 :: a태그 안에 다른 요소를 넣으니 a가 먼저 닫혔다.
답안 ::
a 태그는 인라인 요소이므로 내부에 블록 요소인 div 가 오면 당연히 a 태그의 content 크기를 div가 뽝! 뚫고 나오게 되므로,
a 태그는 옆구리가 터지지 않기 위해 호다닥 문을 닫을 수 밖에 없던 것이다.
그래서 div로 감싼 img는 문제가 발생했지만 a 태그 안에 같은 inline 요소인 img를 넣는 것은 가능했던 것!
📍 그럼 두번째 문제.
문제 :: a 태그 top/bottom 여백이 제대로 들어가지 않는 것은 왜 그런걸까?
답안 ::
이것도 inline 요소 전체의 특징이다.
원래 inline 요소는 margin top-bottom이 안들어 간다고 한다.
위 이미지에서는 마치 padding top이 적용되지 않는 것 처럼 보이지만 실제론 들어간 거다.(브라우저 가려진 듯)
위에 블록요소인 div를 놓아보면 좀더 눈에 잘 보인다.
<style>
body{
margin: 0;
padding: 0;
}
a{
border: 1px solid #000;
margin: 10px;
padding: 10px;
}
span{
border: 1px solid #ac2;
margin: 10px;
padding: 10px;
}
div{
border: 1px solid #91d;
margin: 10px;
padding: 10px;
}
</style>
<body>
<div>div-block</div>
<a href="/">여기는 a태그 입니다.</a>
<span>span-inline</span>
</body>
브라우저에서 실제 블록요소와 인라인 요소가 적용된 모습을 보면
블록요소인 div는 margin과 padding 둘다 상하좌우 모두 적용 된 것이 확인된다.
📍 인라인 요소는 padding은 상하좌우가 모두 적용되었지만 margin은 좌우여백은 적용되지만 상하여백은 적용되지 않는 것이 확인된다. 게다가 div의 margin도 적용이 엥? 왜안되지?
oh 인라인은 블록라인에 적용된 margin도 적용이 안되는군.
그럼 inline-block을 주면 어캐되나?
a 태그에 inline-block을 주니 a 태그에 준 margin이 적용되면서 주변 블록 요소의 margin도 이제는 영향을 준다.
다만 같은 선상에 있던 인라인 요소 span은 여전히 margin top-bottom이 적용되지 않음에도
a 태그가 inline-block으로 바뀌어 margin의 영향을 받으니 같이 영향을 받는 것을 확인할 수 있다.
아주 신기하다.
한번 데였으니 이제 인라인 안에 블록을 넣는 바보짓은 하지 않겠지! 하하하 (사망플래그)
인라인 요소 예시
<a>, <abbr>, <acronym>, <b>, <bdo>, <big>,
<br/>, <button>, <cite>, <code>, <dfn>,
<em>, <i>, <img>, <input>, <kbd>, <label>,
<map>, <object>, <q>, <samp>, <small>,
<script>, <select>, <span>, <strong>, <sub>,
<sup>, <textarea>, <tt>, <var>
블록 요소 예시
<address>, <article>, <aside>, <audio>,
<blockquote>, <canvas>, <dd>, <div>, <dl>,
<fieldset>, <figcaption>, <figure>, <footer>,
<form>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>,
<header>, <hgroup>, <hr>, <noscript>, <ol>,
<output>, <p>, <pre>, <section>, <table>,
<ul>, <video>
🚨 블록 요소는 내부 중첩으로 블록라인, 인라인 요소 모두 올 수 있지만
< p >만 내부에 인라인 요소가 와야 한다.
블록 얘도 margin에 억한 심정이 있나보다.
블록요소는 블록요소의 margin top과 bottom이 만났을 때 더 큰 margin값 하나만 적용되는 현상이 있다.
<div>div-block1</div>
<div>div-block2</div>
div{
border: 1px solid #91d;
width: 100px;
height: 100px;
padding: 10px;
margin-top: 10px;
margin-bottom: 30px;
margin-left: 10px;
margin-right: 10px;
}
이미지는 div-block1의 margin을 표현한 것이다.
코드를 보면 margin-bottom은 30px 나머지는 다 10px 씩 적용했다.
블록요소인 div가 만나는 부분은 div-block1의 bottom값 30px과 div-block2의 top값 10px이 적용되어 총 40px 만큼의 간격이 떨어져야 하는데 보다시피 div-block1의 bottom값 30px 만 적용된 것을 확인할 수 있다. 물론 div-block2의 top 10px이 div-block2에 적용은 되어있다.
즉, 중첩적용이 안된다는 것.
<div class="parent">
<div class="child">div-block1</div>
<div class="child">div-block2</div>
</div>
부모-자식 요소가 중첩된 상태에서 first-child의 margin-top과 부모의 margin-top, last-child의 margin-bottom과 부모의 margin-bottom 이 만나는 경우 마진상쇄(margin collapsing) 현상이 발생한다.
이는 부모가 boder도 없고, padding도 없는 상태에서 자식요소의 margin과 부모요소의 margin이 만났을 때 발생한다.
말 그대로 자식 요소가 content 없는 비어있는 블로 요소이고 부모 요소가 boder도 없고, padding도 없는 상태에서 자식요소의 margin과 부모요소의 margin이 만났을 때 발생한다.
마진 상쇄를 만난 경우 오류라고 생각할 수 있으나 공식문서에 적혀있는 사실이자 현상이다.
왜인지는 모름. 그치만 해당 현상을 맞닥뜨렸을 때 오류나 버그로 인지해 당황하지 말고 해결 방안을 생각해보는 것이 좋다.