Categories
程式開發

CSS語法與規則— 重學CSS


我是三鑽,一個在《技術銀河》中等你們一起來終生漂泊學習。點贊是力量,關注是認可,評論是關愛!下期再見👋

前言

進入重學CSS 的第一步,首先需要找到一些線索。我們在前面的課程中講學習方法的部分也講過,要想建立知識體系骨架,我們需要一個完備性更權威,更全的線索。但是CSS 現在標準的狀態非常複雜,所以我們沒有辦法找到一份像JavaScript 或者HTML 中比較完備的現形標準,能把CSS 的一切都濃縮在內。

不過這種情況也是我們平時學習知識的一種常態,知識並不是有人給我們總結好一本書,或者能有一個地方包含了所有的知識。一般來說知識都會分佈在各種不同的文檔當中。

根據Winter 老師比較喜歡學習一個線索,凡是對於編程語言,都會先從它的語法去了解它。

所以CSS 也不例外,它也有自己的一套語法體系。但是CSS 標準是分散開的,我們想找到它完整的語法非常的不容易的。所以我們這裡先從CSS 2.1 語法標准開始。

CSS語法與規則— 重學CSS 1

CSS 2.1 語法標準

CSS 2.1 確實是一個比較老的版本了,但是它有一個好處,在2.1 的版本的時候建立了一個Snapshot,也就是說沒有其他版本去替代它。所以CSS 2.1 的Grammar Summary 部分是當時一個比較完整的一份語法列表。

當然現在我們已經大量的引入了CSS3 了,所以這裡面會有一些語法差異和不全。但是總體來講是一個不錯的起點,讓我們可以先開始認識CSS 的語法基礎。

這裡的語法是使用“產生式” 來表達的。但是這裡會有一些CSS 中特別的表達方式和標準:

[ ] —— 方括號代表組的概念? —— 問號代表可以存在和不存在| —— 單豎線代表“或” 的意思* —— 星號代表0 個或多個

CSS 總體結構

@[email protected] —— 多個規則,這裡面的規則沒有順序要求

+ @media

+ @頁面

+ rule —— 這里基本上就是我們平時寫的CSS 樣式規則部分

我們平時寫都是在寫普通的CSS 規則,charset 我們基本都不會用,一般我們都會用UTF-8。

這裡講到的是CSS 2.1 的CSS 結構,在CSS3 中我們有更多的@ 規則和CSS 規則,我們首先要在CSS3 中找到這兩塊的所有內容,然後補充道這個總體結構中,那麼我們就可以形成CSS 的總體結構。這時候我們對CSS 的語法認識就有完備性了。

CSS語法與規則— 重學CSS 1

CSS @ 規則研究

@字符集:https://www.w3.org/TR/css-syntax-3/

在CSS syntax 3 中在CSS 2.1 中做了一個重新的定義但是相對CSS 2.1 基本沒有什麼變化

@import:https://www.w3.org/TR/css-cascade-4/

然後import 就在css cascade 4 的規範裡面因為CSS 的全稱就是Cascade Style Sheet(級聯表)所以import 屬於級聯規則之一

@media:https://www.w3.org/TR/css3-conditional/

Media 不是在我們的media query 標準裡它在CSS3 的conditional 標準裡但是在media 的conditional 標準中又去引用了media query,規定了media 後面的一部分的查詢規則所以我們常常去講media query 是一個新特性,其實它並不是,它是類似一個預置好的函數的一個規範真正把Media 特性真正引入到CSS3 當中,是通過CSS3 中的conditional 標準那麼Conditional,就是“有條件的”,顧名思義就是用來控制一些規則在有效條件下才會生效

@page:https://www.w3.org/TR/css-page-3/

page 是有一份單獨的CSS3 標準來表述它就是css page 3 它主要是給我們需要打印的頁面所使用的理論上這個叫做分頁媒體,其實主要的分頁媒體就是打印機我們的頁面是不會有分頁的

@ counter-style:https://www.w3.org/TR/css-counter-styles-3/

我們平時寫列表的時候會有一個counter也就是列表最前面的那個“小黑點” 或者是“小數字”

@keyframes:https://www.w3.org/TR/css-animations-1/

keyframes 是用於我們的動畫效果定義的

@fontface:https://www.w3.org/TR/css-fonts-3/

fontface 就是我們使用web font 功能時候用到的它可以用來定義一切字體由此延伸出一個技巧叫Icon font

@supports:https://www.w3.org/TR/css3-conditional/

這個同樣是來自於conditional 的標準它是用來檢查某些CSS 的功能是否存在的supports 是一個比較尷尬的存在,自己就是隸屬於CSS3,所以它本身是有兼容性問題的導致沒辦法用所以現在基本上不推薦使用support 來檢查CSS 兼容性因為我們檢查的那個屬性,比我們support 這個規則兼容性要更好,所以根本檢查不了估計可能4~5年後,CSS 新出來的新特性我們再用support 來檢查會更好一點

@名稱空間:https://www.w3.org/TR/css-namespaces-3/

現在HTML 裡面除了HTML 命名空間,還引入了SVG、MathML 等這樣的其他的命名空間的標記和標籤所以CSS 裡面有了對應的設施,其實主要是一個完備性的考量,並不是一個特別重要的規則

這裡不是完整的列表,還有3 個規則,因為它們本身狀態太年輕在討論狀態,要不就是已經沒有瀏覽器支持了,或者是已經被廢棄了。分別有document、color-profile、font-feature。然後最常用的有三種:@media、@keyframes、@fontface

CSS語法與規則— 重學CSS 1

CSS 規則結構

這裡我們選中了HTML 所有的DIV 並且給予它們一個blue 的背景顏色。

div {
background-color: blue;
}

通過以上代碼示例,我們看到一段CSS 代碼是有分為選擇器和聲明兩部分的。在我們《實戰中理解瀏覽器原理》的文章中,我們編寫我們的CSS parsor 的時候,就是把CSS parse 成selector 部分和declaration 部分。我們這裡也會按照這個方法來理解CSS 規則。

選擇器—— selector (div)聲明—— declaration

+鍵-鍵(背景色)

+值-值(藍色)

CSS 規則標準

Selector 選擇器

3級-https://www.w3.org/TR/selectors-3/

+ Selectors_group —— 選擇器組:用逗號分隔

+ Selector —— 選擇器:需要用combinator (組合器) 把多個簡單選擇器拼在一起的

+ Combinator —— 組合器:+、>、~、空格

+ Simpleselectorsequence —— 簡單選擇器:類型選擇器、* 一定會在最前面,然後可以是ID、class、attr、pseudo等選擇器

4級-https://www.w3.org/TR/selectors-4/

+ Level 4 和Level 3 是非常的相似的,但是它的選擇器更複雜

+ 增加了很多的偽類選擇器、“或” 和“與” 的關係

+ 而且它的NOT 也更強大

+ Level 4 的話我們看一看拓展思路就可以了,因為從2018年12月開始也沒有再更新了

+ 所以目測是遇到問題了,處於比較難推動的階段,所以投入使用還有很漫長的路要走

Properties|性質Variables|CSS 變量—— https://www.w3.org/TR/css-variables/

+ 可以聲明一個雙減號開頭的變量:–main-color: #06c

+ 然後我們可以在子元素中使用這些CSS 變量了color: var(–main-color)

+ 可以跟其他的函數進行嵌套:–accent-background: linear-gradient(to top, var(–main-color), white);

+ 使用var() 函數的時候是可以給默認值的,傳入第二個參數就是默認值:var(–main-color, black)

+ CSS 變量處理可以用作value,還可以用作key:先聲明了–side: margin-top 然後就可以這樣使用var(–side): 20px

4級-https://www.w3.org/TR/css-values-4/

+ 它也是working draft (工作草稿) 狀態,但是實現狀態非常的好

+ 而且這個版本一直有保持更新,最後一次更新是2019年1月份

+ 數字類型有:整型、百分比、浮點型還有帶維度(Dimensions)

+ 長度單位有:相對單位(em, ex, cap, ch … )、視口單位(vw, vh, vi, vb, vmin, vmax)、絕對單位(cm, mm, Q, in, pt, pc px)

+ 其他單位:弧度單位(deg, grad, rad, turn)、時間單位(s, ms)、頻率單位(Hz, kHz)、分辨率單位(dpi, dpcm, dppx)

+ 數據類型:顏色、圖片 CSS語法與規則— 重學CSS 4、2D 位置等類型

+ 函數:計算cal()、最小值min()、最大值max() 、範圍剪切clamp()、切換value toogle()、屬性引用attr()

CSS語法與規則— 重學CSS 1

使用爬蟲收集整套CSS 標準

通過上面講到的幾個部分,我們已經了解了整個CSS 的架構。但是我們發現整個的CSS 標準是散落在幾份標準當中的,為了我們更好的閱讀標準,我們想拿到一份比較完整的標準列表是需要我們做一些工作的。很多時候我們都是需要在零散的標準裡面,去蒐集一些共性的內容。

接下來我們來做一個小實驗,通過類似爬蟲的方法,在W3C 網站上抓取標準的內容。然後我們對他進行一些處理,方便我們後續的一些工作。

首先我們打開W3C 的標準和草稿的列表頁:https://www.w3.org/TR/

這裡我們可以看到所有的W3C 的標準和草稿,但是這裡我們只需要CSS 部分的。如果我們檢查元素中查看,我們可以看到其實所有的數據都已經掛載在DOM 上了,只是前端做了篩選分頁而已。

所以我們就可以用一段代碼,直接複製到瀏覽器的console 中運行就可以篩選出所有CSS 相關的文章列表了。

// 获取 CSS 相关的标准列表
JSON.stringify(
Array.prototype.slice
.call(document.querySelector('#container').children)
.filter(e => e.getAttribute('data-tag').match(/css/)) // 找到有 CSS tag 的
.map(e => ({ name: e.children[1].innerText, url: e.children[1].children[0].href })) // 只获取标题名字和链接
);

最終輸入的內容如下:

CSS語法與規則— 重學CSS 6

然後我們點擊下方的”Copy” 即可複制,把這個JSON 內容保存在一個JavaScript 文件裡面,並且賦予一個變量叫standards。在我們後面的爬蟲代碼中需要用到。

這裡我們用一個簡單的方法來獲取爬取信息,就是在W3C 原本的頁面上開啟一個iframe,這樣我們就可以忽略掉跨域的問題。

let standards = [...] // 这里面的内容就是我们刚刚从 W3C 网页中爬取到的内容

let iframe = document.createElement('iframe');
document.body.innerHtml="";
document.body.appendChild(iframe);

function happen(element, event) {
return new Promise(function (resolve) {
let handler = () => {
resolve();
element.removeEventListener(event, handler);
};
element.addEventListener(event, handler);
});
}

void (async function () {
for (let standard of standards) {
iframe.src = standard.url; // 让 Iframe 跳转到每个 standards 中的详情页面
console.log(standard.name);
await happen(iframe, 'load'); // 等待 iframe 中的页面打开完毕
}
})();

然後我們需要的信息就是屬性表格中的內容:

CSS語法與規則— 重學CSS 7

如果我們看一下這個table 的HTML 代碼,我們會發現這個table 都是有一個class 名叫propdef 的。我們就可以用這個特性來獲取這個表格中的內容了。

所以我們就可以在await happen(iframe, ‘load’),後面添加一行代碼來答應這個表格的DOM 元素來看一下:

let iframe = document.createElement('iframe');
document.body.innerHTML = '';
document.body.appendChild(iframe);

function happen(element, event) {
return new Promise(function (resolve) {
let handler = () => {
resolve();
element.removeEventListener(event, handler);
};
element.addEventListener(event, handler);
});
}

void (async function () {
for (let standard of standards) {
iframe.src = standard.url;
console.log(standard.name);
await happen(iframe, 'load');
console.log(iframe.contentDocument.querySelectorAll('.propdef')); // 这里答应出表格的内容
}
})();

CSS語法與規則— 重學CSS 1

CSS語法與規則— 重學CSS 9