理解CSS(上)

125 阅读11分钟

一、概述

为什么学习CSS:使网页有更丰富的交互行为和视觉效果,能承载传递更多的信息量。

发展史

  • HTML提出
  • CSS1 解决排版布局和装饰问题,第一个 ”层叠“ 语言
  • CSS2
  • CSS2.1
  • CSS3

CSS - Cascading Style Sheets 层叠样式表 样式表 是 规则声明的集合,集合的声明会产生冲突,层叠用来解决冲突。

二、层叠

优先级 三大规则(优先度递减)

1.样式表来源

  • 作者样式表 (开发者写的)
  • 用户样式表 (少有)
  • 用户代理样式表 (浏览器默认样式)

加上 !important 优先级会反过来,例如浏览器默认样式有!important,则作者样式表将无法覆盖。

*这里先忽略了transition和animation,原因是不同浏览器和css规范规定的表现不一致

2.选择器

选择器的作用:找标签

 选择器 {
     属性名:属性值;
 }
  1. 元素选择器:根据HTML元素类型选择元素。例如,p选择所有的<p>元素。

  2. 类选择器:根据元素的类属性选择元素。例如,.my-class选择具有类my-class的所有元素。

  3. ID选择器:根据元素的ID属性选择特定元素。例如,#my-element选择ID为my-element的元素。

  4. 属性选择器:根据元素的属性和属性值选择元素。例如,[data-attribute]选择具有data-attribute属性的所有元素,[data-attribute="value"]选择具有data-attribute属性且其值为value的所有元素。

  5. 伪类选择器:根据元素的状态或文档结构选择元素。例如,:hover选择鼠标悬停在其上的元素,:first-child选择作为其父元素的第一个子元素的元素。

  6. 伪元素选择器:选择元素的某个部分,例如内容的前后。例如,::before选择元素内容之前的一个虚拟元素,::after选择元素内容之后的一个虚拟元素。

  7. 组合选择器:通过组合多个选择器来选择符合所有条件的元素。

    • 后代选择器(空格):例如,div p选择所有作为<div>元素后代的<p>元素。
    • 子元素选择器(>):例如,div > p选择所有作为<div>元素直接子元素的<p>元素。
    • 相邻兄弟选择器(+):例如,div + p选择紧跟在<div>元素后面的<p>元素。
    • 一般兄弟选择器(~):例如,div ~ p选择在<div>元素后面的所有<p>兄弟元素。
  8. 多个选择器:使用逗号分隔的多个选择器可以同时选择符合任一选择器条件的元素。例如,div, p选择所有的<div><p>元素。

优先级

image.png

3.源码位置

样式最后声明的生效,而不是引用的顺序。

4.代码建议

选择器尽量少用 id 尽量不要用 !important 自己的样式 加载在 引用库样式 的后面

继承

大部分具有继承特性的属性跟文本相关: color、font、 font-family、 font-size、font-weight、 font-variant、 font-style、 line-height、 letter-spacing、text-align、 text-indent、text-transform, white-space以及word-spacing 还有少部分列表、表格的属性

可以使用inherit关键字显式指定一个属性值从其父元素继承

CSS的值和单位

文字类:比如像initial这种关键字,颜色、位置等等 数值类:比如z-index:1这种数值,或者带有单位的数值、百分比等 函数生成:比如calc(), min(), max()等

单位 绝对长度:px,pt,cm,in... 相对长度: em, rem, ex, rex... vw, vh, vmin, vmax... 角度:deg, grad, turn, rad 时间:s, ms 分辨率: dpi, dpcm, dppx

盒模型

margin (可负值) border padding content

浏览器根据视觉格式化模型(visual formatting model), 将所有元素表示为盒子模型, css通过盒模型做layout

控制盒子类型 display: block、inline、inline-block、flex、.

控制盒子大小 & 计算方式 width, height. box-sizing: content-box, border-box

控制盒中内容流 overflow: auto、 scroll、hidden、

控制定位 position: static、 relative、absolute、fixed、 sticky

是否可见 visibility: visible、hidden、...

margin 负外边距

margin负值最终减少的是外界可感知的宽高。(少用

设置左边或顶部的负外边距,元素就会相应地向左或向上移动,导致元素与它前面的元素重叠。 如果设置右边或者底部的负外边距,并不会移动元素,而是将它后面的元素拉过来;

常见形式

三角形

 // html
 <div class="triangle-bottom"></div>
 //css
 .triangle-bottom {
     width: 0;
     height: 0;
     border-left: 50px solid transparent;
     border-right: 50px solid transparent;
     border-bottom: 50px solid red;
 }

固定比例矩形 (或者使用新特性: aspect-ratio)

 //html
 <div class="ratio-box"></div>
 //css
 ratio-box {
     background-color: cadetblue;  //军校蓝
     width: 100%;    //是父元素宽度100%
     height: 0;
     padding: 0;
     padding-bottom: 75%;  //是父元素宽度75%
 }

水平居中

 //html
 <div class="wrap">
     <div class="h-center"></div>
 </div>
 //CS5
 .wrap {
     width: 100%;
     height: 80px;
     border: 1px dashed grey;
 }
 .h-center {
     width: 100px;
     height: 50px;
     background-color: navajowhite;
     // 左右两侧的margin 使用auto
     // 将水平方向剩余空间均分auto
     margin: 10px auto; 
 }

渐变边框

 // html
 <div class="awesome-borer"></div>
 // css
 awesome-border {
     width: 150px;
     height: 100px;
     border: 8px solid transparent;
     border-radius: 12px;
     background-clip: padding-box, border-box;
     background-origin: padding-box, border-box;
     background-image:
         linear-gradient(to right, #fff, #fff),
         linear-gradient(135deg, #e941ab, #a557ef);
 }

三、布局

CSS3 之前的常用布局 Normal Flow 常规流 默认的布局方式 有 块级格式化上下文 和 内联格式化上下文

Float 浮动流 用float属性控制脱流,做横向布局

Positioning 定位流 用position属性控制 fixed 和 absolute 脱离文档流可以自由定位、覆盖等

CSS3 之后的新增布局

Flex弹性盒子布局 Grid 网格布局 Multicol多列布局 一维空间布局 二维空间布局 文本、内容的多列展示

3.1 常规流布局

格式化上下文 FC (Formatting Context)

其实指的是一个渲染区域,拥有一套渲染规则; 它决定了其子元素如何定位,以及与其他元素之间的关系和相互作用。它是CSS2.1规范中的一个概念。

常见的有以下两种:

  • IFC 内联级格式化上下文: 从左到右水平排列
  • BFC 块级格式化上下文: 块级元素默认沾满一行

外部显示类型(display-outside)

规定了该盒子如何与同一格式上下文中的其他元素一起显示。

内部显示类型(display-inside)

规定了该盒子内部的布局方式。比如display: flex;其外部显示是block,参与 BFC; display: inline-flex,则外部显示是inline,参与IFC。他们内部的盒子都参与弹性盒子布局。

常规流中的盒子

外部显示类型为 block

  • 块级盒子:display: block I flex I grid I table I flow-root I...

参与 块级格式化上下文 (block formatting context)

  • 内联级盒子:display: inline I inline-block I inline-flex I inline-grid I inline-able I...

参与 内联级格式化上下文(inline formatting context)

3.2 BFC--块级格式化上下文

BFC布局规范

在一个块格式区域中,盒子会从包含块的顶部开始,按序垂直排列。同级盒子间的垂直距离会由“margin”属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠在一个块格式区域中,每个盒子的左外边缘会与包含块左边缘重合(如果是从右到左的排版顺序则盒子的右外边缘与包含块右边缘重合)。

平时说的BFC

BFC本身是 block formatting context 的缩写,是一种格式规范。如果说一个盒子是BFC或者有BFC特性,那么BFC表示的是block formatting context root,不管它外部显示类型是什么,但是它的内部显示类型是flow-root,其实就是这个盒子内部形成了一个新的块级格式化上下文。

触发BFC特性

display: flow-root I inline-block;
position: absolute | fixed;
float: 不为none;
overflow: 不为 visible

外边距塌陷

margin塌陷的意思:同时给两个div设置相同的属性,当设置margin为100px,那么两个div之间的间隙应该是margin-bottom+margin-top=200px的外边距,但是没有设置BFC属性,块的上外边距和下外边距会合并为单个边距,取最大值,如果margin相等,则仅为一个,这就是外边距重叠(margin塌陷)。

会塌陷的情况:

  • 两个兄弟元素之间相邻的上下外边距
  • 父子元素之间相邻的上下外边距
  • 内容空二事白コ下カ听组金

image.png

消除外边距塌陷的方法:

  • 在两个相邻的上下边距之间增加border、padding或者内联元素,使之不相邻;
  • 在父子元素重叠时,除了上述方法,还可以设置父元素为BFC,使得父子不在同级BFC中

image.png

3.3 IFC内联级格式化上下文

在内联格式区域中,盒子会从包含块的顶部开始,按序水平排列。只有水平外边距、边框和内边距会被保留。这些盒子可以以不同的方式在垂直方向上对齐:可以底部对齐或顶部对其,或者按文字底部进行对齐。我们把包含一串盒子的矩形区域称为一个线条框。(The rectangular area that括contains the boxes that form a line is called a line box.)

image.png

布局规则

  • 在一个IFC里,盒是一个接一个从顶部水平放置。
  • 摆放这些框,它们水平方向的margin,padding,border所占空间会被计算在内。
  • 行盒的高度由行盒内最高的inline boxes决定。
  • 垂直方向,可通过vertical-align设置文本基线,取值可以是具体像素值,也可以是middle等方向词。
  • 当内部的容器盒子太多了一个line box装不下来,他们折行之后会变成两个或者多个line box, line box们垂直方向无间隔地堆叠,但不能重叠
  • 浮动后IFC内部的浮动元素宽高参与IFC的line-box宽高计算并且从换行后的行开始排列

一些实用case

  • 单行文字垂直居中,比如标题,利用了line-height的垂直居中特性 image.png
// html
<div class="title">我是标题</div>
// css
.title {
    background: antiquewhite;
    font-size: 18px;
    line-height: 36px;
    height: 36px; // 可以省略
}
  • 文字和icon垂直对齐

利用了line box中计算高度的原理和vertical-align的设置,垂直对齐,但不是完全垂直居中。如果设置父元素font-size:0,基线和中线重叠,则居中对齐

image.png

// html
<div class="wrap">
    <img class""image" src="dy.png">
    <span class""text">抖音同款能力</span>
</dtv>
// css
.image{
    width: 24px;
    height: 24px;
    vertical-align: middle;
}
.text (
    font-size: 16px;
    line-height: 32p×;
    margin-left: 4px;
    vertical-align: middle;
}

3.4 弹性盒子布局

Flexible Box Lavout 是为了提供更加高效灵活的布局方式,在即便是宽高未知的情况下,也能排列和分割一个盒子内部的布局。而且在不同布局方向(横向/纵向)的调整更为灵活。

image.png

相关属性分类

作用于父元素(flex container):

建立一个弹性盒子
display: flex | inline-flex;

规定盒子的主轴方向
flex-direction: row | column |...;

子元素折行显示形式
flex-wrap: nowrap | wrap | wrap-reverse;

主轴方向子元素的排列方式
justify-content: center | space-between |;

交叉轴方向子元素的对齐方式
align-iterms: flex-start | center | stretch |...;

交叉轴方向多行子元素的布局方式
align-content:flex-start | space-between |...

以明确值设定子元素间的间隔
gap:<row-gap><column-gap>;

作用于子元素(flex items):

规定item未放缩之前的默认大小
flex-basis: auto | 长度值…..;

规定有剩余空间时,对item的分配比例
flex-grow: number,

规定空间不够时,对item的压缩的比例
flex-shrink: number;

以上三项的缩写
flex: grow shrink basis; 默认 0 1 auto

规定item从左到右(row布局)显示的顺序
order: number; 默认是0

规定单个item在交叉轴上的位置
align-self: auto | center | flex-start |...

使用示例

image.png

// html
<div class="fitename"
    <span class-"fstenane base"
        this-file-has-a-really-really-really-long-filename.
    </span>
    <span class="filename__extension">
        pdf
    </span>
// css
.filenane{
    display: flex;
}
.filenane___base{
    text-overflow: ellipsis;
    whit-space: nowrap;
    overflowt: hidden;
}
.filenane extension{
    flex-shrink: 0;
}

image.png

//html
<div class""dot-one">
    <div class""dot"></div>
</div>
.dot-one (
    display: flex;
    justify-content: center;
    align-itens: center;
}
// html
<div class="dot-five face">
    <div class="row">
        <div class="dot"></div>
        <div class="dot"></div>
    </div>
    <div class "row row-center">
        <div class="dot"></div>
    </div>
    <div class="row">
        <div class="dot"></div>
        <div class="dot"></div>
    </div>
</dtv>

//css
.dot-five (
    display: flex;
    flex-direction: column;
    justify-content: space-between
}
.row {
    display: flex;
    justify-content: space-between;
}
.row-center{
     justify-content: center:
}

3.5 网格布局

2017年推出的Grid布局可以定义由行和列组成的二维布局,然后将元素放置到网格中。元素可以只占其中一个单元格,也可以占据多行或多列。

image.png

.grid-container{
    display: grid;
    grid-template-columns: 100px 1fr;
    grid-template-rows: 60px 6fr 1fr;
}

image.png

使用示例

image.png

Grid和Flex布局的使用策略

Flex

  • 1.一维布局
  • 2.基于内容
  • 3.浏览器兼容性更好

Grid

  • 1.二维布局
  • 2.基于布局
  • 3.2017年后浏览器的版本普遍支持

Grid for layout, Flexbox for components

  • 1,大面积或整体布局推荐使用Grid布局
  • 2,小面积或组件中,或Grid Iterh中可以使用Flex做灵活布局