CSS (中)
回顾
HTML5新增的那些
HTML5标准更加的讲究语义化了,借用一张网上的图来说明这些新标签
-
header元素
:header 元素代表“网页”或“section”的页眉。 -
footer元素
:footer元素代表“网页”或“section”的页脚,通常含有该节的一些基本信息,譬如:作者,相关文档链接,版权资料。 -
hgroup元素
:<hgroup> 标签用于对网页或区段(section)的标题进行组合。 -
nav元素
:nav元素代表页面的导航链接区域。用于定义页面的主要导航部分。 -
aside元素
:aside元素被包含在article元素中作为主要内容的附属信息部分,其中的内容可以是与当前文章有关的相关资料、标签、名次解释等。(特殊的section) -
section元素
:section元素代表文档中的“节”或“段”,“段”可以是指一篇文章里按照主题的分段;“节”可以是指一个页面里的分组。section通常还带标题,虽然html5中section会自动给标题h1-h6降级,但是最好手动给他们降级。- 当一个容器需要直接定义样式或通过脚本定义行为时,推荐使用div元素而非section
<section>
<h1>图灵</h1>
<p>一个<b>可爱</b>>技术俱乐部</p>
</section>
- 注意标题部分位于它的内部,而不是前面(通常不推荐为那些没有标题的内容使用section)
-
article元素
:article元素最容易跟section和div容易混淆,其实article代表一个在文档,页面或者网站中自成一体的内容,其目的是为了让开发者独立开发或重用。譬如论坛的帖子,博客上的文章,一篇用户的评论,一个互动的widget小工具。(特殊的section)除了它的内容,article会有一个标题(通常会在header里),会有一个footer页脚。
推荐看原博主的博客:传送门
常见问题
为什么出现二级标题比一级的大?
http://www.it1352.com/867990.html
背景与边框
灵活背景定位
- background-position
- 原理:background-positioon:right 10px bottom 20px;指背景位置距离右边10px,距离底部20px.
/**
* Flexible background positioning
* via extended background-position
*/
div {
background: url(http://csssecrets.io/images/code-pirate.svg)
no-repeat bottom right #58a;
background-position: right 20px bottom 10px;
/* Styling */
max-width: 10em;
min-height: 5em;
padding: 10px;
color: white;
font: 100%/1 sans-serif;
}
https://codepen.io/AlexZ33/pen/JjoRvRP
/**
* Flexible background positioning
* via calc()
*/
div {
background: url(http://csssecrets.io/images/code-pirate.svg)
no-repeat bottom right #58a;
background-position: calc(100% - 20px) calc(100% - 10px);
/* Styling */
max-width: 10em;
min-height: 5em;
padding: 10px;
color: white;
font: 100%/1 sans-serif;
}
http://dabblet.com/gist/b5fcb42d055427ab6c1a
https://codepen.io/AlexZ33/pen/QWwKrKm
- background-origin
- 作用:用于设置背景的原始位置依据,值为content-box,padding-box,border-box;
/**
* Flexible background positioning
* via extended background-position
*/
div {
background: url(http://csssecrets.io/images/code-pirate.svg)
no-repeat bottom right #58a;
background-origin: content-box;
/* Styling */
max-width: 10em;
min-height: 5em;
padding: 10px;
color: white;
font: 100%/1 sans-serif;
}
http://dabblet.com/gist/0f19ac5d28d0aa7b6c60
https://codepen.io/AlexZ33/pen/xxbEjRK
边框内圆角
- 原理:利用outline和box-shadow组合实现内圆角(outline目前没有实现圆角)
- https://www.html.cn/tool/css3Preview/Box-Shadow.html
- 方法二:两个元素来实现,当然这样增加了额外的html标签
https://codepen.io/AlexZ33/pen/vYEXjgX
横向条纹背景
- 原理:利用
bacground:linear-gradient(red 50%,green 50%)
实现双条纹,利用background-size:100% 30px
实现单个条纹高15px
垂直条纹背景
- 原理:设置
linear-gradient
角度为90deg,或to right
,通过background-size:30px 100%
设置条纹单个宽15px
斜向条纹
- 原理:45deg斜向条纹,利用 勾股定理计算出 条纹若30px时,需要background-size对应的值
60度斜向条纹
- 原理:通过
background:repeating-linear-gradient(60deg,red,red 15px,blue 15px ,blue 30px)
实现
灵活同色系条纹
- 应用场景:如bootstrap的进度条,由深色背景+同色系浅背景的斜条纹组成
- 原理:同色系深色作为背景色,再通过叠加
白色半透明
和透明条纹,实现深浅间隔条纹
蓝色网格背景
- 原理:利用background-image:linear-gradient()支持分隔叠加的属性方式
波点背景图
- 原理:利用
background:radial-gradient(green 30%,transparent 0)
实现,径向渐变由内向外
动态loading图
- 原理:通过叠加多个animation,实现连续动画效果(旋转,变色,边框宽度增加)
https://codepen.io/AlexZ33/pen/abzmGWo
连续的图像边框
- 原理:通过叠加纯白背景(渐变实现,padding-box)和图像背景(border-box)
信封边缘背景
- 原理:通过叠加纯白渐变背景(padding-box)和-45deg条纹渐变(borderbox)
边框背景图实现信封边缘
- 原理:通过border-image值为线性渐变的条纹而实现
移动的虚线边框
- 原理:利用背景叠加实现虚线边框,通过animation实现背景移动产生动态效果
字体脚注效果
- 原理:利用
border-image
属性加一条线性渐变产生的垂直条纹,border-width
控制边框粗线,渐变长度
来控制脚注长度
尺寸
尺寸,我们就应该从单位聊起,对于px这个单位,做网页的应该在熟悉不过了,因此不多做介绍。
那么,我们可以来介绍一下下面几个单位:
- 百分比:百分比的参照物是父元素,50%相当于父元素width的50%
- rem:这个对于复杂的设计图相当有用,它是html的font-size的大小
- em:它虽然也是一个相对的单位,相对于父元素的font-size,但是,并不常用,主要是计算太麻烦了。
单位只是一个来定义元素大小的相应参考。另一个概念,或许可以用房子来打一个比方,在早年每幢房子都会在房子的外围建一层栅栏,使得整一块地区可以看成房子+内部地块+栅栏+外围地块的模型。而在css中,每个元素也会有盒子模型的概念。
盒子模型:每个元素,都会形成一个矩形块,主要包括四部分:margin(外边距)+border(边框)+padding(内边距)+content(内容)
css中存在两种不同的盒子模型,可以通过box-sizing设置不同的模型。两种盒子模型,主要是width的宽度不同。如图:
content-box
这是标准盒子模型,可以看到width的长度等于content的宽度;而当将box-sizing的属性值设置成border-box时,盒子模型的width=border+padding+content的总和。
可以看出,对于不同的模型的宽度是不同的。宽度默认的属性值是auto,这个属性值会使得内部元素的长度自动填充满父元素的width。如图:
width-auto
但是,height的属性值也是默认的auto,为什么没有像width一样呢?
其实,auto这个属性值表示的是浏览器自动计算。这种自动计算,需要一个基准,一般浏览器都是允许高度滚动的,所以,会导致一个问题——浏览器找不到垂直方向上的基准。
同样地道理也会被应用在margin属性上。相信如果考察居中时,水平居中你可能闭着眼睛都能写出来,但是垂直居中却绕着脑袋想。这是因为如果是块级元素水平居中只要将水平方向上的margin设置成auto就可以了。但是,垂直方向上却没有这么简单,因为你设置成auto时,margin为0。这个问题,还是需要仔细思考一下的。
到此为止,布局最基本的部分我们已经将去大半,还有就是一块浮动。
正常文档流
如果你选择没有用任何CSS来改变页面布局的网页,那么HTML元素就会排列在一个正常流(Normal Flow)之中。在正常流中,元素盒子(任何一个HTML元素其实就是一个盒子)会基于文档的写作模式一个接一个地排列(根据不同的文档写作模式,排列方向不一样)。这就意味着,如果你的写作模式是水平的(句子是从左到右或从右到左写),正常流会垂直地一个接一个排列页面的块级元素。如果你是在一个垂直方向的写作模式下,句子是垂直方向书写的,那么块级元素会水平方向排列。
确保书写的页面具有良好的结构(HTML结构),可以最大程度复用正常文档流
- 如果浏览器中没有正常流,那么你创建的HTML元素都会堆积在浏览器的右上角。这就意味着,你必须指定所有的HTML元素的布局方式。
- 有了正常流,哪怕是CSS加载失败了,用户仍然能阅读你的页面内容;
布局技术会覆盖默认的布局行为:
**
-
display
属性 — 标准的value,比如block
,inline
或者inline-block
元素在正常布局流中的表现形式 (见 Types of CSS boxes). 接着是全新的布局方式,通过设置display
的值, 比如 CSS Grid 和 Flexbox. -
浮动——应用
float
值,诸如left
能够让块级元素互相并排成一行,而不是一个堆叠在另一个上面。 -
position
属性 — 允许你精准设置盒子中的盒子的位置,正常布局流中,默认为static
,使用其它值会引起元素不同的布局方式,例如将元素固定到浏览器视口的左上角。 -
表格布局— 表格的布局方式可以用在非表格内容上,可以使用
display: table
和相关属性在非表元素上使用。 - 多列布局— 这个 Multi-column layout 属性 可以让块按列布局,比如报纸的内容就是一列一列排布的。
拓展阅读 -->
脱离文档流
一旦页面有一个良好的结构,你就需要去决定如何利用它并将它变为我们需要的布局结构。这会涉及到脱离正常文档流
浮动
float(浮动)
浮动被用来将元素盒子向左或向右移动,同时让内容环绕其展示。
要让一个元素进行浮动,需要给该元素的flaot
属性设置为left
或right
。float
的默认值为none
。
.item {
float: left
}
float 属性有四个可能的值:
-
left
— 将元素浮动到左侧。 -
right
— 将元素浮动到右侧。 -
none
— 默认值, 不浮动。 - inherit — 继承父元素的浮动属性。
简单示例:
将两个 <div>
元素排成一行。注意这两个 <div>
一个浮动值为 left
,另外一个浮动为 right
。这意味着它们其中一个往左靠,另外一个往右靠。给这两个元素分别设置 width
值,使得它们能够在同一行放下来,并且设置一个水平的间距(总宽度不要大于100%!).
demo:
https://codepen.io/AlexZ33/pen/povvOQd
实践:
https://game.xiaomi.com/
需要注意的是, 当你使某个元素浮动并让文字环绕它时,内容的行框(Line Box)被缩短。如果你让一个元素浮动,同时为紧跟着的包含文本的元素设置一个背景颜色,你会发现背景色会出在浮动元素下方。
如果想要在浮动元素和环绕的文本之间有一定的间距,需要给浮动元素设置margin。在文本元素上设置margin只会让其相对于容器缩进。例如在下面这个例子中,你就需要为左侧浮动的图片设置右边距和下边距。著作权归作者所有。
https://codepen.io/AlexZ33/pen/WNbbgmO
clear(清除浮动)
一旦对一个元素进行了浮动,所有接下来的元素都会环绕它,直到内容处理它下方才开始应用正常文档流。如果想要避免这种情形,可以手动清除浮动。
如果不想要在某个元素受到其之前的浮动元素影响时,可以为其添加clear属性。left值表示清除左边的浮动,right值表示清除右浮动,both值表示清除左右两边的浮动。
.clear {
clear: both;
}
如果希望元素在浮动元素之后开始排列,那么上面的代码可以达到你的需求。如果你发现在容器内有一个浮动元素,同时容器内文本内容过短时,就会出现问题。文本盒子会被绘制在浮动元素下,然后接下来的部分会以正常流方式绘制在其后。著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
更好的写法
.clear::after {
display: block;
content: '';
clear: both;
}
典型的CSS清除浮动
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix { display: inline-block; }
html[xmlns] .clearfix { display: block; }
* html .clearfix { height: 1%; }
新版清除浮动(2011)
.clearfix:before, .container:after { content: ""; display: table; }
.clearfix:after { clear: both; }
/* IE 6/7 */
.clearfix { zoom: 1; }
绝对定位
定位
定位的概念就是它允许你定义一个元素相对于其他正常元素的位置,它应该出现在哪里,这里的其他元素可以是父元素,另一个元素甚至是浏览器窗口本身。还有就是浮动了,其实浮动并不完全算是定位,它的特性非常的神奇,以至于它在布局中被人广泛的应用。我们会在后文中专门提及它的。
谈及定位,我们就得从position属性说起。你能准确的说出position的属性值吗?相信你可以完美地说出这么六个属性值:static、relative、absolute、fixed、sticky和inherit。
- static(默认):元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分;行内元素则会创建一个或多个行框,置于其父元素中。
- relative:元素框相对于之前正常文档流中的位置发生偏移,并且原先的位置仍然被占据。发生偏移的时候,可能会覆盖其他元素。
- absolute:元素框不再占有文档流位置,并且相对于包含块进行偏移(所谓的包含块就是最近一级外层元素position不为static的元素)
- fixed:元素框不再占有文档流位置,并且相对于视窗进行定位
- sticky:(这是css3新增的属性值)粘性定位,官方的介绍比较简单,或许你不能理解。其实,它就相当于relative和fixed混合。最初会被当作是relative,相对于原来的位置进行偏移;一旦超过一定阈值之后,会被当成fixed定位,相对于视口进行定位。demo地址
简单地,介绍一下position的属性值的含义后,在来看一下偏移量top、right、bottom、left四个属性。
不清楚,当初在初学css的时候,会不会与margin这个属性混淆?其实,它们之间是很容易去辨识地。因为这四个属性值,其实是,定位时的偏移量。偏移量不会对static的元素起到作用。而margin,相对应的是盒子模型的外边距,它会对每个元素框起到作用,使得元素框与其他元素之间产生空白。
下面:我们来看一下一些常用定位的偏移
- relative:它的偏移是相对于原先在文档流中的位置,如图:
relative relative-offset
这里设置了top:100px,left:100px。
- absolute:它的偏移量是相对于最近一级position不是static的祖先元素的
- fixed:它的偏移量是相对于视口的。
其实,这里说描述的内容,应该都是需要理解的。这些相对于布局来说是基础的,同时也是非常重要的。需要注意的是,这里的偏移量其实已经涉及到了接下来要说的尺寸。在做自适应布局设计时,往往希望这些偏移量的单位能够使用百分比,或者相对的单位例如rem等。
fixed:
实践:
定位&居中
水平居中
(1). 行内元素的水平居中?
如果被设置元素为文本、图片等行内元素时,在父元素中设置text-align:center实现行内元素水平居中,将子元素的display设置为inline-block,使子元素变成行内元素
<div class="parent" style="background-color: gray;">
<div class="child" style="background-color: lightblue;">DEMO</div>
</div>
<style>
.parent{text-align: center;}
.child{display: inline-block;}
</style>
(2)块状元素的水平居中(定宽)
当被设置元素为定宽块级元素时用 text-align:center 就不起作用了。可以通过设置“左右margin”值为“auto”来实现居中的。
<div class="parent" style="background-color: gray;">
<div class="child" style="background-color: lightblue;">DEMO</div>
</div>
.child{
width: 200px;
margin: 0 auto;
}
(3)块状元素的水平居中(不定定宽)**
**
**实际工作中我们会遇到需要为“不定宽度的块级元素”设置居中,比如网页上的分页导航,因为分页的数量是不确定的,所以我们不能通过设置宽度来限制它的弹性。
可以直接给不定宽的块级元素设置text-align:center来实现,也可以给父元素加text-align:center 来实现居中效果。
当不定宽块级元素的宽度不要占一行时,可以设置display 为 inline 类型或inline-block(设置为 行内元素 显示或行内块元素)
<div class="container">
<ul>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
.container{text-align:center;background: beige}
.container ul{list-style:none;margin:0;padding:0;display:inline-block;}
.container li{margin-right:8px;display:inline-block;}
垂直居中
和水平居中一样,这里要讲垂直居中,首先设定两个条件即父元素是盒子容器且高度已经设定
1:子元素是行内元素,高度是由其内容撑开的
这种情况下,需要通过设定父元素的line-height为其高度来使得子元素垂直居中
<div class="wrap line-height">
<span class="span">111111</span>
</div>
.wrap{
width:200px ;
height: 300px;
line-height: 300px;
border: 2px solid #ccc;
}
.span{
background: red;
}
2:子元素是块级元素但是子元素高度没有设定
在这种情况下实际上是不知道子元素的高度的,无法通过计算得到padding或margin来调整,但是还是存在一些解法。
通过给父元素设定display:table-cell;vertical-align:middle来解决
<div class="wrap">
<div class="non-height ">11111</div>
</div>
.wrap{
width:200px ;
height: 300px;
border: 2px solid #ccc;
display: table-cell;
vertical-align: middle;
}
.non-height{
background: green;
}
https://codepen.io/AlexZ33/pen/BaBvbEr
3:子元素是块级元素且高度已经设定
计算子元素的margin-top或margin-bottom,计算方法为父(元素高度-子元素高度)/2
<div class="wrap ">
<div class="div1">111111</div>
</div>
.wrap{
width:200px ;
height: 300px;
border: 2px solid #ccc;
}
.div1{
width:100px ;
height: 100px;
margin-top: 100px;
background: darkblue;
}
4、最常用方法
怎么垂直对齐容器中的元素是最佳实践呢?
- 现在,利用
CSS3
的Transform
,可以很优雅的解决这个困惑:
.verticalcenter{
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
使用这个技巧,从单行文本、段落到box,都会垂直对齐。目前浏览器对Transform
的支持是需要关注的,Chrome 4
, Opera 10
, Safari 3
, Firefox 3
, and Internet Explorer 9
均支持该属性
https://codepen.io/AlexZ33/pen/qBBewPE
水平垂直居中
1、水平对齐+行高
text-align + line-height实现单行文本水平垂直居中
<style>
.test{
text-align: center;
line-height: 100px;
}
</style>
<div class="test" style="background-color: lightblue;width: 200px;">测试文字</div>
2、水平+垂直对齐
- text-align + vertical-align 在父元素设置text-align和vertical-align,并将父元素设置为table-cell元素,子元素设置为inline-block元素
<style>
.parent{
display: table-cell;
text-align: center;
vertical-align: middle;
}
.child{
display: inline-block;
}
</style>
**
<div class="parent" style="background-color: gray; width:200px; height:100px;">
<div class="child" style="background-color: lightblue;">测试文字</div>
</div>
2.若子元素是图像,可不使用table-cell,而是其父元素用行高替代高度,且字体大小设为0。子元素本身设置vertical-align:middle
<div class="parent" style="background-color: gray; width:200px; ">
<img class="child" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/img1.gif" width="50%" alt="test">
</div>
<style>
.parent{
text-align: center;
line-height: 100px;
font-size: 0;
}
.child{
vertical-align: middle;
}
</style>
3、相对+绝对定位
1、使用absolute,利用绝对定位元素的盒模型特性,在偏移属性为确定值的基础上,设置margin:auto
<style>
.parent{
position: relative;
}
.child{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 50px;
width: 80px;
margin: auto;
}
<div class="parent" style="background-color: lightgray; width:200px; height:100px; ">
<div class="child" style="background-color: lightblue;">测试文字</div>
</div>
2、如果要居中元素是定宽高的
- 使用绝对定位定位到 50%/ 50%
- 再使用margin退回到元素的一半距离
.parent {
position: relative;
}
.child {
width: 300px;
height: 100px;
padding: 20px;
position: absolute;
top: 50%;
left: 50%;
margin: -70px 0 0 -170px;
}
demo:
https://codepen.io/AlexZ33/pen/JjjQgWd
实践:
3、如果要居中元素是不定宽高的
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
https://codepen.io/AlexZ33/pen/abbgewz
4、使用flexbox
可以垂直居中任何元素:
.parent {
display: flex;
justify-content: center;
align-items: center;
}
https://codepen.io/AlexZ33/pen/GRRVKWY
https://codepen.io/AlexZ33/pen/BaBvbEr
https://codepen.io/AlexZ33/pen/WNNVqYp
注意: IE11 对 flexbox 的支持有点 bug。
5、使用Grid
**
body, html {
height: 100%;
display: grid;
}
span { /* thing to center */
margin: auto;
}
https://codepen.io/AlexZ33/pen/xxxvKXX
常见布局
网页实质是块与块之间的位置,块挨着块,块嵌套块,块叠着块。
三种关系:相邻,嵌套,重叠。
盒布局
一栏布局
常见的有两种:
- header,content和footer等宽的单列(一栏)布局
- header与footer等宽,content略窄的单列(一栏)布局
对于第一种:
先通过对header,content,footer统一设置width:1000px;或者max-width:1000px(这两者的区别是当屏幕小于1000px时,前者会出现滚动条,后者则不会,显示出实际宽度);然后设置margin:auto实现居中即可得到。
https://codepen.io/AlexZ33/pen/WNNqoPx
<div class="header sameStyle"></div>
<div class="content sameStyle"></div>
<div class="footer sameStyle"></div>
.header {
background-color: blue;
height: 100px;
}
.content {
background-color: aquamarine;
height: 400px;
}
.footer {
background-color: aqua;
height: 100px;
}
.sameStyle {
max-width: 960px;
margin: 0 auto;
}
第二种,header、footer的内容宽度不设置,块级元素充满整个屏幕,但header、content和footer的内容区设置同一个width,并通过margin:auto实现居中。
https://codepen.io/AlexZ33/pen/xxxogZQ
<div class="header sameStyle">
<div class="nav sameStyle"></div>
</div>
<div class="content sameStyle"></div>
<div class="footer sameStyle"></div>
.header {
max-width: 960px;
height: 100px;
background-color: blue;
}
.nav {
height: 50px;
max-width: 800px;
background: darkgray;
}
.content {
max-width: 800px;
background: aquamarine;
height: 400px;
}
.footer {
max-width: 960px;
height: 100px;
background: aqua;
}
.sameStyle {
margin: 0 auto;
}
双栏(二列)布局
二列布局与三列布局的原理相同,将三列布局减少一个侧边栏即可得到二列布局。
左边定宽,右边自适应
一栏定宽,一栏自适应。这样子做的好处是定宽的那一栏可以做广告,自适应的可以作为内容主体。
特别是一些管理系统,比如左边显示信息或操作列表,右边显示详情,如下所示:
针对这种布局,首先抽象出页面结构如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
color: #fff;
font-size: 30px;
font-weight: bold;
text-align: center;
box-sizing: border-box;
}
aside {
width: 200px;
height: 200px;
padding-top: 75px;
background: #5A6A94;
}
section {
height: 200px;
padding-top: 75px;
background: #BE4F4F;
}
</style>
</head>
<body>
<!-- 左边定宽 -->
<aside class="left">Left</aside>
<!-- 右边自适应 -->
<section class="right">Right</section>
</body>
</html>
浏览器中效果:
需要实现的效果如下:
那么针对这种常见的布局,方式是非常多的,下面给出几种比较简单和常见的方法。
方法一:左边设置左浮动,右边宽度设置100%
【分析】这样的方式简单得让我怀疑,但是效果上确实是实现了。
方法二: 父容器设置 display:flex;Right部分设置 flex:1
【分析】display:flex; 设置为弹性盒子,其子元素可以通过设置 flex 的数值来控制所占空间的比例。
方法三:设置浮动 + 在 css 中使用 calc() 函数
【分析】
1. 浮动。(注意:为了不影响其他元素,别忘了在父级上清除浮动)
2. calc() = calc(四则运算) 用于在 css 中动态计算长度值,需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px)
;
3. vw: viewport width。1vw = viewport 宽度的 1%, 100vw = viewport width,
同样的还有 vh: viewport height。1vw = viewport 高度的 1%, 100vh = viewport height。
浏览器支持情况: 主流浏览器、IE10+
vw 和 vh 会随着viewport 的变化而变化,因此十分适合于自适应场景来使用。
方法四:使用负margin
首先修改页面结构,为自适应部分添加容器 .container, 同时改变左右部分的位置,如下:
设置样式:
【分析】
1. 首先设置左边部分和右边部分左浮动,并为自适应部分(Right)设置宽度100%。此时的效果是这样的:
2. 设置左边部分左外边距为负100%,此时效果如下:
但是右边部分的宽度仍然为100%,部分内容被 Left 所覆盖。
3. 为 Right 部分添加左边距(即 Left 部分的宽度)
此时可以看到,Right 部分的内容居中显示了。
1、float + margin:
<body>
<div class="left">定宽</div>
<div class="right">自适应</div>
</body>
.left{
width: 200px;
height: 600px;
background: red;
float: left;
display: table;
text-align: center;
line-height: 600px;
color: #fff;
}
.right{
margin-left: 210px;
height: 600px;
background: yellow;
text-align: center;
line-height: 600px;
}
示例1:
两列自适应
两列自适应布局是指一列由内容撑开,另一列撑满剩余宽度的布局方式
**
1.float+overflow:hidden实现
如果是普通的两列布局,浮动+普通元素的margin便可以实现,但如果是自适应的两列布局,利用float+overflow:hidden便可以实现,这种办法主要通过overflow触发BFC,而BFC不会重叠浮动元素。由于设置overflow:hidden并不会触发IE6-浏览器的haslayout属性,所以需要设置zoom:1来兼容IE6-浏览器
<div class="parent" style="background-color: lightgrey;">
<div class="left" style="background-color: lightblue;">
<p>left</p>
</div>
<div class="right" style="background-color: lightgreen;">
<p>right</p>
<p>right</p>
</div>
</div>
.parent {
overflow: hidden;
zoom: 1;
}
.left {
float: left;
margin-right: 20px;
}
.right {
overflow: hidden;
zoom: 1;
}
https://codepen.io/AlexZ33/pen/abzvjdb
注意点:如果侧边栏在右边时,注意渲染顺序。即在HTML中,先写侧边栏后写主内容
**
2.Flex来实现
Flex布局,也叫弹性盒子布局,区区简单几行代码就可以实现各种页面的的布局。
//html部分同上
.parent {
display:flex;
}
.right {
margin-left:20px;
flex:1;
}
https://codepen.io/AlexZ33/pen/PowPBNJ
3. grid布局实现
Grid布局,是一个基于网格的二维布局系统,目的是用来优化用户界面设计
//html部分同上
.parent {
display:grid;
grid-template-columns:auto 1fr;
grid-gap:20px
}
https://codepen.io/AlexZ33/pen/MWYaBex
三栏布局
三栏布局在前端开发中特别常见,即两边定宽,中间宽度自适应。最优的实现目前是双飞翼布局,兼容性和语义、以及加载性能都很好。
对于三栏布局,如下图:
特征:中间列自适应宽度,旁边两侧固定宽度
1、边栏固定中间自适应各方案对比
https://codepen.io/AlexZ33/pen/OJPyEYg
Float方法
- 元素浮动后,脱离了文档流,左右两栏分别浮动到窗口的两边
- 中间块紧跟在浮动元素之后,通过调整margin调整三者之间的间距
- dom结构必须是先浮动,再中间块。
实现
.left {
float: left;
height: 200px;
width: 200px;
background-color: red;
}
.right {
width: 200px;
height: 200px;
background-color: blue;
float: right;
}
.main {
margin-left: 220px;
margin-right: 220px;
height: 200px;
background-color: green;
}
注意dom元素的顺序
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
缺点
- 由于dom顺序,无法先加载content
- 显示的顺序和dom的顺序不一致,不好理解
绝对定位方式
绝对定位的元素也会脱离文档流,会相对于最近的定位的祖先元素进行定位。
实现
注意定位元素的设置
.main {
height: 200px;
margin: 0 220px;
background-color: green;
}
.left {
position: absolute;
width: 200px;
height: 200px;
top: 0;
left: 0;
background-color: red;
}
.right {
position: absolute;
width: 200px;
height: 200px;
background-color: blue;
top: 0;
right: 0;
}
dom节点可以随意排列
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
优缺点
优点:
- 可以按照dom的顺序排列,也可以将content排在前面。
缺点:
- 容器脱离了文档流,后代元素也脱离了文档流
- 高度未知的时候,会有问题
Table实现
实现
.container {
display: table;
width: 100%;
}
.left, .main, .right {
display: table-cell;
}
.left {
width: 200px;
height: 200px;
background-color: red;
}
.main {
background-color: green;
}
.right {
width: 200px;
height: 200px;
background-color: blue;
}
优缺点
优点:
- 兼容性良好
缺点:
- 无法设置栏边距
- 对seo不友好
- 高度会同时增加
grid布局
CSS Grid Layout的兼容性的确还是不容乐观,不过看起来也是已经一片绿了,api有可能还会变动,但是使用起来简单方便。
.container {
display: grid;
width: 100%;
grid-template-rows: 200px;
grid-template-columns: 200px auto 200px;
}
.left {
background-color: red;
}
.main {
margin: 0 20px;
background-color: green;
}
.right {
background-color: blue;
}
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
Flex布局
lex给我们布局提供很大的便利,很多在css2.1时代实现的很麻烦的布局,都可以通过flex很容易的实现,而且语义也很好。对三栏布局的实现,主要用到了flew-grow(发大比例,默认为0),flex-shrink(缩小比例,默认为1),flex-basis(计算是否有多余空间,默认为auto)。可以使用这三个属性的缩写形式,建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
**
// 默认值为0 1 auto
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
// 有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
.container {
display: flex;
}
.main {
flex: 1;
margin: 0 20px;
height: 200px;
background-color: green;
}
.left {
width: 200px;
height: 200px;
background-color: red;
}
.right {
width: 200px;
height: 200px;
background-color: blue;
}
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
2、圣杯布局
实现这些的目的就是在实现布局的基础上,content在dom的最前面,同时又有很好的兼容性。
.container {
margin-left: 220px; /* 为左右栏腾出空间 */
margin-right: 220px;
}
.main {
float: left;
width: 100%;
height: 200px;
background-color: green;
}
.left {
float: left;
width: 200px;
height: 200px;
margin-left: -100%;
position: relative;
left: -220px;
background-color: red;
}
.right {
float: left;
width: 200px;
height: 200px;
margin-left: -200px;
position: relative;
right: -220px;
background-color: blue;
}
DOM结构为中-左-右。.container设置margin-left和margin-right为左右栏腾出空间。
<div class="container">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
分析
- 给外围的container加上padding:0 220px 0 220px
- 将main部分放在最初的位置,加载最早,为了实现这样,只有将三者都采用float:left,为了调整两边栏的位置,给边栏再加上一个position:relative (因为相对定位后面会用到)
- main部分因为需要自适应,width:100%占满宽度,因此这个时候边栏都在下面一行。
- 这时因为main已经占满了,为了将left拉倒最左边,需要使用margin-left:-100%
- 这时right还停留在原来的位置,让right向左移动一个身位,marign-left:-200px,right就可以来到上方的最右边。
- 这时left会覆盖main的左端,对left使用使用相对定位left:-220px,同理right也要相对定位还原right:-220px
详解:
https://codepen.io/AlexZ33/pen/QWWXpWx
① 特点
比较特殊的三栏布局,同样也是两边固定宽度,中间自适应,唯一区别是dom结构必须是先写中间列部分,这样实现中间列可以优先加载
② 实现步骤
- 三个部分都设定为左浮动,否则左右两边内容上不去,就不可能与中间列同一行。然后设置center的宽度为100%(实现中间列内容自适应),此时,left和right部分会跳到下一行
- 通过设置margin-left为负值让left和right部分回到与center部分同一行
- 通过设置父容器的padding-left和padding-right,让左右两边留出间隙。
- 通过设置相对定位,让left和right部分移动到两边。
③ 缺点
- center部分的最小宽度不能小于left部分的宽度,否则会left部分掉到下一行
- 如果其中一列内容高度拉长(如下图),其他两列的背景并不会自动填充。(借助等高布局正padding+负margin可解决,下文会介绍)
3、双飞翼布局
杯布局实际看起来是复杂的后期维护性也不是很高,在淘宝UED的探讨下,出来了一种新的布局方式就是双飞翼布局,增加多一个div就可以不用相对布局了,只用到了浮动和负边距。
该布局的出现是出于让圣杯布局更好理解,语义化更好的目的。
.main {
float: left;
width: 100%;
height: 200px;
}
.left {
float: left;
width: 200px;
height: 200px;
margin-left: -100%;
/* position: relative;
left: -220px; */
background-color: red;
}
.right {
float: left;
width: 200px;
height: 200px;
margin-left: -200px;
/* position: relative;
right: -220px; */
background-color: blue;
}
.inner {
margin: 0 220px;
height: 200px;
background-color: green;
}
给main添加一个包裹,类似张鑫旭大神提出的“宽度分离准则”,利用这个准则就可以很好的利用块元素的流体特性,铺满可用空间。
分析
先将main部分放好,然后再将“翅膀”移动到相应的位置。
- main放在dom的最前面,紧接着是left、right
- 三部分都是float:left
- 将main铺满width:100%
- 这时将left拉上去margin-left:-100%,同理right使用margin-right:-200px。一直到这里都和圣杯布局很类似
- main被占满了,除了使用container的padding(圣杯),还可以给main增加一个内层div包裹,添加margin: 0 220px 0 220px
- 这时就可以了
详解
① 特点
同样也是三栏布局,在圣杯布局基础上进一步优化,解决了圣杯布局错乱问题,实现了内容与布局的分离。而且任何一栏都可以是最高栏,不会出问题。
.container {
min-width: 600px;//确保中间内容可以显示出来,两倍left宽+right宽
}
.left {
float: left;
width: 200px;
height: 400px;
background: red;
margin-left: -100%;
}
.center {
float: left;
width: 100%;
height: 500px;
background: yellow;
}
.center .inner {
margin: 0 200px; //新增部分
}
.right {
float: left;
width: 200px;
height: 400px;
background: blue;
margin-left: -200px;
}
<article class="container">
<div class="center">
<div class="inner">双飞翼布局</div>
</div>
<div class="left"></div>
<div class="right"></div>
</article>
② 实现步骤(前两步与圣杯布局一样)
- 三个部分都设定为左浮动,然后设置center的宽度为100%,此时,left和right部分会跳到下一行;
- 通过设置margin-left为负值让left和right部分回到与center部分同一行;
- center部分增加一个内层div,并设margin: 0 200px;
③ 缺点
多加一层 dom 树节点,增加渲染树生成的计算量。
两种布局实现方式对比:
- 都是把主列放在文档流最前面,使主列优先加载。
- 实现上也有相同之处,都是让三列浮动,然后通过负外边距形成三列布局。
- 不同之处在于如何处理中间主列的位置:
圣杯布局是利用父容器的左、右内边距+两个从列相对定位;
双飞翼布局是把主列嵌套在一个新的父级块中利用主列的左、右外边距进行布局调整
总结
对于中间自适应的实现,我们需要利用其流体特性,而因为我们又必须考虑兼容性,又要让main最先加载到dom中,对整体的布局影响又较小。
简单的Float方式dom的顺序不可修改,main需要最后添加;绝对布局的方式脱离了文档流,对布局影响较大;Table布局会越来越少,而且其高度、间隔的也有限制;flex,grid的方式兼容性还是个问题;圣杯布局虽好,但是position:realtive和相对定位的添加,使得代码不好理解,可维护性较差。
综合分析,双飞翼布局相对于圣杯布局,增加了一个div,完美使用了宽度分离准则,使得代码更好理解,可维护性最高。
等高布局
等高布局是指子元素在父元素中高度相等的布局方式。接下来我们介绍常见几种实现方式:
1.利用正padding+负margin
我们通过等布局便可解决圣杯布局的第二点缺点,因为背景是在 padding 区域显示的,设置一个大数值的 padding-bottom,再设置相同数值的负的 margin-bottom,并在所有列外面加上一个容器,并设置 overflow:hidden 把溢出背景切掉。这种可能实现多列等高布局,并且也能实现列与列之间分隔线效果,结构简单,兼容所有浏览器。新增代码如下
.center,
.left,
.right {
padding-bottom: 10000px;
margin-bottom: -10000px;
}
.container {
padding-left: 220px;
padding-right: 220px;
overflow: hidden;//把溢出背景切掉
}
https://codepen.io/AlexZ33/pen/rNaOryX
2.利用背景图片
这种方法是我们实现等高列最早使用的一种方法,就是使用背景图片,在列的父元素上使用这个背景图进行Y轴的铺放,从而实现一种等高列的假象。实现方法简单,兼容性强,不需要太多的css样式就可以轻松实现,但此方法不适合流体布局等高列的布局。
在制作样式之前需要一张类似下面的背景图:
<div class=”container clearfix”>
<div class=”left”></div>
<div class=”content”></div>
<div class=”right”></div>
</div>
.container {
background: url("column.png") repeat-y;
width: 960px;
margin: 0 auto;
}
.left {
float: left;
width: 220px;
}
.content {
float: left;
width: 480px;
}
.right {
float: left;
width: 220px;
}
3.模仿表格布局
这是一种非常简单,易于实现的方法。不过兼容性不好,在ie6-7无法正常运行。
<div class="container table">
<div class="containerInner tableRow">
<div class="column tableCell cell1">
<div class="left aside">
....
</div>
</div>
<div class="column tableCell cell2">
<div class="content section">
...
</div>
</div>
<div class="column tableCell cell3">
<div class="right aside">
...
</div>
</div>
</div>
</div>
.table {
width: auto;
min-width: 1000px;
margin: 0 auto;
padding: 0;
display: table;
}
.tableRow {
display: table-row;
}
.tableCell {
display: table-cell;
width: 33%;
}
.cell1 {
background: #f00;
height: 800px;
}
.cell2 {
background: #0f0;
}
.cell3 {
background: #00f;
}
4.使用边框和定位
这种方法是使用边框和绝对定位来实现一个假的高度相等列的效果。结构简单,兼容各浏览器,容易掌握。假设你需要实现一个两列等高布局,侧栏高度要和主内容高度相等。
#wrapper {
width: 960px;
margin: 0 auto;
}
#mainContent {
border-right: 220px solid #dfdfdf;
position: absolute;
width: 740px;
height: 800px;
background: green;
}
#sidebar {
background: #dfdfdf;
margin-left: 740px;
position: absolute;
height: 800px;
width: 220px;
}
<div id="wrapper">
<div id="mainContent">...</div>
<div id="sidebar">...</div>
</div>
5. display:table实现多列等高布局
6. display:flex实现多列等高布局
https://codepen.io/AlexZ33/pen/ExaVpYB
粘连布局
1.特点
- 有一块内容
<main>
,当<main>
的高度足够长的时候,紧跟在<main>
后面的元素<footer>
会跟在<main>
元素的后面。 - 当
<main>
元素比较短的时候(比如小于屏幕的高度),我们期望这个<footer>
元素能够“粘连”在屏幕的底部
<div id="wrap">
<div class="main">
main <br />
main <br />
main <br />
</div>
</div>
<div id="footer">footer</div>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;//高度一层层继承下来
}
#wrap {
min-height: 100%;
background: pink;
text-align: center;
overflow: hidden;
}
#wrap .main {
padding-bottom: 50px;
}
#footer {
height: 50px;
line-height: 50px;
background: deeppink;
text-align: center;
margin-top: -50px;
}
2.实现步骤
(1)footer必须是一个独立的结构,与wrap没有任何嵌套关系
(2)wrap区域的高度通过设置min-height,变为视口高度
(3)footer要使用margin为负来确定自己的位置
(4)在main区域需要设置 padding-bottom。这也是为了防止负 margin 导致 footer 覆盖任何实际内容。
flex布局
- 盒子排成一行
demo:
https://codepen.io/AlexZ33/pen/GRRbwxZ
实践:
- 父元素100%宽度
https://codepen.io/AlexZ33/pen/ExxBOEG
- 我们可以给每个子盒子用
width: 25%
,它确实能够生效,但是flexbox弹性盒子自己就是可伸缩的,我们没必要给它一个具体的width 。比如用flex: 1
,应用到子组件,让他们能够伸缩填充整个空间
https://codepen.io/AlexZ33/pen/MWWMzXG
- 更复杂点呢,我们其实不用做任何数学计算和硬编码就能实现一个文字文本布局
https://codepen.io/AlexZ33/pen/qBBzgqP
- 你还可以
https://codepen.io/AlexZ33/pen/qBBzgRV
- 当页面缩小的时候
https://codepen.io/AlexZ33/pen/qBBzgRV?editors=1100
- 还可以 flex-wrap
https://codepen.io/AlexZ33/pen/qBBzgRV
- 如果我想我自己的 box排在第一个呢, 我可以重新编辑盒子顺序(order), 使用
order: -1
https://codepen.io/AlexZ33/pen/bGGPzPV
- 给我的块 占一行
flex-basis: 100%
https://codepen.io/AlexZ33/pen/bGGPzPV
-
当屏幕小于600px时候纵向排布,并且子box占据一行
- flex-direction: column;
- display: block;(与其更改所有的flexbox内容以处理列布局,不如将其关闭。)
https://codepen.io/AlexZ33/pen/QWWXREe
利用 Flexbox 去除多余的外边距
与其使用 nth-
, first-
, 和 last-child
去除列之间多余的间隙,不如使用 flexbox 的 space-between
属性:
.list {
display: flex;
justify-content: space-between;
}
.list .person {
flex-basis: 23%;
}
常用经典布局
作业
1、 任选一个卡片,实现其布局
参考进度条
https://c.runoob.com/codedemo/3105
参考五星(纯css实现,正常项目我们用的贴图)
https://codepen.io/JowayYoung/pen/MWgjGMj
2、应用今天所学, 实现task02的页面 -->如图
3、分别尝试使用Float、Position或者Flexbox来实现如下需求:
- 实现一个两栏布局,左侧占30%宽度,右侧占70%宽度
- 实现一个两栏布局,左侧固定宽度,右侧根据浏览器宽度进行自适应变化
- 实现一个两栏布局,右侧固定宽度,左侧根据浏览器宽度进行自适应变化
- 实现一个三栏布局,左侧固定宽度,右侧固定宽度,中间部分宽度随浏览器宽度变化而自适应变化
- 实现一个三栏布局,左侧固定宽度,中间固定宽度,右侧根据浏览器宽度变化而自适应变化
要求:
- 每一个需求都尽可能多地用多种方式来实现
vscode常见快捷键
shift
+alt
+↓
是快速复制当前行到下一行
拓展阅读
如果有同学觉得太简单,不妨花上3个小时来阅读 CSS 的标准文档,至于看标准规范有什么用,欢迎移步看CSS专家顾轶灵的知乎回答,以及貘吃馍香的回答。另外HTML也是,有时间可以读一下规范,这样你也可以像这样回答问题
- 学习CSS布局
- CSS Backgrounds and Borders Module Level 3 规范
- [Relationships between 'display', 'position', and 'float']()
- CSS Page Floats
- The Clearfix: Force an Element To Self-Clear its Children
- float mdn
- CSS 布局-浮动
- W3C-float
- 如何理解 CSS 中的浮动布局方式?最主要的功能是什么?如何正确地使用它?
- What methods of ‘clearfix’ can I use?
- Getting Started With CSS Layout
- 学习CSS布局
- MDN 定位
- MDN 定位实战
- MDN Flexbox
- CSS布局(三) 布局模型
- CSS布局(四) Float
- CSS布局(五) 网页布局方式
- CSS布局(六) 对齐方式
- 七种实现左侧固定,右侧自适应两栏布局的方法
- 圣杯布局
- 双飞翼布局
- 圣杯布局和双飞翼布局
- CSS深入理解流体特性和BFC特性下多栏自适应布局
- 三种三栏网页宽度自适应布局方法
- The Different Kinds of CSS Layout
- Centering in CSS: A Complete Guide
- The Thought Process Behind a Flexbox Layout
- A Complete Guide to Flexbox
- A Complete Guide to Grid
- flex-shrink mdn
- flex-direction mdn
- Flex 布局教程:语法篇
- Flex 布局教程:实例篇
- [[译] 渐进增强的 CSS 布局:从浮动到 Flexbox 到 Grid](https://juejin.im/post/5987ac...
- 理解 CSS 布局和 BFC
- 【布局】聊聊为什么淘宝要提出「双飞翼」布局
- CSS Layout 字典
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。