前端菜鸡的学习笔记02: 布局中的问题(上)

145 阅读8分钟

这周总结一下布局中常见的一些问题,顺便祝大家中秋快乐!

文档流

文档流(normal flow) 规定了html中每个元素如何占用空间,以及其他元素如何相应的定位自己,可以说它是一切布局问题的基础

我们都知道我们所看到的网页是一个多层级的结构,层与层之间互相叠加,通过CSS我们可以为每一层来分别设置样式,而文档流则是这些层级中最底部的一层,我们所创建的各种元素默认都是在文档流中进行排列

在文档流中所有的元素可以分为两类: 块级元素(block-level elements)内联元素(inline elements)

块级元素会在页面中总是独占一行(自上向下垂直排列),无论宽度多宽,其默认宽度是父元素的全部(会把父元素撑满),默认高度是被内容(子元素)撑开

常见的块级元素有:<div>,<form>, <table>, <p>, <pre>, <h1>~<h6>, <dl>, <ol>, <ul><li>

内联元素不会独占页面的一行,只占自身的大小,也不在独占一行,而是在页面中左向右(与所设置语言的书写习惯一致)水平排列,如果一行之中不能容纳下所有的行内元素,则元素会换到第二行继续自左向右排列,内联元素的默认宽度和高度都是被内容撑开

常见的内联元素有:<span>, <a>, <strong>, <em>, <lable>, <input>, <select>, <textarea>, <img>, <br>

当然,元素不一定都在文档流中,我们可以通过一定的手段让元素脱离文档流,其特性也会发生相应的改变,这部分内容在下面的部分进行总结

盒模型中的布局问题

CSS将页面中的所有元素都设置为了一个矩形的盒子,称它为盒模型(box model),我们对样式的编写几乎都围绕盒模型来进行

接下来在这里总结一下盒模型中常见的布局问题

盒模型的水平布局

在盒模型中,元素在水平方向的布局通常由margin-leftborder-leftpadding-leftwidthpadding-rightborder-rightmargin-right几个属性共同决定

而块级元素在其父元素中,水平布局必须要满足以下的等式:

margin-left+border-left+padding-left+width+padding-right+border-right+margin-right = 父元素内容区的宽度

这个等式是强制性满足的,如果各属性相加结果不成立,则称为过度约束,等式会对其中部分值进行自动调整,以满足条件

调整的规则:
(1)当这七个属性都没有值设置为auto的情况时,浏览器会自动调整margin-right的值来使等式满足

<div class="box1"></div>
.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
}

image.png

(2)在这七个属性中,只有margin-leftwidthmargin-right这三个属性的值能够设置为auto

如果其中某一个值为auto,则会自动调整值为auto的那个属性以使等式成立,就像下面这样:

.box1 {
  width: 200px;
  height: 200px;
  marign-left: auto;
  background-color: skyblue;
}

image.png

如果将width和一个margin设置为auto,则width会调整到最大,设置为automarign会自动为0

.box1 {
  width: auto;
  height: 200px;
  background-color: skyblue;
  margin-left: auto;
}

image.png 如果将三个值都设置为auto,两个margin会调整为0,而width最大,其效果和上面一样

.box1 {
  width: auto;
**  **height: 200px;
  background-color: skyblue;
  margin-left: auto;
  margin-right: auto;
}

image.png 如果将两个margin设置为autowidth为固定值,则会将两个margin设置为相同的值,我们经常利用这个特点来使一个元素在其父元素中水平居中

.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
  margin-left: auto;
  margin-right: auto;
}

image.png

垂直外边距的折叠

当相邻的两个块级元素的垂直外边距发生重叠时,会产生一些特殊的效果,这会对我们的布局产生影响

外边距的重叠的两个元素可能存在两种情况:兄弟元素父子元素

当兄弟元素的外边距发生重叠时,会有如下的情况:
(1)兄弟元素间的相邻垂直外边距会取两者之间的较大值(两者都是正值

  <div class="box1"></div>
  <div class="box2"></div>
.box1 {
width: 200px;
height: 200px;
background-color: skyblue;
margin-bottom: 20px;
}
.box2 {
width: 200px;
height: 200px;
background-color: teal;
margin-top: 50px;
}

我们看到对于兄弟元素box1和box2,两个元素之间的距离是值更大的box2的margin-top(50px),而不是box1的margin-bottom(20px) image.png (2)兄弟元素间如果重叠的外边距一正一负,则取两者的和

.box1 {
width: 200px;
height: 200px;
background-color: skyblue;
margin-bottom: -50px;
}
.box2 {
width: 200px;
height: 200px;
background-color: teal;
margin-top: 50px;
}

我们给两个元素分别设置一正一负,大小相等的外边距并使它们发生重叠,根据规则元素间的距离会是两者之和,也就是0px

image.png

(3) 兄弟元素间如果相邻的外边距都是负值,则取两者中绝对值较大的

.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
  margin-bottom: -100px;
}
.box2 {
  width: 200px;
  height: 200px;
  background-color: teal;
  margin-top: -50px;
}

box1的外边距绝对值更大,所以两个元素间的距离以此为准(-100px刚好遮住box1的一半)

image.png

通常来说,兄弟元素之间的外边距的重叠,对于开发是有利的,所以我们一般不需要进行处理

而当父子元素的垂直外边距发生重叠时,子元素与父元素的垂直外边距也会发生合并,合并规则跟兄弟元素间的情况一样,且外边距会作用到父元素身上

<div class="box1">
 <div class="box2"></div>
</div>
.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
  

}
.box2 {
  width: 100px;
  height: 100px;
  background-color: teal;
  margin-top: 50px;
}

这里给子元素box2设置的50px上外边距,因发生外边距重叠使父元素box1下移了50px image.png 父子外边距的折叠会影响到页面的布局,必须要进行处理,我们可以通过为父元素设置padding或是border来隔离开父子间的外边距避免它们重叠

.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
  border-top: 1px solid rgb(0,0,0);
  

}
.box2 {
  width: 100px;
  height: 100px;
  background-color: teal;
  margin-top: 50px;
}

这里通过给父元素设置了一个上边框隔开了外边距,成功解决了外边距的重叠

image.png

但通过设置padding或是border的解决方式并不推荐使用,因为这样会改变我们元素的样式和大小,不利于整体布局

更好的解决方式是通过::before伪元素选择器设置一个隐藏的占位元素,并使该元素开启BFC(块级格式化环境)来隔离父子元素间的垂直外边距(关于BFC在以后的笔记再详细总结)

.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
}
.box1::before {
    content:"";
    display:table;/* 设置为block虽然开启了BFC,但因为content为空,所有还是会被margin击穿*/
}
.box2 {
  width: 100px;
  height: 100px;
  background-color: teal;
  margin-top: 50px;
}

image.png

内联元素在盒模型中的布局

与块级元素相比,内联元素在盒模型中有一些自身所独有的特点:
(1) 内联元素不支持设置宽度和高度,仅能被内容撑开

需要注意的是内联元素中的<img><video><object>等元素属于比较特殊的类型,虽然也是内联元素,但却能够设置宽度和高度,我们称它们为可替换元素,这类元素内容往往不受当前文档样式的影响,使用 CSS 可以影响可替换标签的位置,但不会替换可替换标签本身的内容

(2) 在盒模型中,内联元素垂直方向上的属性,如垂直方向上的marginpaddingborder不会对布局造成影响

<div class="box1">
</div>
<span>5555555555555</span>

.box1 {
width: 200px;
height: 200px;
background-color: skyblue;
}
span {
margin-top: 100px;
padding-top: 100px;
border-top: solid red 2px;
}

这里给内联元素<span>所设置的垂直方向上的属性都生效了(其中borderpadding撑起),但是对布局没有影响,元素的位置没有改变

image.png

在一些场景下我们往往需要对内联元素的宽和高进行设置或是需要设置内联元素在垂直方向上的一些属性,可以使用display属性来改变元素的类型

display 用来设置元素显示的类型
                    可选值:
                        inline 将元素设置为内联元素
                        block 将元素设置为块元素
                        inline-block 将元素设置为行内块元素 
                                行内块:既可以设置宽度和高度又不会独占一行
                        table 将元素设置为一个表格
                        none 元素不在页面中显示,且不占位(如需占位可使用 visibility:hidden)
.box1 {
  width: 200px;
  height: 200px;
  background-color: skyblue;
}
span {
 margin-top: 50px;
 padding-top: 50px;
 border-top: solid red 2px;
 display: block;
}

这样内联元素就会变成块元素,我们设置的属性也会生效了

image.png

由于时间关系,关于浮动定位的相关总结就放在下周的更新中了,我们下周再见!