Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSSS教程: CSS (中) #77

Open
AlexZ33 opened this issue Mar 3, 2020 · 0 comments
Open

CSSS教程: CSS (中) #77

AlexZ33 opened this issue Mar 3, 2020 · 0 comments

Comments

@AlexZ33
Copy link
Owner

AlexZ33 commented Mar 3, 2020

CSS (中)

回顾

HTML5新增的那些

HTML5标准更加的讲究语义化了,借用一张网上的图来说明这些新标签

  • header元素:header 元素代表“网页”或“section”的页眉。
  • footer元素:footer元素代表“网页”或“section”的页脚,通常含有该节的一些基本信息,譬如:作者,相关文档链接,版权资料。
  • 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页脚。

推荐看原博主的博客:传送门

常见问题

为什么出现二级标题比一级的大?

image.png
image.png

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

边框内圆角

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。这个问题,还是需要仔细思考一下的。
到此为止,布局最基本的部分我们已经将去大半,还有就是一块浮动。

正常文档流

image.png

如果你选择没有用任何CSS来改变页面布局的网页,那么HTML元素就会排列在一个正常流(Normal Flow)之中。在正常流中,元素盒子(任何一个HTML元素其实就是一个盒子)会基于文档的写作模式一个接一个地排列(根据不同的文档写作模式,排列方向不一样)。这就意味着,如果你的写作模式是水平的(句子是从左到右或从右到左写),正常流会垂直地一个接一个排列页面的块级元素。如果你是在一个垂直方向的写作模式下,句子是垂直方向书写的,那么块级元素会水平方向排列。


确保书写的页面具有良好的结构(HTML结构),可以最大程度复用正常文档流

  • 如果浏览器中没有正常流,那么你创建的HTML元素都会堆积在浏览器的右上角。这就意味着,你必须指定所有的HTML元素的布局方式。
  • 有了正常流,哪怕是CSS加载失败了,用户仍然能阅读你的页面内容;

布局技术会覆盖默认的布局行为:
**

  • ** display **属性 — 标准的value,比如block, inline 或者 inline-block 元素在正常布局流中的表现形式 (见 Types of CSS boxes). 接着是全新的布局方式,通过设置display的值, 比如 CSS GridFlexbox.
  • 浮动——应用 float 值,诸如 left 能够让块级元素互相并排成一行,而不是一个堆叠在另一个上面。
  • **position **属性 — 允许你精准设置盒子中的盒子的位置,正常布局流中,默认为 static ,使用其它值会引起元素不同的布局方式,例如将元素固定到浏览器视口的左上角。
  • 表格布局— 表格的布局方式可以用在非表格内容上,可以使用display: table和相关属性在非表元素上使用。
  • 多列布局— 这个 Multi-column layout 属性 可以让块按列布局,比如报纸的内容就是一列一列排布的。

拓展阅读 --> 

脱离文档流

一旦页面有一个良好的结构,你就需要去决定如何利用它并将它变为我们需要的布局结构。这会涉及到脱离正常文档流

浮动

image.png
image.png

float(浮动)

浮动被用来将元素盒子向左或向右移动,同时让内容环绕其展示。
要让一个元素进行浮动,需要给该元素的flaot属性设置为leftrightfloat的默认值为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; }

绝对定位

image.png

定位

定位的概念就是它允许你定义一个元素相对于其他正常元素的位置,它应该出现在哪里,这里的其他元素可以是父元素,另一个元素甚至是浏览器窗口本身。还有就是浮动了,其实浮动并不完全算是定位,它的特性非常的神奇,以至于它在布局中被人广泛的应用。我们会在后文中专门提及它的。
谈及定位,我们就得从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:

实践:

https://www.xiaomiyoupin.com/

image.png

https://game.xiaomi.com/

image.png

定位&居中

水平居中

(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、最常用方法

怎么垂直对齐容器中的元素是最佳实践呢?

  • 现在,利用CSS3Transform,可以很优雅的解决这个困惑:
.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、水平+垂直对齐

  1. text-align + vertical-align  在父元素设置text-alignvertical-align,并将父元素设置为table-cell元素,子元素设置为inline-block元素

```css <style> .parent{ display: table-cell; text-align: center; vertical-align: middle; } .child{ display: inline-block; } </style> ``` ** ```css
测试文字
``` ![](https://cdn.nlark.com/yuque/0/2019/png/247789/1574772937268-43a989ce-f279-40b4-b0ba-b5a20bf90f55.png#align=left&display=inline&height=99&originHeight=99&originWidth=199&size=0&status=done&style=none&width=199)

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

实践:
image.png

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:

示例2
https://alexz33.github.io/

两列自适应

两列自适应布局是指一列由内容撑开,另一列撑满剩余宽度的布局方式
**

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实现

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

实践:
image.png

  • 父元素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


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、 任选一个卡片,实现其布局

image.png

image.png

参考进度条
https://c.runoob.com/codedemo/3105

参考五星(纯css实现,正常项目我们用的贴图)
https://codepen.io/JowayYoung/pen/MWgjGMj

2、应用今天所学, 实现task02的页面 -->如图  https://gitee.com/turingitclub/css-learning/blob/dev/task02/task_1_2_1.jpg

参考: https://gitee.com/turingitclub/css-learning/tree/dev/task02


3、分别尝试使用Float、Position或者Flexbox来实现如下需求:

  • 实现一个两栏布局,左侧占30%宽度,右侧占70%宽度
  • 实现一个两栏布局,左侧固定宽度,右侧根据浏览器宽度进行自适应变化
  • 实现一个两栏布局,右侧固定宽度,左侧根据浏览器宽度进行自适应变化
  • 实现一个三栏布局,左侧固定宽度,右侧固定宽度,中间部分宽度随浏览器宽度变化而自适应变化
  • 实现一个三栏布局,左侧固定宽度,中间固定宽度,右侧根据浏览器宽度变化而自适应变化

要求:

  • 每一个需求都尽可能多地用多种方式来实现

vscode常见快捷键

shift+alt+是快速复制当前行到下一行

拓展阅读

如果有同学觉得太简单,不妨花上3个小时来阅读 CSS 的标准文档,至于看标准规范有什么用,欢迎移步看CSS专家顾轶灵的知乎回答,以及貘吃馍香的回答。另外HTML也是,有时间可以读一下规范,这样你也可以像这样回答问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant