前言
首先是个前端中非常基础小白的话题,已经很清楚这个方法的前端大牛轻喷。我现在学习前端,对学习过程中进行的思考会作记录,希望能帮到有需要的人。
关于不定宽块级元素
块级元素我们很清楚,默认占据一行的元素,比如div
,ul
就是很典型的块级元素。对于定宽的块级元素居中,通过设置相应的margin
为auto
即可,比如对宽度为500px的div
元素:
div {
width: 500px;
margin: 20px auto;
}
这样,该定宽元素就可以居中了。
问题在于不定宽,也就是我们没有设置宽度,是不能通过以上方法来实现居中的。因为,不定宽的块级元素,其整个内容(即border + padding + width)就需要占据一整行,也就无法再通过margin:auto
来实现居中,因为auto了之后,margin也是0。
关于position:relative和float
position:relative
可以让元素相对于原来自身的位置进行偏移,通过设置top
和left
就可以进行偏移。
为了方便说明,我们先来写两个div元素:
<body>
<div id="parent">
<div id="child">I am a child</div>
</div>
</body>
在设置top
和left
时还可以设置为百分比,这个百分比就是其父元素宽度的百分比,例如对一个不定宽的块级元素div#child
进行以下设置,就可以让其往前移动div#parent
宽度的50%,在我们的例子里,div#parent
和body
同宽。
div#child {
position: relative;
left: 50%;
}
注意这并不是居中!
居中是指其内容的中点正好位于页面的中点,而以上只是将其左边界移到了父元素容器的中点。
于是乎,如果div#parent
进行50%的偏移,然后再让div#child
反向进行50%偏移,是不是就可以实现居中了呢?
其实不然,因为对该元素进行反向50%,即left:-50%;
偏移的时候,偏移的距离是父元素的宽度的一半,如果父元素刚好和body
也就是页面的宽度一致,那相当于都是偏移页面宽度的一半,一正一反,刚好抵消。而如果父元素有自己的宽度,那就更加不好预测了。
所以问题的关键是确定元素偏移的距离问题。
现在div#parent
已经被移动到页面的中点,我们期望的是:div#child
设置了left:-50%
之后,其偏移距离应该是自身内容的宽度的一半。
注意:我们说元素的内容,说的是元素内可见的内容,比如这里
div#child
的『I am a child』,如果有不严谨的地方,请各位指出哈
那么怎么实现呢?
让我们理一下关系:
1. div#child
的偏移距离是div#parent
的宽度
2. div#child
的偏移距离应该是其自身内容的宽度
所以只要div#parent
的宽度和div#child
内容的宽度一致不就行了?怎么做到呢?
这时我们可以用float
。
浮动对于盒子模型元素的效果就是从文档流中移出来,这时高度和宽度也随之塌缩到其所包含的子元素的宽度,比如做如下设置
div#parent {
float: left;
}
div#parent
的宽度就变成div#child
的宽度
此外我们还会发现,
body
的高度变为0,因为其不再包含div#parent
了,也就不包含任何元素。
这样就达到我们的目的了,总的来说,实现div#child
居中,只要进行如下设置
div#parent {
float: left;
position: relative;
left: 50%;
}
div#child {
position: relative;
left: -50%
}
多说几句
其实设置父元素的宽度与子元素相同,还有一种方法,那就是设置display:inline-block
,可以用来代替float:left
div#parent {
display:inline-block;
position:relative;
left:50%;
}
div#child {
position:relative;
left:-50%;
}
但是我发现,同样是以行内元素形式排列的display:inline
却不能实现居中,观察元素宽度发现,设置了display:inline
后的div#parent
宽度是子元素的宽度,但不是子元素内容的宽度,那么子元素的宽度是多少?没错就是等于body
的宽度,这是从上往下继承的。
然而如果我把div#child
也设置成display:inline
,此时父子元素的宽度都是子元素的内容的宽度了,仍然不能居中,仿佛此时div#child
设置的left:-50%
不是针对div#parent
的。
看到这句疑惑以及结合inline元素的宽高特性,大家应该就可以理解了,要知道,如果我们去设置行内元素的宽高,是不会起作用的,所以让子元素去参照父元素的宽高偏移50%也是不会起作用的,因此子元素会继续向上寻找,找到一个块级元素,或者一个inline-block的元素,并以其宽高为百分比基准。而在本例中,那就是body
这是我个人得出的结论,没有经过官方证实,但我觉得可以说明问题
所以,为父元素设置display:inline
是不能实现居中的,而应该用display:inline-block