从规则到布局认识CSS

184 阅读13分钟

层叠样式表(Cascading Style Sheets,缩写为 CSS)是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG、MathML 或 XHTML 之类的 XML 分支语言)文档的呈现。

基本规则语法:

style-rule ::=
    selectors-list {
      properties-list
    }

/* 其中selectors-list */
selectors-list ::=
    selector[:pseudo-class] [::pseudo-element]
    [, selectors-list]

/* 其中properties-list */
properties-list ::=
    [property : value] [; properties-list]

css-declaration-small.png

整个结构称为规则集(规则集通常简称规则),注意各个部分的名称:

  • 选择器(Selector):HTML 元素的名称位于规则集开始。它选择了一个或多个需要添加样式的元素。要给不同元素添加样式,只需要更改选择器。
  • 声明(Declaration):一个单独的规则,如 color: red; 用来指定添加样式元素的属性。
  • 属性(Properties):改变 HTML 元素样式的途径(本例中 color 就是

    元素的属性)。CSS 中,由编写人员决定修改哪个属性以改变规则。

  • 属性的值(Property value):在属性的右边,冒号后面即属性的值,它从指定属性的众多外观中选择一个值(我们除了 red 之外还有很多属性值可以用于 color )。

注意其他重要的语法:

  • 除了选择器部分,每个规则集都应该包含在成对的大括号里({})。
  • 在每个声明里要用冒号(:)将属性与属性值分隔开。
  • 在每个规则集里要用分号(;)将各个声明分隔开。

选择器

CSS 选择器规定了 CSS 规则会被应用到哪些元素上。

  • 基本选择器
    • 通用选择器
      • 选择所有元素,可以将其限制为特定的名称空间或所有名称空间。
      • 语法:* ns|* *|*
    • 元素选择器
      • 按照给定的节点名称,选择所有匹配的元素。
      • 语法:elementname
    • 类选择器
      • 按照给定的 class 属性的值,选择所有匹配的元素。
      • 语法:.classname
    • ID 选择器
      • 按照 id 属性选择一个与之匹配的元素。需要注意的是,一个文档中,每个 ID 属性都应当是唯一的。
      • 语法:#idname
    • 属性选择器
      • 按照给定的属性,选择所有匹配的元素。
      • 语法:[attr] [attr=value] [attr~=value] [attr|=value] [attr^=value] [attr$=value] [attr*=value]
  • 分组选择器(Grouping selector)
    • 选择器列表
      • , 是将不同的选择器组合在一起的方法,它选择所有能被列表中的任意一个选择器选中的节点。
      • 语法:A, B
  • 组合器(Combinator)
    • 后代组合器
      • ”(空格)组合器选择前一个元素的后代节点。
      • 语法:A B
    • 直接子代组合器
      • > 组合器选择前一个元素的直接子代的节点。
      • 语法:A > B
    • 一般兄弟组合器
      • ~ 组合器选择兄弟元素,也就是说,后一个节点在前一个节点后面的任意位置,并且共享同一个父节点。
      • 语法:A ~ B
    • 紧邻兄弟组合器
      • + 组合器选择相邻元素,即后一个元素紧跟在前一个之后,并且共享同一个父节点。
      • 语法:A + B
    • 列组合器
      • || 组合器选择属于某个表格行的节点。
      • 语法:A || B
  • 伪选择器(Pseudo)
    • 伪类:: 伪选择器支持按照未被包含在文档树中的状态信息来选择元素。
    • 伪元素::: 伪选择器用于表示无法用 HTML 语义表达的实体。

优先级

优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。下面列表中,选择器类型的优先级是递增的:

  1. 元素选择器和伪元素(权重:0,0,0,1)
  2. 类选择器,属性选择器和伪类(权重:0,0,1,0)
  3. ID 选择器(权重:0,1,0,0)

通配选择符,关系选择符和否定伪类对优先级没有影响。

匹配任意伪类 :is()、:where() 和否定伪类 :not() 在特异性计算中不被视为伪类。但是,放置在伪类中的选择器在确定选择器类型数量时会像普通选择器一样计算。

:where() 和 :is() 的不同之处在于,:where() 的优先级总是为 0,但是 :is() 的优先级是由它的选择器列表中优先级最高的选择器决定的。

浏览器自上而下解析代码,对样式进行覆盖,给元素添加的内联样式 总会覆盖外部样式表的任何样式,因此可看作是具有最高的优先级(权重:1,0,0,0)。

当在一个样式声明中使用一个 !important 规则时,此声明将覆盖任何其他声明(权重:∞)。当两条相互冲突的带有 !important 规则的声明被应用到相同的元素上时,拥有更大优先级的声明将会被采用。

内联样式和 !important 都被认为是非常不好的做法,但是有时你可以在 CSS 文件里用 !important 去覆盖内联样式。

At 规则

css_syntax_-_statements_venn_diag.png

At 规则是一个 CSS 语句,用来指示 CSS 如何运行。以 at 符号开头,'@'(U+0040 COMMERCIAL AT),后跟一个标识符,并包括直到下一个分号的所有内容,';'(U+003B SEMICOLON),或下一个 CSS 块,以先到者为准。

/* 一般结构 */
@identifier (RULE) {};

就像属性值那样,每条 at 规则都有不同的语法。不过一些 @规则可以归为一个特殊的分类:条件规则组。这些语句使用相同的语法。它们都可以包括 嵌套语句——规则集或者是嵌套 at 规则。它们都表达:它们所指的条件 (类型不同) 总等效于 true 或者 false,如果为 true 那么它们之中的语句生效。

由它们的标示符指定,每种规则都有不同的语法:@charset@import@namespace

嵌套 at 规则,是嵌套语句的子集,不仅可以作为样式表里的一个语句,也可以用在条件规则组里:@media@supports@document@page@font-face@keyframes@counter-style@font-feature-values@property@layer

条件规则组由 CSS Conditionals Level 3 定义:@media@supports@document

既然条件规则组可以嵌套语句,那么嵌套层级不定。

动画

CSS animations 使得可以将从一个 CSS 样式配置转换到另一个 CSS 样式配置。动画包括两个部分:描述动画的样式规则和用于指定动画开始、结束以及中间点样式的关键帧。

相较于传统的脚本实现动画技术,使用 CSS 动画有三个主要优点:

  1. 能够非常容易地创建简单动画,你甚至不需要了解 JavaScript 就能创建动画。
  2. 动画运行效果良好,甚至在低性能的系统上。渲染引擎会使用跳帧或者其他技术以保证动画表现尽可能的流畅。
  3. 让浏览器控制动画序列,允许浏览器优化性能和效果,如降低位于隐藏选项卡中的动画更新频率。
p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}

CSS 过渡提供了一种在更改 CSS 属性时控制动画速度的方法。其可以让属性变化成为一个持续一段时间的,而不是立即生效的过程。

div {
  transition: <property> <duration> <timing-function> <delay>;
}

条件规则

CSS 特性查询是 CSS Conditional Rules module 标准的一部分,这一标准也包含了媒体查询 @media 规则;在你使用特性查询的时候,你会发现它们的行为方式与媒体查询类似。不同点在于媒体查询是测试网页运行的环境相关内容,但特性查询测试的是浏览器对 CSS 特性的支持。

特性查询由 @supports 规则组成,紧跟着是属性名以及你想测试的属性值。你不能测试一个单单的属性名比如 display;规则需要你提供一个属性名以及一个值:

@supports (property: value) {
  /* 将要应用的 CSS 规则 */
}

媒体查询

媒体查询(Media queries)非常实用,尤其是当你想要根据设备的大致类型(如打印设备与带屏幕的设备)或者特定的特征和设备参数(例如屏幕分辨率和浏览器视窗宽度)来修改网站或应用程序时。

媒体查询常被用于以下目的:

  • 有条件的通过 @media 和 @import at-rules 用CSS 装饰样式。
  • 用 media= 属性为<style>, <link>, <source>和其他HTML元素指定特定的媒体类型。
  • 使用Window.matchMedia() 和MediaQueryList.addListener() 方法来测试和监控媒体状态。
  1. 定位媒体类型

媒体类型(Media type)描述设备的一般类别。除非使用 not 或 only 逻辑操作符,媒体类型是可选的,并且会(隐式地)应用 all 类型。

  • all 适用于所有设备。
  • print 适用于在打印预览模式下在屏幕上查看的分页材料和文档。
  • screen 主要用于屏幕。
/* 
媒体类型描述了给定设备的一般类别。
尽管通常在设计网站时会考虑屏幕,但您可能希望创建针对特殊设备的样式 
*/
@media print { }

/* 还可以定位多个设备 */
@media screen, print { }
  1. 定位媒体特性

媒体特性(Media feature)描述了用户代理、输出设备或环境的具体特征。媒体特性表达式是完全可选的,其用于测试这些特征是否存在存在和它们的值。每个媒体特性表达式都必须用括号括起来。

  • any-hover 是否有任何可用的输入机制允许用户(将鼠标等)悬停在元素上。
  • any-pointer 可用的输入机制中是否有任何指针设备,如果有,它的精度如何?
  • aspect-ratio 视口(viewport)的宽高比。
  • color 输出设备每个像素的比特值,如果设备不支持输出彩色,则该值为 0。
  • color-gamut 用户代理和输出设备大致程度上支持的色域。
  • color-index 输出设备的颜色查询表(color lookup table)中的条目数量,如果设备不使用颜色查询表,则该值为 0。
  • device-aspect-ratio 输出设备的宽高比。
  • device-height 输出设备渲染表面(如屏幕)的高度。
  • device-width 输出设备渲染表面(如屏幕)的宽度。
  • display-mode 应用程序的显示模式,如 web app 的 manifest 中的 display 成员所指定。
  • dynamic-range 用户代理和输出设备支持的亮度、对比度和颜色深度的组合。
  • forced-colors 检测用户代理是否限制调色板。
  • grid 输出设备使用网格屏幕还是点阵屏幕?
  • height 视口的高度。
  • hover 主输入机制是否允许用户在元素上悬停。
  • inverted-colors 用户代理或者底层操作系统是否反转了颜色。
  • monochrome 输出设备单色帧缓冲区中每个像素的位深度。如果设备并非黑白屏幕,则该值为 0。
  • orientation 视口的旋转方向。
  • overflow-block 输出设备如何处理沿块轴溢出视口的内容。
  • overflow-inline 沿内联轴溢出视口的内容是否可以滚动。
  • pointer 主输入机制是一个指针设备吗?如果是,它的精度如何?
  • prefers-color-scheme 检测用户倾向于选择亮色还是暗色的配色方案。
  • prefers-contrast 检测用户是否有向系统要求提高或降低相近颜色之间的对比度。
  • prefers-reduced-motion 用户是否希望页面上出现更少的动态效果。
  • resolution 输出设备的像素密度(分辨率)。
  • scripting 检测脚本(例如 JavaScript)是否可用。
  • update 输出设备修改渲染内容的频率。
  • video-dynamic-range 用户代理的视频平面(video plane)和输出设备支持的亮度、对比度及颜色深度的组合。
  • width 视口的宽度,包括纵向滚动条的宽度。
/* 媒体功能描述了给定的user agent的输出设备或环境的特定特征 */
@media (hover: hover) { }

/* 
许多媒体功能都是范围功能,
这意味着可以在它们前面加上“最小”或“最大”来表示“最小条件”或“最大条件”约束 
*/
@media (max-width: 12450px) { }

/* 
在未指定值的情况下创建媒体功能查询,则该样式将全部被应用,
只要该查询的值不为零即可 
*/
@media (color) { }

/* 如果某个功能不适用于运行浏览器的设备,则涉及该媒体功能的表达式始终为 false */
@media speech and (aspect-ratio: 11/5) { }
  1. 创建复杂查询

逻辑操作符(logical operator)notandonly,or 可用于联合构造复杂的媒体查询,你还可以通过用逗号分隔多个媒体查询,将它们组合为一个规则。

  • 结合多种类型和特性
/* and关键字将媒体功能与媒体类型或其他媒体功能组合在一起 */
@media (min-width: 30em) and (orientation: landscape) { }

/* 要将样式限制为带有屏幕的设备,可以将媒体功能链接到screen媒体类型 */
@media screen and (min-width: 30em) and (orientation: landscape) { }
  • 测试多重查询
/* 
当用户的设备与各种媒体类型,功能或状态中的任何一种匹配时,
可以使用逗号分隔的列表来应用样式。
*/
@media (min-height: 680px), screen and (orientation: portrait) { }
  • 反转查询的含义

not关键字会反转整个媒体查询的含义。它只会否定要应用的特定媒体查询。not关键字不能用于否定单个功能查询,只能用于否定整个媒体查询。

@media not all and (monochrome) { }
/* 等价于 */
@media not (all and (monochrome)) { }

@media not screen and (color), print and (color) { }
/* 等价于 */
@media (not (screen and (color))), print and (color) { }
  • 提升老版本浏览器兼容性

only关键字可防止不支持带有媒体功能的媒体查询的旧版浏览器应用给定的样式。它对现代浏览器没有影响。

@media only screen and (color) { }

布局

CSS 布局模式,有时简称为布局,是一种基于盒子与其兄弟和祖辈盒子的交互方式来确定盒子的位置和大小的算法。有以下几种形式:

  • 块布局:用来布置文件。块布局包含以文档为中心的功能,例如 浮动元素或将其放置在多列上的功能。
  • 行内布局:用来布置文本。
  • 表格布局:用来布置表格。
  • 定位布局:用来对那些与其他元素无交互的定位元素进行布置。
  • 弹性盒子布局:用来布置那些可以顺利调整大小的复杂页面。
  • 网格布局:用来布置那些与一个固定网格相关的元素。
  • 多栏式布局:用于将内容布置到一组列框中,就像报纸中的列一样。
  • 流动布局:可以根据浏览器窗口的大小自动调整页面的布局。
  • 固定布局:网页宽度是固定的,不会随浏览器窗口的大小而改变。
  • 响应式布局:根据不同的设备自动适应大小和分辨率,保证网页能在各种设备上正常显示。