CSS 杂记

COMP3322 课程 CSS 相关内容拾遗。

见习魔女在浩如烟海的 MDN web docs 中终于找到了看起来合适的 CSS 咒语;满心欢喜的施展出去,却发现毫无效果。是吟唱的姿势不对,还是咒语本身出了问题?面前的施法材料 —— 纹丝不动的 HTML 文件 —— 只是一味地沉默。

前端魔法课导论的教授是一个神采奕奕的小个子老人。他的头发早已经全白了,却没有秃顶的迹象;这在魔法科学系中实在少见。见习魔女在长达三个半小时的课堂上常常发呆。我必须说,这不能完全怪她:前端魔法的知识太多太杂,难以形成体系,听起来很是枯燥。

后来我在香港大学站的九又四分之三站台遇到了她,她正在与众多巫师排队进入校园。由于港大站的人实在太多,居然从未有人发现这个秘密入口。我于是向她问起前端魔法学的怎么样,她自豪地向后一仰,掏出了这本自学笔记,并委托我在互联网上加以记录,以此造福更多在学业中挣扎的巫师们。


  This article is a self-administered course note.

  It will NOT cover any exam or assignment related content.


3 Ways of Placing Styling

  • inline style: 直接在 HTML 文件中对指定的元素设定 style attribute。
  • embedded style: 在 HTML 文件的 <head> 元素中添加 <style> 元素。
  • external style sheet: 在 HTML 文件中的 <head> 元素中添加 <link>,引用外部的 CSS 文件。其中,rel="stylesheet"type="text/css"


CSS Syntax

CSS 文件最基本的单元是 styling rules,其包括:

  • selector:选择 HTML 文件中的施法对象。
  • declaration block:紧跟在 selector 之后,包含一系列 property & value pairs,指定咒语的效用。

注意区分 pseudo-element selector 与 pseudo-class selector。

pseudo-element pseudo-class
syntax selector::pseudo-element selector:pseudo-class
feature 选择对应元素的某个部分 (specific part) 与对应元素的状态 (special state) 相关
example ::before 可在对应元素之前插入内容 :first-child 若对应元素是长子,选择它

此外还有一系列 combinator,指定 multiple selectors 之间的关系。

  • (null). Descendant - 后代元素。
  • >. Child - 直系子女元素。
  • +. Adjacent Sibling - comes directly after 的同辈元素 (一个元素)。
  • ~. General Sibling - 所有 come after 的同辈元素 (一系列元素)。


CSS Box Model

最基本的 CSS 概念之一。All HTML elements exist within an element box. 具体来说,该 element box 又包括四个 boxes,从里到外依次是:

  • Content: The innermost box contains the content of the element.
  • Padding: A clear, transparent area around the content.
  • Border: Borders provide a way to visually separate elements.
  • Margin: A clear, transparent area outside the border, differentiating different elements.

注意在使用 short-hand property 时传入单值,双值,三值与四值的含义:

  • padding: 0px. 同时应用于 ↑ ↓ ← → 四个方向。
  • padding: 5px 0px. 双值,先 ↑ ↓ 再 ← →。
  • padding: 1px 2px 3px. 三值,先 ↑ 再 ← → 再 ↓。
  • padding: 1px 2px 3px 4px. 四值,先 ↑ 再 → 再 ↓ 再 ←。

Content box

对于 block-level elements 与 non-text inline elements (比如图片),我们能在 CSS 中指定其 widthheight。但请注意,这里的 widthheight 指的是 content box 的宽度与长度。

  • total width: width + padding + border + margin.
  • total height: height + padding + border + margin.

但指定 box-sizing: border-box 后,元素总长/宽的计量方式有所不同:

  • total width: width + margin.
  • total height: height + margin.

注意到在设定 content box 的 width 与 height 后,content 中的文本可能会超出我们所指定的范围。设定 overflow property 来改善问题:

  • overflow: visible; (default) 超出范围的文本被显示出来。
  • overflow: hidden; 超出范围的文本被隐藏。
  • overflow: scroll; 添加一个 scroll bar,无论文本是否 overflow。
  • overflow: auto; (most practical) 只有当文本 overflow 后才添加 scroll bar。

Border Box

注意 border-width features 的解读。

  • border-radius: 15px 50px 30px 50px; 普通的四值表示,分别指定 ↖,↗,↘ 与 ↙。
  • border-radius: 15px 50px / 45px 150px/ 左侧指定椭圆角的 \(a\),右侧指定椭圆角的 \(b\)。在两值表示下,第一个值指定 ↖ 与 ↘;第二个值指定 ↗ 与 ↙。
  • border-radius: 4px 3px 6px / 2px 4px; 在三值表示法下,第一个值指定 ↖,第二个值指定 ↗ 与 ↙,第三个值指定 ↘。

Margin Box

margin 有一个特性:collapsing margins.

假设元素 top 位于元素 bot 上方,并且我们在 CSS 中指定:

1
2
3
4
5
6
7
8
9
#top {
padding: 0;
margin: 100px;
}

#bot {
padding: 0;
margin: 150px;
}

此时,元素 top 与元素 bot 之间的 margin 为 150px,而不是 250px。但注意,collapsing margin 只会发生在 vertical 方向;horizontal margins 将不会 collapse。


CSS Controllers

At-Rules

介绍几个常见的 @-rules:

  • @charset "UTF-8" 设定字符集为 UTF-8。HTML header 中的设定可 override 该条 CSS rule。
  • @import url("global.css")
  • @support(display: grid) { div { display: grid; } } 在支持 display: grid 规则的浏览器中应用接下来的规则。
  • @media responsive web design 必用的 at-rule: media queries [stay tuned]。

CSS Function

大多数都是 built-in function,可直接作为 property 对应的 value。例:rgb(255, 0, 0)

CSS Variables

也称 custom properties 或 cascading variables。

  • 定义:用 -- 开头,例 --fancy-color: pink;
  • 使用:用 var() 提取,例 color: var(--fancy-color);
  • 同样有 scope。在 :rootbody selector 中定义的变量是全局变量。


CSS Normal Flow

在 normal flow 中,元素按照 HTML 中出现的顺序被渲染。其中:

  • block-level element: stacked from top to bottom (within a document/block-level elements).
  • inline element: placed horizontally from left to right (within a block).

我们可以通过更改元素的 display property 来一定程度上 override normal flow 中的规则。

  • display: inline;
  • display: block;
  • display: inline-block; 将某个 block-level 元素按照 inline 的规则,即从左到右水平显示。
  • display: none; 元素消除术。注意与 visibility: hidden; 相区别。
  • display: flex; [stay tuned]
  • display: grid;


Float Property

单独拿出来说一下 float property:这个性质其实并不是很好理解。

  • float: left; floats the element to the left.
  • float: right; floats the element to the right.
  • float: none; [default]

当我们为一个元素 \(a\) 设定 float property 时,该元素立刻脱离 normal flow 并浮动在其之上。

  • \(a\) 脱离 normal flow 后其所占的空间被释放。因此在 normal flow 中的下一个元素将占据该空间。
  • \(a\) 的上一个元素位于 normal flow 中, \(a\) 不会向上漂;即,\(a\) 的相对垂直位置并不会改变。
  • \(a\) 的上一个元素也是浮动的,\(a\) 将会紧跟其后,向左 (float: left;) 或向右 (float: right;) 排列。

在 normal flow 之上的 floating flow 中,浮动的元素是横向排列的;此时我们又引入 clear property,其作用是清除浮动流的横向排列。

  • clear: left; move down to clear past left floats.
  • clear: right; move down to clear past right floats.
  • clear: both; move down to clear both floats.

若浮动元素 \(b\) 紧随浮动元素 \(a\) 之后,且 \(a,b\) 两元素均设置了 float: left;,此时在 floating flow 中 \(a\)\(b\) 应当位于同一行,且 \(a\) 靠左紧挨着 \(b\)。此时我们为 \(b\) 设置 clear: left;

这表示,\(b\) 元素的左侧不允许出现任何浮动元素。但浮动元素 \(a\)\(b\) 的左侧;因此 \(b\) 被迫下移一行。\(a,b\) 元素之间原本在 floating flow 中默认的横向排列关系被打断了。

可以参考这篇文章,写得很通俗易懂。


Position Property

normal flow 中的元素所在的默认位置称为 static position。此外,我们还可以为元素设置:

  • position: relative; 接下来 top, left 等 properties 指定的位置是相对于 static position 而言的。
  • position: absolute; 接下来指定的位置均是相对于其 containing element 而言的。
  • position: fixed; 接下来指定的位置均是相对于 browser window 而言的。
  • position: sticky; 先位于 static position,scroll 到某处后变为 fixed position。


Flexbox

在 containing element 中,我们设定 display: flex; 将其设置为弹性容器。该元素的所有直系子女将自动变为 flexible items (弹性元素)。

在弹性盒子中,水平方向由 main axis 指定,垂直方向由 cross axis 指定。

Flex-Direction Property

flex-direction 性质决定了弹性容器中的弹性元素布局的方式。

  • flex-direction: row; stacks the flex items horizontally from left to right.
  • flex-direction: row-reverse; stacks the flex items horizontally from right to left.
  • flex-direction: column; stacks the flex items vertically from top to bottom.
  • flex-direction: column-reverse; stacks the flex items vertically from bottom to top.

Flex-Wrap Property

默认情况下,所有弹性元素会挤在弹性盒子的一行中。一行中的元素越多,每个元素被压缩的越厉害。设定 flex-wrap property,在宽度超限时新开一行容纳弹性元素。

  • flex-wrap: nowrap; (default)
  • flex-wrap: wrap;
  • flex-wrap: wrap-reverse; (宽度超限时向上新开一行)

Alignment Property

  • justify-content: alignment along the main axis.
  • align-items: on the current line, how flex items are laid out along the cross axis.
  • align-content: aligns a flexbox's lines when there is extra space in the cross axis.

这里的 line 指的是我们所说的一行;弹性盒子默认情况下也是遵循横向排列关系的,我们有时可以将弹性盒子中的 视为一个基本的操纵单位。


Responsive Web Design

Responsive web design refers to the idea that websites should display equally well in everything from widescreen monitors to mobile phones.

RWD 四部曲:

  • Setting viewports via <meta> tag in HTML files.
  • Customizing CSS for different viewports using media queries.
  • Scaling images to the viewport size.
  • Flexible layouts.

Viewport

viewport 是个啥?

The viewport is the user's visible area of a web page.

网页本身能够向 mobile browser 提供有关 viewport size 的信息。具体是通过 <meta> 元素指定的:

1
<meta name="viewport" content="width=device-width, initial-scale=1">
  • viewport 的宽度是由 device width 决定的。
  • page will be rendered at the size determined by the width attribute.

Media Queries

一种 CSS at-rule。通过 media queries,我们能对不同的设备应用不同的 CSS styling。

1
2
3
@media only screen and (max-width:480px) {
... // CSS rules if device matches these conditions
}

上述的 media queries 询问当前的设备是否具有屏幕,且屏幕的宽度至少为 480px。若设备符合这些条件,随后的一系列 CSS rules 将得以应用。

此外,media queries 也是 progressive enhancement 中设置 breakpoint 的方式。

什么是 breakpoint?在课程的 assignment1 中,500px 就是一个 breakpoint。在 breakpoint 前后,应用在对应网页上的 CSS styling 将发生改变。

Flexible Layouts

为了应对 screen size 的变化,程序员采取了以下的方式来实现 flexible layout:

  • liquid (fluid) layout: 全程使用 relative units (如 %em),而非 fixed units (如 px)。
  • adaptive layout: 允许使用 fixed units,但使用 media queries 对不同 viewport range 的设备应用不同的 CSS styling。
  • responsive layout: 以上两种布局的结合,取长补短。


Reference

  This article is a self-administered course note.

  References in the article are from corresponding course materials if not specified.

Course info: Code, COMP3322. Lecturer, Dr. Tam Anthony Tat Chun.

External references:

-----------------------------------そして、次の曲が始まるのです。-----------------------------------