CSS学习2-布局介绍

布局介绍

1.浮动布局

本例中,body就是外层容器,因为它默认就是100%的网页宽度,所以不用给它添加新的样式。在body内部,整个网页的内容放在了container容器里面,也就是内层容器。对于内层容器,需要设置一个max-width,并将外边距设置为auto,使内容居中,如下代码

.container {
    max-width: 1080px;
    margin: 0 auto;
}

这里使用了max-width,而不是width。因此如果视口宽度小于1080px的话,内层容器就能缩小到1080px以下。换句话说,在小视口上,内层容器会填满屏幕,在大视口下,它会扩展到1080px。这种方式能有效避免在小屏幕上出现水平滚动条。

浮动元素不同于普通文档流的元素,它们的高度不会加到父元素上。这可能看起来很奇怪,但是恰好体现了浮动的设计初衷。

浮动是为了实现文字围绕浮动元素排列的效果。在段落里浮动图片时,段落的高度并不会增长到能够容纳该图片。也就是说,如果图片比段落文字高,下一段会直接从上一段的文字下面开始,两段文字都会围绕浮动的图片排列。

1.1 理解容器 折叠

例子中,除了页面标题,其他元素都设置了浮动,所以容器的高度只包含页面标题的高度,浮动的媒体元素则扩展到主元素的白色背景下面。这不是我们想要的,主元素应该向下扩展到灰色的盒子。

解决的办法是使用跟浮动配套的clear属性。将一个元素放在主容器的末尾,并对它使用clear,这会让容器扩展到浮动元素下面。

 <div style="clear:both"></div>
 <!-- 在main容器的末尾增加一个带有clear属性的空div -->

clear:both声明让该元素移动到浮动元素的下面,而不是侧面。clear的值还可以设置为left或者right,这样只会相应地清除向左或向右浮动的元素。因为空div本身没有浮动,所以容器就会扩展,直到包含它,因此也会包含该div上面的浮动元素。

但是这种方式不雅。要在HTML里面添加不必要的标记,用纯css方案来实现相同的而效果

1.2 理解清除浮动

不用额外的div标签,我们还可以用伪元素来实现。使用::after伪元素选择器,就可以快速地在DOM中在容器尾部添加一个元素,而不用在HTML里添加标记。

如下所示:

.clearfix::after { 
    /* 选中容器尾部的伪元素 */
    display: block;
    /* 将伪元素的display设置为非inline,并给定一个content值, */
    /* 以便让为元素出现在文档中, */
    content: " ";
    clear: both;
    /* 让伪元素清除容器的所有浮动 */
}

请注意,要给包含浮动的元素清除浮动,而不是给别的元素,比如浮动元素本身,或包含浮动元素的后面的兄弟元素。

这个清除浮动还有个问题没解决:浮动元素的外边距不会折叠到清除浮动容器的外部,非浮动元素的外边距则会正常折叠。比如在前面的页面里,标题“Running tips”紧挨着main元素的顶部,它的外边距在容器外面折叠了。

一些开发人员跟喜欢使用清除浮动的一个修改版,它能包含所有的外边距。这样更符合预期。使用这个修改版,能防止标题外部的外边距在main元素的外部折叠。

.clearfix::before,
.clearfix::after {
    /* 防止伪元素的外边距折叠 */
    display: table;
    content: " ";

}
.clearfix::after {
    /* 只有after伪元素需要清除浮动 */
    clear: both;
}

这个版本使用display:table而不是display:block。给::before和::after伪元素都加上这一属性,所有子元素的外边距都会包含在容器的顶部和底部之间。

清除浮动和display:table

在清除浮动时使用display:table能够包含外边距,是因为利用了CSS的一些特性。创建一个display:table元素,也就是在元素内隐式创建了一个表格行和一个单元格。而且clear属性只能对块级元素生效。表格是块级元素。

1.3 出乎意料的"浮动陷阱"

页面里面的白色容器已经能够包含浮动的媒体元素了,但是出现了另外一个问题:4个盒子没有如预期那样均匀地占据2行。虽然前2个盒子符合预期,但是第3个盒子出现在了右边,也就是第2个盒子的下面,导致第1个盒子下面出现了一片空白。

众多的元素浮动到同一侧,如果每个浮动盒子的高度不一样,最后的布局可能 千变万化。同理,改变浏览器的宽度也会造成相同的结果,因为它会导致换行,从而改变元素高度。而我们真正想要的是每行有2个浮动盒子。

要想修复这个问题很简单:清除第三个浮动元素上面的浮动。更 通用的做法是,清除每行的第一个元素上面的浮动。由于每行有2个盒子,所以只需要清除每行的第奇数个元素上面那行的浮动即可。你可以用:nth-child()伪类选择器来选中这些目标元素。

.media:nth-child(odd) {
    /* 每个新行清除了上面一行的浮动 */
    clear: left;
}

接下来给媒体元素加上外边距来拉开距离。

1.4 BFC

例子中,每个media块里面,发现它的盒子扩展到了最左边,因为它会包围浮动的 图片。现在文字围绕着图片,但是只要清除了图片底部的浮动,正文就会立刻移动到媒体盒子的左边。而我们真正想要的是将正文的左侧靠着浮动图片的右侧排列。

为了实现这种布局,需要为正文建立一个块级格式化上下文(BFC)。BFC是网页的一块区域,元素基于这块区域布局。虽然BFC本身是环绕文档流的一部分,但它将内部的内容与外部的上下文 隔离开。这种隔离为创建BFC的元素做出了以下3件事情:

  1. 包含了内部所有元素的上下外边距
  2. 包含了内部所有的浮动元素
  3. 不会跟BFC外面的浮动元素重叠。

简而言之,BFC里的内容不会跟外部的元素重叠或者相互影响。如果给元素增加clear属性,它只会清除自身所在BFC内的浮动。如果强制给一个元素生成一个新的BFC,他不会跟其他BFC重叠。

给元素添加以下的任意属性值都会创建BFC.

float:left或者right,不为none即可。
overflow:hidden、auto或scroll,不为visible即可。
display:inline-block、table-cell、table-caption、flex、inline-flex、grid或inline-grid。拥有这些属性的元素称为块级容器。
position:absolute或position:fixed。

网页的根元素也创建了一个顶级的BFC

例子中只要给媒体正文创建BFC,网页的布局就会符合预期。通常是给元素设置overflow值-hidden或者auto

使用overflow:auto通常是创建BFC最简单的一种方式。也可以前面提到的其他方式:但是有些问题需要注意,比如,使用浮动或inline-block方式创建BFC的元素宽度变成100%,因此需要限制一下元素的宽度,防止因为过宽而换行,导致内容移动到浮动图片的下面,相反,使用table-cell方式显示的元素,其宽度只会刚好容纳其中的内容,因此需要设置一个较大的宽度,强制使其填满剩余空间。

说明:某些情况下,BFC中的内容可能还会与别的BFC的内容重叠。比如,内容溢出了容器或者因为负外边距导致内容被拉到容器下面。

如下代码,为例子中的代码

html代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="./4-1.css" rel="stylesheet" type="text/css">
</head>
<body>
    <div class="container">
        <header>
            <h1>Franklin Runnint Club</h1>
        </header>
        <main class="main clearfix">
            <h2>Running tips</h2>
            <div>
                <div class="media">
                    <img class="media-image" src="./runner.png">
                    <div class="media-body">
                        <h4>Strength</h4>
                        <p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and glutes.</p>
                    </div>
                   
                </div>
                <div class="media">
                    <img class="media-image" src="./shoes.png">
                    <div class="media-body">
                        <h4>Strength</h4>
                        <p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
                            glutes.</p>
                    </div>
                
                </div>

                <div class="media">
                    <img class="media-image" src="./shoes.png">
                    <div class="media-body">
                        <h4>Strength</h4>
                        <p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
                            glutes.</p>
                    </div>
                
                </div>
                <div class="media">
                    <img src="./runner.png">
                    <div>
                        Strength
                        <p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
                            glutes.</p>
                    </div>
                
                </div>

                <!-- <div style="clear:both"></div>
               在main容器的末尾增加一个带有clear属性的空div -->
            </div>
        </main>
    </div>
</body>

</html>

css代码如下:

:root {
    box-sizing: border-box;
}

*,
::before,
::after {
    box-sizing: inherit;
}

body {
    background-color: #eee;
    font-family: Arial, Helvetica, sans-serif;
}

body *+* {
    margin-top: 1.5em;
}

header {
    padding: 1em 1.5em;
    color: #fff;
    background-color: #0072b0;
    border-radius: 0.5em;
    margin-bottom: 1.5em;
    border: 1px solid;
}

.container {
    max-width: 1080px;
    margin: 0 auto;
}

.main {
    background-color: #fff;
    padding: 0 1.5em;
}

.media {
    background-color: peru;
    float: left;
    width: calc(50% - 1.5em);
    padding: 1.5em;
    border-radius: 0.5em;
    margin: 0 1.5em 1.5em 0;
}

.media-image {
    float: left;
    padding-right: 1.5em;
}

.media-body {
    margin-top: 0;  
    /* 创建一个新的BFC,这样正文就不会跟浮动的图片重叠 */
    overflow: hidden;
}

.media-body h4{
    margin-top: 0;  
}

.clearfix::before,
.clearfix::after {
    /* 防止伪元素的外边距折叠 */
    display: table;
    content: " ";

}
.clearfix::after {
    /* 只有after伪元素需要清除浮动 */
    clear: both;
}

.media:nth-child(odd) {
    /* 每个新行清除了上面一行的浮动 */
    clear: left;
}
posted @ 2020-11-06 17:59  melimeli  阅读(182)  评论(1编辑  收藏  举报