CSS的使用(下) | 青训营

104 阅读8分钟

五、CSS布局方式及相关技术

布局:确定内容的大小和位置的算法(分块)

  • 依据元素、容器、兄弟节点和内容等信息来计算。

三种布局方式:

  • 常规流(normal flow):块级规则,行级规则,table表格布局,FlexBox排版上下文,Grid布局

    • 根元素、浮动和绝对定位的元素会脱离常规流
    • 其他元素都在常规流之内
    • 常规流中的盒子,在某种排版上下文(描述盒子的排布方式)中参与布局
  • 浮动:通过将元素从常规流中移动并使其向左或向右浮动,来实现网页中元素的位置控制。浮动可以使元素脱离常规流,并且允许其他元素环绕在其周围。如将文字环绕图片的效果。

  • 绝对定位:可以盖在常规流上面,任意改变元素的位置而不对常规流产生影响。

5.1 盒模型 box-sizing

widthheightpaddingbordermargin

  1. content-box:

默认情况下指定widthheight通常指content的。

  • width:

    • 指定的是content的宽度
    • 取值为长度、百分数、auto
    • auto由浏览器根据经其他属性确定
    • 百分数:相对于容器(当前元素所在的盒子)的content box宽度
  • height:

    • 同上
    • auto取值由内容计算得来
    • 容器有指定的高度时,百分数才生效
  • padding:

    • padding-toppadding-rightpadding-bottompadding-left
    • 百分数:相对于容器的宽度
    • 正方形;上下、左右;顺时针
  • border:

    • 三种属性:border-width,border-style,border-color

    • 四个方向

    • 可组合搭配:

      当四条边框颜色不同,宽高为0时:可以改变粗细、颜色、透明度设置各种各样的图形

  • margin:

    • 取值可以是长度、百分数、auto
    • 百分数:相对于容器的宽度
    • margin-left: auto;margin-right: auto;:水平居中
    • margin collapse:垂直方向上margin会合并,取两者的最大值
  1. border-box:

    宽和高包括borderpaddingcontent

overflow属性:控制内容溢出盒子的高的部分该怎么展示

  • visible:默认,仍然展示出溢出的部分
  • hidden:溢出的部分不限时
  • scroll:滚动条
  • auto:超出了就滚动

5.2 盒模型中常见的布局规则

5.2.1 常规流

行级与块级

  • 盒子的摆放规则不同:

    块级盒子不和其他盒子并列摆放

    行级盒子和其他行级盒子一起放在一行或拆成多行

  • 块级元素生成块级盒子

    body,article,div,main,section,h1-6,p,ul,li等

    display : block

  • 行级元素生成行级盒子,内容分散在多个行盒中

    span,em,strong,cite,code等

    display : inline

  • display属性:block , inline

    inline-block:本身是行级,可以放在行盒中;可以设置宽高;作为一个整体不会被拆散成多行(inline-block里面的元素都是行级,整体是块级,例如:图片和文字放在同一行)

    none:排版时完全被忽略

行级排版上下文
  • Inline Formatting Context (IFC)

  • 只包含行级盒子的容器会创建一个IFC

  • IFC内的排版规则

    • 盒子在一行内水平摆放
    • 一行放不下时,换行显示
    • text-align决定一行内盒子的水平对齐
    • vertical-align决定一个盒子在行内的垂直对齐
    • 避开浮动(float)元素
  • 例:

    div为块级元素,但内部只包含行级盒子,则div创建的为行级上下文

    <div>
      This is a paragraph of text with long word Honorificabilitudinitatibus. Here is an image
      <img src="https://assets.codepen.io/59477/cat.png" alt="cat">
      And <em>Inline Block</em>
    </div>
    
    <style>
      div {
        width: 10em;
        //overflow-wrap: break-word;
        background: #411;
      }
    
      em {
        display: inline-block;
        width: 3em;
        background: #33c;
      }
    </style>
    

    若将emdisplay: inline-block;注释掉,//overflow-wrap: break-word;去掉注释,则变为:

块级排版上下文
  • Block Formatting Context(BFC)

  • 某些容器会创建一个BFC,容器:

    • 根元素,即<html>
    • 浮动、绝对定位、inline-block
    • Flex子项和Gird子项
    • overflow值不是visible的块盒
    • display:flow-root;
  • BFC内的排版规则

    • 盒子从上到下摆放

    • 垂直margin合并

    • BFC内的盒子的margin不会与外面的合并

      (所以,若不想让两个盒子的margin合并,则可以把这两个盒子分散在不同的BFC里面,例如,给一个元素嵌套一个div,将该div设置成display:flow-root;overflow:hidden创建了一个BFC,与下面的盒子分属于两个不同的BFC,不会合并)

    • BFC不会和浮动元素重叠

例:行级盒子(文本内容:匿名行盒)和块级盒子同处于一个父级span里面(但不允许一个父级里面既有行级又有块级)所以创建两个匿名块级盒子把两段文字包起来。

实际的渲染结果可能是这样的:

  1. 创建匿名块级盒子(盒子A),其中包含行内文本 "This is a text and"。
  2. 创建块级盒子(盒子B),作为 <div> 元素的容器,包含块级元素 <div>
  3. 创建匿名块级盒子(盒子C),其中包含文本 "and other text."。

盒子A和盒子C是匿名的块级盒子,用于包裹行内文本部分,以确保同时包含行内和块级内容的正确排版。

<span>
  This is a text and
  <div>block</div>
  and other text.
</span>

<style>
  span {
    line-height: 3;
    border: 2px solid red;
    background: coral;
  }

  div {
    line-height: 1.5;
    background: lime;
  }
</style>

块级和行级布局只能实现一些简单的效果,没法实现更灵活的布局方式,所以提出了更新的排版上下文。

Flex Box(弹性盒子布局)

通过flex box(常用布局)的一些属性控制容器内的子元素:

  • 可以控制子集盒子的:

    • 摆放的流向(→(默认) ← ↑ ↓)

      • flex-direction:决定了弹性项目的排列方向。
      • row(→)、column(↓)、row-reverse(水平反向)或 column-reverse(垂直反向)。
    • 摆放顺序

      • order:用于控制弹性项目的显示顺序,设置为1等数字,从小到大排。
    • 是否允许拆行(换行)

    • 水平和垂直方向的对齐

      • 分为主轴justify-content和侧轴align-itemsalign-items设置在容器上,默认为stretch)。
      • align-self:针对某个特定的子元素设定一个样式,覆盖了父容器的 align-items
    • 盒子的宽度和高度

      • Flexibility:设置子项的弹性,当容器有剩余空间时,伸展;容器空间不足时,收缩。

      • flex-growflex-shrinkflex-basis:用于控制弹性项目的增长、收缩和基础大小。

      • flex:是 flex-growflex-shrinkflex-basis 的简写属性。

        flex : 1flex-grow:1flex-shrink:1flex-basis:auto

      •   <div class="container">
            <div class="a">A</div>
            <div class="b">B</div>
            <div class="c">C</div>
          </div>
          <style>
            .container {
              display: flex;
              border: 2px solid #966;
            }
        
            .a, .b, .c {
              text-align: center;
              padding: 1em;
            }
        
            .a {
              background: #fcc;
            }
        
            .b {
              background: #cfc;
            }
        
            .c {
              background: #ccf;
            }
          </style>
        

        image-20230811125649298转存失败,建议直接上传图片文件

      • 将剩余空间按照2:1分给A和B

        <div class="container">
          <div class="a">A</div>
          <div class="b">B</div>
          <div class="c">C</div>
        </div>
        
        <style>
          .container {
            display: flex;
            border: 2px solid #c66;
            height: 100px;
          }
        
          .a, .b, .c {
            width: 100px;
            text-align: center;
            padding: 1em;
          }
        
          .a {
            flex-grow: 2;
          }
        
          .b {
            flex-grow: 1;
          }
        </style>
        
      • 页面长度不够400,需要压缩。A为刚性,不能压缩;B和C宽度不够了 进行压缩,分配相同的宽度。

        <div class="container">
          <div class="a">A</div>
          <div class="b">B</div>
          <div class="c">C</div>
        </div>
        
        <style>
          .container {
            display: flex;
            border: 2px solid #c66;
            height: 100px;
          }
        
          .a, .b, .c {
            width: 400px;
            text-align: center;
            padding: 1em;
          }
        
          .a {
            flex-shrink: 0;
          }
        </style>
        

Grid布局(网格布局)

CSS布局中最强大的。 文档上解释比较详细,用法多。

步骤:

  • 网格容器:display: grid;使元素生成一个块级的Gird容器。

  • 网格行和列:使用gird-template相关属性将容器划分为网格。

    • 使用属性 grid-template-rowsgrid-template-columns 来定义网格容器的行和列。可以使用像像素、百分比、自动调整和分数等单位。
    • 例: image.png
    • 例:1fr:一份,列:即B与C各占一份;行:D将剩下的占满 image.png
  • 网格线和网格区域:设置每一个子项占哪些行列

    • grid-row-start + grid-column-start + grid-row-end + grid-column-end = grid-area
    • 例: image.png
    • 例:

      image.png

5.2.2 float 浮动

为了实现文字环绕的效果。

<img>设置了float属性,<p>标签仍从<section>最开始排版,但绕开<img>

<section>
  <img src="https://p4.ssl.qhimg.com/t017aec0e7edc961740.jpg" width="300" alt="mojave" />
  <p>莫哈韦沙漠不仅纬度较高,而且温度要稍微低些,是命名该公园的短叶丝兰——约书亚树的特殊栖息地。约书亚树以从茂密的森林到远远间隔的实例等各种形式出现。
  </p>
</section>

<style>
  img {
    float: left;
  }

  p {
    font-size: 20px;
    line-height: 1.8;
  }
</style>

5.2.3 绝对定位

position属性:

  • static:默认值,非定位元素,参与常规流的布局

  • relative:相对于自身原本位置偏移,不脱离文档流

  • absolute:绝对定位,将一个元素从其正常在文档流中的位置脱离出来(即常规流布局时当absolute元素不存在一样),相对最近的非static祖先元素定位:设置 toprightbottomleft 属性

  • fixed:相对于视口(viewpoint)绝对定位,也脱离常规流

  • absolute例:

没有其他已定位的祖先元素,.box 将相对于文档的初始包含块进行定位。初始包含块通常是浏览器窗口的可视区域。

<h1>页面标题</h1>
<div class="container">
  <div class="box"></div>
  <p>段落内容段落内容 1</p>
  <p>段落内容段落内容 2</p>
  <p>段落内容段落内容 3</p>
  <p>段落内容段落内容 4</p>
</div>

<style>
  .container {
    background: lightblue;
  }

  .box {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    background: red;
  }
</style>
  • fixed例:
<nav>
  <a href="#">首页</a>
  <a href="#">导航1</a>
  <a href="#">导航2</a>
</nav>
<main>
  <section>1</section>
  <section>2</section>
  <section>3</section>
  <section>4</section>
  <section>5</section>
</main>
<a href="#" class="go-top">返回顶部</a>

<style>
  nav {
    position: fixed;
    line-height: 3;
    background: rgba(0, 0, 0, 0.3);
    width: 100%;
  }
  
  .go-top {
    position: fixed;
    right: 1em;
    bottom: 1em;
    color: #fff;
  }

  nav a {
    padding: 0 1em;
    color: rgba(255, 255, 255, 0.7);
  }

  nav a:hover {
    color: #fff;
  }

  body {
    margin: 0;
    font-size: 14px;
  }

  a {
    color: #fff;
    text-decoration: none;
  }

  section {
    height: 50vh;
    color: #fff;
    text-align: center;
    font-size: 5em;
    line-height: 50vh;
  }

  section:nth-child(1) {
    background: #F44336;
  }

  section:nth-child(2) {
    background: #3F51B5;
  }

  section:nth-child(3) {
    background: #FFC107;
  }

  section:nth-child(4) {
    background: #607D8B;
  }

  section:nth-child(5) {
    background: #4CAF50;
  }
</style>

流的嵌套

绝对定位元素内部的元素是一个新的常规流;flex布局子项也是一个新的流,等等。

六、调试CSS

右键点击页面,选择检查,可以直接看如何实现的一些效果。

快捷键:Ctrl+Shift+I