CSS教程: CSS (中)

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页脚。

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

    常见问题

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

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


    <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

    实践:
    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的页面 -->如图  



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

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

    要求:

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

    vscode常见快捷键

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

    拓展阅读

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

    阅读 395

    推荐阅读
    镜心的小树屋
    用户专栏

    方寸湛然GitHub组织地址:[链接]

    46 人关注
    122 篇文章
    专栏主页