理解CSS | 青训营笔记

73 阅读9分钟

这是我参与「第四届青训营」笔记创作活动的的第 1天

一、本堂课重点内容:

  • 学习什么是 CSS (Cascading Style Sheets)
  • 学习如何在页面中使用 CSS
  • CSS 在页面中是如何工作的

二、详细知识点介绍:

  • CSS 用于定义页面元素的样式(例如字体、颜色、位置和大小等等)
  • CSS 的结构由选择器(Selector)、属性(Property)、属性值(Value) 组成,其中属性和属性值组成一个声明(Declaration)
  • 在页面中使用 CSS 有三种方式:外链、嵌入和内联

    • 推荐优先使用外链:能够使得内容和样式分离
    • <!-- 外链(推荐) -->
      <link rel="stylesheet" href="/assets/style/style.css">
      
      <!-- 嵌入 -->
      <style>
        h1 {margin: 20px;}
      </style>
      
      <!-- 内联 -->
      <h1 style="margin: 20px">Hello World!</h1>
      
  • CSS 在页面的工作流程图

    流程图.jpg

选择器(Selector)

  1. 用于找出页面中的元素并设置样式
  1. 选择器有五种:通配选择器、标签选择器、ID 选择器、类选择器和属性选择器

    1. 属性选择器(例如 [disabled] 等) - 匹配含有该属性的元素
    2. 类选择器(.) - 匹配元素中的 Class 属性
    3. ID 选择器(#) - 匹配元素中的 ID 属性
    4. 标签选择器(例如 h1 等) - 匹配含有该标签的元素
    5. 通配选择器(*) - 匹配页面中的所有元素

子串匹配的属性选择符

表达式描述
E[att^="val"]匹配具有att属性、且值以val开头的E元素
E[att$="val"]匹配具有att属性、且值以val结尾的E元素
E[att*="val"]匹配具有att属性、且值中含有val的E元素

伪类(Pseudo-classes)

  • 伪类常用的有状态伪类结构性伪类

状态伪类

选择器描述
:active选择活动的链接。
:focus鼠标在元素上聚焦的状态
:link未访问的链接
:visited已访问的链接
:hover鼠标悬停在元素上的状态

结构性伪类

选择器例子描述
:not(selector):not(p)选择所有 p 以外的元素
:first-childp:first-child选择器匹配属于任意元素的第一个子元素的

元素

:first-of-typep:first-of-type选择的每个 p 元素是其父元素的第一个 p 元素
:last-childp:last-child选择所有 p 元素的最后一个子元素
:last-of-typep:last-of-type选择每个 p 元素是其母元素的最后一个 p 元素
:only-childp:only-child选择所有仅有一个子元素的 p 元素
:nth-child(n)p:nth-child(2)选择所有 p 元素的父元素的第二个子元素
:nth-last-child(n)p:nth-last-child(2)选择所有 p 元素倒数的第二个子元素
:nth-last-of-type(n)p:nth-last-of-type(2)选择所有 p 元素倒数的第二个为 p 的子元素
:nth-of-type(n)p:nth-of-type(2)选择所有 p 元素第二个为 p 的子元素
:only-of-typep:only-of-type选择所有仅有一个子元素为 p 的元素
:target#news:target选择当前活动 #news 元素(点击 URL 包含锚的名字)

组合(Combinators)

名称语法说明例子
直接组合AB满足 A 同时也满足 Binput:focus
后代组合A B选中 B,如果它是 A 的子孙p a
亲子组合A > B选中 B,如果它是 A 的子元素p > em
兄弟选择器A ~ B选中 B,如果它在 A 后且与 A 同级h2 ~ p
相邻选择器A + B选中 B,如果它紧跟在 A 后h2 + p
  • 选择器组

    • body, h1, h2, h3 {
        margin: 0;
      }
      

属性 (Property)

颜色(Color)

  • 十六进制颜色代码 - #FFFFFF
  • RGB - rgb(255, 255, 255)
  • HSL - hsl(18, 91%, 84%)

    • Hue(H) - 色相 - 范围 0-360
    • Saturation(S) - 饱和度 - 范围 0~100%
    • Lightness(L) - 亮度 - 范围 0~100%
  • Alpha 透明度(不透明度) - 范围 0~1 - 越大越不透明

    • 十六进制颜色代码 - #FFFFFFFF
    • RGB - rgba(255, 255, 255, 1)
    • HSL - hsl(18, 91%, 84%, 1)

字体(Font)

  1. 在选择字体时,最好在最后放上一个通用字体族,以来保证字体的正常显示。
  1. 当想要为不同语言设置不同字体时,应将部分的放在前面,例如下面为英文设置英文字体

    1. body {
        font-family: Helvetica, Microsoft YaHei, sans-setif;
      }
      
    2.   当遇到英文时则使用 Helvetica ,当遇到中文时由于 Helvetica 字体无中文字体,因此则跳转到下一个使用 Microsoft YaHei ,若遇到 Microsoft YaHei 也没有包含的字体时,则会跳转到通用字体族 sans-setif

属性值(Value)

  • 在 CSS 中,每个属性一个初始值
  • 可以使用 initial 关键字显式重置为初始值

特异度(Specificity)

当我们编写 CSS 的时候,有时候会因自己的疏忽导致同一元素下重复,例如下面的代码

<div>
  <h1 class="title">Title</h1>
</div>

<style>
  .title {
    color: #000000;
  }
  
  div h1 {
    color: #ffffff;
  }
</style>

那么这时候 CSS 的优先级则是根据该选择器的特异度来判断的

组成

特异度的分数由 ID(#)、(伪)类(.)、标签(E) 三部分组成,这三部分分别对应着百位、十位和个位,让我们来举个例子:

  • #nav .list li a:link

    • ID - 1 - #nav
    • (伪)类 - 2 - .list & :link
    • 标签 - 2 - li & a

继承(Inherit)

某些属性会自动继承其父元素的计算值,除非显式指定一个值,那么如何简单的进行显式继承呢,来看看下面的例子吧

* {
  box-sizing: inherit;
}

取值过程

  1. DOM 树 和 样式规则 传入 filtering
  1. filtering(通过选择器匹配、属性有效和符合当前 media 等条件进行过滤
  1. 过滤后可能会有多个声明值(Declared Values),例如 p {font-size: 16px} 和 p.next {font-size: 2em}
  1. 在层叠过程中,将声明值传入 cascading 通过来源、!important、特异度、书写顺序等条件筛选出优先级最高的一个属性值则为层叠值(Cascaded Value)
  1. 将层叠值放入 defaulting 中,当层叠值为空的时候则使用继承或者初始值,经过前面的处理后将获得一个指定值(Specified Value),由于 CSS 的每个属性都有自己的初始值,所以一定不为空
  1. 将指定值放入 resolving 中,将指定值中的一些相对值或者关键字转换为绝对值,例如将 em 转换为 px ,相对路径转换为绝对路径等等,转换后则为计算值(Computed Value)

    在 resolving 中相对值的转换仅针对能从 CSS 直接分析出来的,例如父级为 20px,则当子级为 2em 时则转换后则为(20 * 2)40px

  1. 将计算值放入 formatting 中,对计算值进行进一步的转换,将关键字和百分比转换为绝对值,此时的转换是从实际布局出手进行转换,转换后则为使用值(Userd Value)
  1. 将使用值放入 constraining 中,将小数像素值转换为整数后得到最后的实际值

布局(Layout)

  • 布局用于确定内容大小和位置的算法
  • 相关技术

    • 常规流(行级、块级、表格布局、FlexBox、Grid布局)
    • 浮动
    • 绝对定位

相关属性

width

  • 指定 content box 宽度
  • 取值可以为长度、百分数、auto
  • 百分数相对于容器的 content box 宽度

height

  • 指定 content box 高度
  • 取值可以为长度、百分数、auto
  • 百分数相对于容器的 content box 宽度

    • 只有容器有指定的高度时,百分数才可以生效

padding

  • 指定元素四个方向的内边框
  • 三种写法

    • padding: 10px; - 上下左右内边框均为 10px
    • padding: 10px 20px; - 上下边框为 10px,左右边框为 20px
    • padding: 10px 20px 10px 20px; - 四个数值分别对应上右下左 (顺时针)

margin

  • 指定元素四个方向的外边框
  • 当上容器的下外边框为 100px ,下容器的上外边框为 100px 时,只会显示 100px 而不是 200px

border

  • 指定元素四个方向的边框
  • 拥有三个属性:border-width、border-style、border-color
  • 可以通过设置不同方向的边框画出三角形

    • #triangle {
        width: 0;
        height: 0;
        border-width: 30px;
        border-style: solid;
        border-color: transparent transparent black;
      }
      

块级(display: block)

  • 不和其他盒子并列摆放
  • 适用所有的盒模型属性
  • 常见标签:body、article、div、main、section 等

BFC(Block Fomatting Context)

  • 形成 BFC 的条件

    • 根元素(body)
    • 浮动(float)、绝对定位(position)
    • display 属性为 inline-block,table-cell,table-caption,flex
    • overflow 属性不为 visible
  • BFC 的排版规则

    • 盒子从上到下摆放
    • 垂直 margin 合并
    • BFC 内盒子的 margin 不会和外部的合并
    • BFC 不会和浮动元素重叠
    • BFC 可以看似成隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然

行级(display: inline)

  • 和其他行盒子一起放在一行或者拆开成多行
  • 盒模型中的 width 和 height 属性无效
  • 常见标签:span、em、strong、code 等

IFC(Inline Formatting Context)

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

    • 盒子在一行内水平摆放,一行放不下则换行
    • Text-align 属性决定一行内盒子的水平对齐
    • Vertical-align 属性决定一行内盒子的垂直对齐
    • 会自动避开浮动(float)元素

Flex Box(display: flex)

  • Flex 能够控制子盒子的摆放的流向(默认从左至右)、顺序、宽度和高度、水平和垂直方向对齐、是否允许拆行等
  • 经过 Flex Box 的中心点的水平线为主轴,垂直线为侧轴

flex-grow

  • 用于设置有剩余空间时的伸展能力
  • 例如 Flex Box 容器的宽度为 300px ,但实际内容使用仅占 200px,则会根据 flex-grow 所设置的值进行剩余空间的分发

    • <div class="index">
        <div class="a"></a>
        <div class="b"></a>
      </div>
      
      <style>
      .index {
        display: flex;
        width: 300px;
      }
      
      .a, .b {
        width: 100px;
      }
      
      .a {
        flex-grow: 2;
      }
      
      .b {
        flex-grow: 1;
      }
      </style>
      
    •   此时由于 a 的伸展能力为 2 ,b 伸展能力为 1 ,因此剩余的 100px 将以 2:1 的比例分别给 a 和 b

flex-shrink

  • 用于设置容器空间不足时的收缩能力
  • 实际的使用和上述的 flex-grow 相似,因此例子就略过了(

Grid 布局(display: grid)

  • 使用 grid-template 相关属性将容器划分为网络

网络轨道

我们可以通过设置 grid-template-columns 和 grid-template-rows 属性来定义网格中的行和列

例如

  • grid-template-columns: 100px 100px 100px (表示三列)
  • grid-template-rows: 100px 100px 100px 100px(表示四行)

网格线

N 行有 N+1 条水平网格线,M 列有 M+1 条垂直网格线

可以通过设置 grid-row-gap 和 grid-columns-gap 设置行间隙列间隙

Flex Box 和 Grid 布局区别

Flex Box 布局可以看成是一维排版

Grid 布局可以看成是二维排版

三、引用参考: