2024-07-09 01:20:14
2021-11-28 14:27:36
My Princess 別低頭 皇冠會掉
When she was younger she would pretend
在她小的時候 她會假裝
That her bedroom was a castle she was fairest in the land
她的卧室是一座城堡 她是這個國度裏最美麗的女孩
And she got older and it all changed
她漸漸長大 一切都物是人非
There was no time for make believe and all the magic slipped away
沒有時間徜徉在幻想裏 所有魔力悄然流逝
Until the light in her eyes it was all but gone
直到她眼中的光芒消失殆盡
‘Cause all the dreams that she had turned out to be wrong
因為她擁有的所有夢想不過都是幼稚可笑的錯誤
So keep your head up princess ‘fore your crown falls
昂首闊步 別讓頭頂的王冠掉落
Know these voices in your head will be your downfall
縈繞腦海裏那些質疑聲音 只會讓你的心不堪一擊
I know it gets so hard but you don’t got far to go
我知道這萬分艱難 而前路並非遙不可及
Yeah keep your head up princess it’s a long road
昂首闊步 這是條漫長的道路
And the path leads right to where they won’t go
是他們都不會選擇去走的一條路
I know it hurts right now but I know you’ll make it home
路程艱辛 但我相信你定會到達終點 載譽歸來
So keep your head up
堅定腳步
Yeah keep your head up
不忘初心
And now she’s grown up works at a bar
現在她長大成人 在酒吧找到一份工作
She traded makeshift gowns for serving rounds from sunrise ‘til it’s dark
她穿着簡單質樸的衣服 披星戴月地賣力工作
And all her friends got someone to hold
她所有的朋友都已找到歸宿
And she’s got no one else still not prepared to make it on her own
可她孑然一身 依然沒有準備好自力更生
And now the light in her eyes it’s now all but gone
現在她眼中的光芒消失殆盡
‘Cause all the dreams that she had turned out to be wrong
因為她擁有的所有夢想不過都是幼稚可笑的錯誤
So keep your head up princess ‘fore your crown falls
昂首闊步 別讓頭頂的王冠掉落
Know these voices in your head will be your downfall
縈繞腦海裏那些質疑聲音 只會讓你的心不堪一擊
I know it gets so hard but you don’t got far to go
我知道這萬分艱難 而前路並非遙不可及
Yeah keep your head up princess it’s a long road
昂首闊步 這是條漫長的道路
And the path leads right to where they won’t go
是他們都不會選擇去走的一條路
I know it hurts right now but I know you’ll make it home
路程艱辛 但我相信你定會到達終點 載譽歸來
So keep your head up
堅定腳步
Yeah keep your head up
不忘初心
One day you’ll find your way back to the start
總有一天 你會找到方向 回到原點
One day you’ll live in your dreams
總有一天 你會沉浸在你的美夢裏
One day you’ll wake up and girl you’ll be a queen
總有一天 你會醒來 你將成為無與倫比的女王
So keep your head up princess ‘fore your crown falls
昂首闊步 別讓頭頂的王冠掉落
Know these voices in your head will be your downfall
縈繞腦海裏那些質疑聲音 只會讓你的心不堪一擊
I know it gets so hard but you don’t got far to go
我知道這萬分艱難 而前路並非遙不可及
Yeah keep your head up princess it’s a long road
昂首闊步 這是條漫長的道路
And the path leads right to where they won’t go
是他們都不會選擇去走的一條路
I know it hurts right now but I know you’ll make it home
路程艱辛 但我相信你定會到達終點 載譽歸來
So keep your head up
堅定腳步
Yeah keep your head up
不忘初心
2021-11-10 19:25:24
年初才把域名換到了 immyw.com
, 還沒到一年,又把域名換到了 crazywong.com
。
之前爲了安全起見,給 Godaddy 開了兩步認證,選擇了 Microsoft Authenticator 儲存驗證。然後倒霉的事情來了,一次不小心的操作,把 Microsoft Authenticator 給刪了,本想著有備份,重新下載軟件再恢復就行。結果可想而知,備份丟了。無奈之下,只能一個個去申訴回來。
Godaddy 的要求比較嚴格,需要提供由政府發行之含照身份證明卡片的彩色影本。能提供的不多,無非就是身份證和護照。不明白現在的網絡,動不動就需要實名認證,上傳身份證。甚至有些還要人臉識別才能使用。本著能不提交就不提交的態度,就算是大公司,也有可能泄露個人資料的時候。
似乎沒有別的方法恢復我的賬號了,只能按要求傳了護照過去。等待了 3.4 天之後,收到了 godaddy 的回信。要求上傳一張手持護照的照片。
手持照片這事就超過我的承受範圍。早知道會這樣,一開始就不會傳護照照片過去了。最終還是考慮放棄這個域名,還好當初有把 renew 給取消了。
心儀的域名都被注冊了,最後選擇了 crazywong.com
.
Wong 是黃(姓)
爲了方便域名記憶,我把博客名字也改成 CrazyWong.
以後設置兩步認證時,真要把二維碼也保存一份,不然就真的 Game Over 了。
2021-03-21 21:18:44
本文轉自微信公衆號 - 大海我來了
原文地址 1.5 萬字 CSS 基礎拾遺(核心知識、常見需求)
本篇文章圍繞了 CSS 的核心知識點和項目中常見的需求來展開。雖然行文偏長,但偏基礎,適合初級中級前端閲讀,閲讀的時候請適當跳過已經掌握的部分。
這篇文章斷斷續續寫了比較久,也參考了許多優秀的文章,但或許文章裏還是存在不好或不對的地方,請多多指教,可以評論裏直接提出來哈。
小 tip:後續內容更精彩哦。
CSS 的核心功能是將 CSS 屬性設定為特定的值。一個屬性與值的鍵值對被稱為聲明(declaration)。
1 |
color: red; |
而如果將一個或者多個聲明用 {}
包裹起來後,那就組成了一個聲明塊(declaration block)。
1 |
{ |
聲明塊如果需要作用到對應的 HTML 元素,那還需要加上選擇器。選擇器和聲明塊組成了 CSS 規則集(CSS ruleset),常簡稱為 CSS 規則。
1 |
span { |
規則集中最後一條聲明可以省略分號,但是並不建議這麼做,因為容易出錯。
CSS 中的註釋:
1 |
/* 單行註釋 */ |
在 CSS 文件中,除了註釋、CSS 規則集以及 @規則 外,定義的一些別的東西都將被瀏覽器忽略。
CSS 規則是樣式表的主體,通常樣式表會包括大量的規則列表。但有時候也需要在樣式表中包括其他的一些信息,比如字符集,導入其它的外部樣式表,字體等,這些需要專門的語句表示。
而 @規則 就是這樣的語句。CSS 裏包含了以下 @規則:
@namespace 告訴 CSS 引擎必須考慮 XML 命名空間。
@media, 如果滿足媒體查詢的條件則條件規則組裏的規則生效。
@page, 描述打印文檔時佈局的變化.
@font-face, 描述將下載的外部的字體。
@keyframes, 描述 CSS 動畫的關鍵幀。
@document, 如果文檔樣式表滿足給定條件則條件規則組裏的規則生效。 (推延至 CSS Level 4 規範)
除了以上這幾個之外,下面還將對幾個比較生澀的 @規則 進行介紹。
@charset 用於定義樣式表使用的字符集。它必須是樣式表中的第一個元素。如果有多個 @charset
被聲明,只有第一個會被使用,而且不能在 HTML 元素或 HTML 頁面的 <style>
元素內使用。
注意:值必須是雙引號包裹,且和
1 |
@charset "UTF-8"; |
平時寫樣式文件都沒寫 @charset 規則,那這個 CSS 文件到底是用的什麼字符編碼的呢?
某個樣式表文件到底用的是什麼字符編碼,瀏覽器有一套識別順序(優先級由高到低):
文件開頭的 Byte order mark 字符值,不過一般編輯器並不能看到文件頭裏的 BOM 值;
HTTP 響應頭裏的 content-type
字段包含的 charset
所指定的值,比如:
1 |
Content-Type: text/css; charset=utf-8 |
CSS 文件頭裏定義的 @charset 規則裏指定的字符編碼;
<link>
標籤裏的 charset 屬性,該條已在 HTML5 中廢除;
默認是 UTF-8
。
@import 用於告訴 CSS 引擎引入一個外部樣式表。
link 和 @import 都能導入一個樣式文件,它們有什麼區別嘛?
link 是 HTML 標籤,除了能導入 CSS 外,還能導入別的資源,比如圖片、腳本和字體等;而 @import 是 CSS 的語法,只能用來導入 CSS;
link 導入的樣式會在頁面加載時同時加載,@import 導入的樣式需等頁面加載完成後再加載;
link 沒有兼容性問題,@import 不兼容 ie5 以下;
link 可以通過 JS 操作 DOM 動態引入樣式表改變樣式,而 @import 不可以。
@supports 用於查詢特定的 CSS 是否生效,可以結合 not、and 和 or 操作符進行後續的操作。
1 |
/* 如果支持自定義屬性,則把 body 顏色設置為變量 varName 指定的顏色 */ |
層疊樣式表,這裏的層疊怎麼理解呢?其實它是 CSS 中的核心特性之一,用於合併來自多個源的屬性值的算法。比如説針對某個 HTML 標籤,有許多的 CSS 聲明都能作用到的時候,那最後誰應該起作用呢?層疊性説的大概就是這個。
針對不同源的樣式,將按照如下的順序進行層疊,越往下優先級越高:
用户代理樣式表中的聲明 (例如,瀏覽器的默認樣式,在沒有設置其他樣式時使用)。
用户樣式表中的常規聲明 (由用户設置的自定義樣式。由於 Chrome 在很早的時候就放棄了用户樣式表的功能,所以這裏將不再考慮它的排序。)。
作者樣式表中的常規聲明 (這些是我們 Web 開發人員設置的樣式)。
作者樣式表中的 !important 聲明。
用户樣式表中的 !important 聲明 S。
理解層疊性的時候需要結合 CSS 選擇器的優先級以及繼承性來理解。比如針對同一個選擇器,定義在後面的聲明會覆蓋前面的;作者定義的樣式會比默認繼承的樣式優先級更高。
CSS 選擇器無疑是其核心之一,對於基礎選擇器以及一些常用偽類必須掌握。下面列出了常用的選擇器。 想要獲取更多選擇器的用法可以看 MDN CSS Selectors。
標籤選擇器:h1
類選擇器:.checked
ID 選擇器:#picker
通配選擇器:*
屬性選擇器
[attr]
:指定屬性的元素;
[attr=val]
:屬性等於指定值的元素;
[attr*=val]
:屬性包含指定值的元素;
[attr^=val]
:屬性以指定值開頭的元素;
[attr$=val]
:屬性以指定值結尾的元素;
[attr~=val]
:屬性包含指定值 (完整單詞) 的元素(不推薦使用);
[attr|=val]
:屬性以指定值 (完整單詞) 開頭的元素(不推薦使用);
相鄰兄弟選擇器:A + B
普通兄弟選擇器:A ~ B
子選擇器:A > B
後代選擇器:A B
條件偽類
:lang()
:基於元素語言來匹配頁面元素;
:dir()
:匹配特定文字書寫方向的元素;
:has()
:匹配包含指定元素的元素;
:is()
:匹配指定選擇器列表裏的元素;
:not()
:用來匹配不符合一組選擇器的元素;
行為偽類
:active
:鼠標激活的元素;
:hover
: 鼠標懸浮的元素;
::selection
:鼠標選中的元素;
狀態偽類
:target
:當前錨點的元素;
:link
:未訪問的鏈接元素;
:visited
:已訪問的鏈接元素;
:focus
:輸入聚焦的表單元素;
:required
:輸入必填的表單元素;
:valid
:輸入合法的表單元素;
:invalid
:輸入非法的表單元素;
:in-range
:輸入範圍以內的表單元素;
:out-of-range
:輸入範圍以外的表單元素;
:checked
:選項選中的表單元素;
:optional
:選項可選的表單元素;
:enabled
:事件啟用的表單元素;
:disabled
:事件禁用的表單元素;
:read-only
:只讀的表單元素;
:read-write
:可讀可寫的表單元素;
:blank
:輸入為空的表單元素;
:current()
:瀏覽中的元素;
:past()
:已瀏覽的元素;
:future()
:未瀏覽的元素;
結構偽類
:root
:文檔的根元素;
:empty
:無子元素的元素;
:first-letter
:元素的首字母;
:first-line
:元素的首行;
:nth-child(n)
:元素中指定順序索引的元素;
:nth-last-child(n)
:元素中指定逆序索引的元素;;
:first-child
:元素中為首的元素;
:last-child
:元素中為尾的元素;
:only-child
:父元素僅有該元素的元素;
:nth-of-type(n)
:標籤中指定順序索引的標籤;
:nth-last-of-type(n)
:標籤中指定逆序索引的標籤;
:first-of-type
:標籤中為首的標籤;
:last-of-type
:標籤中為尾標籤;
:only-of-type
:父元素僅有該標籤的標籤;
::before
:在元素前插入內容;
::after
:在元素後插入內容;
優先級就是分配給指定的 CSS 聲明的一個權重,它由匹配的選擇器中的每一種選擇器類型的數值決定。為了記憶,可以把權重分成如下幾個等級,數值越大的權重越高:
10000:!important;
01000:內聯樣式;
00100:ID 選擇器;
00010:類選擇器、偽類選擇器、屬性選擇器;
00001:元素選擇器、偽元素選擇器;
00000:通配選擇器、後代選擇器、兄弟選擇器;
可以看到內聯樣式(通過元素中 style 屬性定義的樣式)的優先級大於任何選擇器;而給屬性值加上 !important
又可以把優先級提至最高,就是因為它的優先級最高,所以需要謹慎使用它,以下有些使用注意事項:
一定要優先考慮使用樣式規則的優先級來解決問題而不是 !important;
只有在需要覆蓋全站或外部 CSS 的特定頁面中使用 !important;
永遠不要在你的插件中使用 !important;
永遠不要在全站範圍的 CSS 代碼中使用 !important;
在 CSS 中有一個很重要的特性就是子元素會繼承父元素對應屬性計算後的值。比如頁面根元素 html 的文本顏色默認是黑色的,頁面中的所有其他元素都將繼承這個顏色,當申明瞭如下樣式後,H1 文本將變成橙色。
1 |
body { |
設想一下,如果 CSS 中不存在繼承性,那麼我們就需要為不同文本的標籤都設置一下 color,這樣一來的後果就是 CSS 的文件大小就會無限增大。
CSS 屬性很多,但並不是所有的屬性默認都是能繼承父元素對應屬性的,那哪些屬性存在默認繼承的行為呢?一定是那些不會影響到頁面佈局的屬性,可以分為如下幾類:
字體相關:font-family
、font-style
、font-size
、font-weight
等;
文本相關:text-align
、text-indent
、text-decoration
、text-shadow
、letter-spacing
、word-spacing
、white-space
、line-height
、color
等;
列表相關:list-style
、list-style-image
、list-style-type
、list-style-position
等;
其他屬性:visibility
、cursor
等;
對於其他默認不繼承的屬性也可以通過以下幾個屬性值來控制繼承行為:
inherit
:繼承父元素對應屬性的計算值;
initial
:應用該屬性的默認值,比如 color 的默認值是 #000
;
unset
:如果屬性是默認可以繼承的,則取 inherit
的效果,否則同 initial
;
revert
:效果等同於 unset
,兼容性差。
在 CSS 的世界中,會把內容按照從左到右、從上到下的順序進行排列顯示。正常情況下會把頁面分割成一行一行的顯示,而每行又可能由多列組成,所以從視覺上看起來就是從上到下從左到右,而這就是 CSS 中的流式佈局,又叫文檔流。文檔流就像水一樣,能夠自適應所在的容器,一般它有如下幾個特性:
塊級元素默認會佔滿整行,所以多個塊級盒子之間是從上到下排列的;
內聯元素默認會在一行裏一列一列的排布,當一行放不下的時候,會自動切換到下一行繼續按照列排布;
如何脱離文檔流呢?
脱流文檔流指節點脱流正常文檔流後,在正常文檔流中的其他節點將忽略該節點並填補其原先空間。文檔一旦脱流,計算其父節點高度時不會將其高度納入,脱流節點不佔據空間。有兩種方式可以讓元素脱離文檔流:浮動和定位。
使用浮動(float)會將元素脱離文檔流,移動到容器左 / 右側邊界或者是另一個浮動元素旁邊,該浮動元素之前佔用的空間將被別的元素填補,另外浮動之後所佔用的區域不會和別的元素之間發生重疊;
使用絕對定位(position: absolute;
)或者固定定位(position: fixed;
)也會使得元素脱離文檔流,且空出來的位置將自動被後續節點填補。
在 CSS 中任何元素都可以看成是一個盒子,而一個盒子是由 4 部分組成的:內容(content)、內邊距(padding)、邊框(border)和外邊距(margin)。
盒模型有 2 種:標準盒模型和 IE 盒模型,本別是由 W3C 和 IExplore 制定的標準。
如果給某個元素設置如下樣式:
1 |
.box { |
標準盒模型認為:盒子的實際尺寸 = 內容(設置的寬 / 高) + 內邊距 + 邊框
所以 .box
元素內容的寬度就為 200px
,而實際的寬度則是 width
+ padding-left
+ padding-right
+ border-left-width
+ border-right-width
= 200 + 10 + 10 + 1 + 1 = 222。
IE 盒模型認為:盒子的實際尺寸 = 設置的寬 / 高 = 內容 + 內邊距 + 邊框
.box
元素所佔用的實際寬度為 200px
,而內容的真實寬度則是 width
- padding-left
- padding-right
- border-left-width
- border-right-width
= 200 - 10 - 10 - 1 - 1 = 178。
現在高版本的瀏覽器基本上默認都是使用標準盒模型,而像 IE6 這種老古董才是默認使用 IE 盒模型的。
在 CSS3 中新增了一個屬性 box-sizing
,允許開發者來指定盒子使用什麼標準,它有 2 個值:
content-box
:標準盒模型;
border-box
:IE 盒模型;
視覺格式化模型(Visual formatting model)是用來處理和在視覺媒體上顯示文檔時使用的計算規則。CSS 中一切皆盒子,而視覺格式化模型簡單來理解就是規定這些盒子應該怎麼樣放置到頁面中去,這個模型在計算的時候會依賴到很多的因素,比如:盒子尺寸、盒子類型、定位方案(是浮動還是定位)、兄弟元素或者子元素以及一些別的因素。
從上圖中可以看到視覺格式化模型涉及到的內容很多,有興趣深入研究的可以結合上圖看這個 W3C 的文檔 Visual formatting model。所以這裏就簡單介紹下盒子類型。
盒子類型由 display 決定,同時給一個元素設置 display 後,將會決定這個盒子的 2 個顯示類型(display type):
outer display type(對外顯示):決定了該元素本身是如何佈局的,即參與何種格式化上下文;
inner display type(對內顯示):其實就相當於把該元素當成了容器,規定了其內部子元素是如何佈局的,參與何種格式化上下文;
對外顯示方面,盒子類型可以分成 2 類:block-level box(塊級盒子) 和 inline-level box(行內級盒子)。
依據上圖可以列出都有哪些塊級和行內級盒子:
塊級盒子:display 為 block、list-item、table、flex、grid、flow-root 等;
行內級盒子:display 為 inline、inline-block、inline-table 等;
所有塊級盒子都會參與 BFC,呈現垂直排列;而所有行內級盒子都參會 IFC,呈現水平排列。
除此之外,block、inline 和 inline-block 還有什麼更具體的區別呢?
block
佔滿一行,默認繼承父元素的寬度;多個塊元素將從上到下進行排列;
設置 width/height 將會生效;
設置 padding 和 margin 將會生效;
inline
不會佔滿一行,寬度隨着內容而變化;多個 inline 元素將按照從左到右的順序在一行裏排列顯示,如果一行顯示不下,則自動換行;
設置 width/height 將不會生效;
設置豎直方向上的 padding 和 margin 將不會生效;
inline-block
是行內塊元素,不單獨佔滿一行,可以看成是能夠在一行裏進行左右排列的塊元素;
設置 width/height 將會生效;
設置 padding 和 margin 將會生效;
對內方面,其實就是把元素當成了容器,裏面包裹着文本或者其他子元素。container box 的類型依據 display 的值不同,分為 4 種:
block container:建立 BFC 或者 IFC;
flex container:建立 FFC;
grid container:建立 GFC;
ruby container:接觸不多,不做介紹。
值得一提的是如果把 img 這種替換元素(replaced element)申明為 block 是不會產生 container box 的,因為替換元素比如 img 設計的初衷就僅僅是通過 src 把內容替換成圖片,完全沒考慮過會把它當成容器。
參考:
格式化上下文(Formatting Context)是 CSS2.1 規範中的一個概念,大概説的是頁面中的一塊渲染區域,規定了渲染區域內部的子元素是如何排版以及相互作用的。
不同類型的盒子有不同格式化上下文,大概有這 4 類:
BFC (Block Formatting Context) 塊級格式化上下文;
IFC (Inline Formatting Context) 行內格式化上下文;
FFC (Flex Formatting Context) 彈性格式化上下文;
GFC (Grid Formatting Context) 格柵格式化上下文;
其中 BFC 和 IFC 在 CSS 中扮演着非常重要的角色,因為它們直接影響了網頁佈局,所以需要深入理解其原理。
塊格式化上下文,它是一個獨立的渲染區域,只有塊級盒子參與,它規定了內部的塊級盒子如何佈局,並且與這個區域外部毫不相干。
BFC 渲染規則
內部的盒子會在垂直方向,一個接一個地放置;
盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊;
每個元素的 margin 的左邊,與包含塊 border 的左邊相接觸 (對於從左往右的格式化,否則相反),即使存在浮動也是如此;
BFC 的區域不會與 float 盒子重疊;
BFC 就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。
計算 BFC 的高度時,浮動元素也參與計算。
如何創建 BFC?
根元素:html
非溢出的可見元素:overflow 不為 visible
設置浮動:float 屬性不為 none
設置定位:position 為 absolute 或 fixed
定義成塊級的非塊級元素:display: inline-block/table-cell/table-caption/flex/inline-flex/grid/inline-grid
BFC 應用場景
1、 自適應兩欄佈局
應用原理:BFC 的區域不會和浮動區域重疊,所以就可以把側邊欄固定寬度且左浮動,而對右側內容觸發 BFC,使得它的寬度自適應該行剩餘寬度。
1 |
<div class="layout"> |
1 |
.aside { |
2、清除內部浮動
浮動造成的問題就是父元素高度坍塌,所以清除浮動需要解決的問題就是讓父元素的高度恢復正常。而用 BFC 清除浮動的原理就是:計算 BFC 的高度時,浮動元素也參與計算。只要觸發父元素的 BFC 即可。
1 |
.parent { |
3、 防止垂直 margin 合併
BFC 渲染原理之一:同一個 BFC 下的垂直 margin 會發生合併。所以如果讓 2 個元素不在同一個 BFC 中即可阻止垂直 margin 合併。那如何讓 2 個相鄰的兄弟元素不在同一個 BFC 中呢?可以給其中一個元素外面包裹一層,然後觸發其包裹層的 BFC,這樣一來 2 個元素就不會在同一個 BFC 中了。
1 |
<div class="layout"> |
1 |
.demo3 .a, |
針對以上 3 個 示例 ,可以結合這個 BFC 應用示例 配合觀看更佳。
參考:CSS 原理 - Formatting Context
IFC 的形成條件非常簡單,塊級元素中僅包含內聯級別元素,需要注意的是當 IFC 中有塊級元素插入時,會產生兩個匿名塊將父元素分割開來,產生兩個 IFC。
IFC 渲染規則
子元素在水平方向上一個接一個排列,在垂直方向上將以容器頂部開始向下排列;
節點無法聲明寬高,其中 margin 和 padding 在水平方向有效在垂直方向無效;
節點在垂直方向上以不同形式對齊;
能把在一行上的框都完全包含進去的一個矩形區域,被稱為該行的線盒(line box)。線盒的寬度是由包含塊(containing box)和與其中的浮動來決定;
IFC 中的 line box 一般左右邊貼緊其包含塊,但 float 元素會優先排列。
IFC 中的 line box 高度由 line-height 計算規則來確定,同個 IFC 下的多個 line box 高度可能會不同;
當內聯級盒子的總寬度少於包含它們的 line box 時,其水平渲染規則由 text-align 屬性值來決定;
當一個內聯盒子超過父元素的寬度時,它會被分割成多盒子,這些盒子分佈在多個 line box 中。如果子元素未設置強制換行的情況下,inline box 將不可被分割,將會溢出父元素。
針對如上的 IFC 渲染規則,你是不是可以分析下下面這段代碼的 IFC 環境是怎麼樣的呢?
1 |
<p>It can get <strong>very complicated</storng> once you start looking into it.</p> |
對應上面這樣一串 HTML 分析如下:
p 標籤是一個 block container,對內將產生一個 IFC;
由於一行沒辦法顯示完全,所以產生了 2 個線盒(line box);線盒的寬度就繼承了 p 的寬度;高度是由裏面的內聯盒子的 line-height 決定;
It can get:匿名的內聯盒子;
very complicated:strong 標籤產生的內聯盒子;
once you start:匿名的內聯盒子;
looking into it.:匿名的內聯盒子。
IFC 應用場景
水平居中:當一個塊要在環境中水平居中時,設置其為 inline-block 則會在外層產生 IFC,通過 text-align 則可以使其水平居中。
垂直居中:創建一個 IFC,用其中一個元素撐開父元素的高度,然後設置其 vertical-align: middle,其他行內元素則可以在此父元素下垂直居中。
偷個懶,demo 和圖我就不做了。
在電腦顯示屏幕上的顯示的頁面其實是一個三維的空間,水平方向是 X 軸,豎直方向是 Y 軸,而屏幕到眼睛的方向可以看成是 Z 軸。眾 HTML 元素依據自己定義的屬性的優先級在 Z 軸上按照一定的順序排開,而這其實就是層疊上下文所要描述的東西。
我們對層疊上下文的第一印象可能要來源於 z-index,認為它的值越大,距離屏幕觀察者就越近,那麼層疊等級就越高,事實確實是這樣的,但層疊上下文的內容遠非僅僅如此:
z-index 能夠在層疊上下文中對元素的堆疊順序其作用是必須配合定位才可以;
除了 z-index 之外,一個元素在 Z 軸上的顯示順序還受層疊等級和層疊順序影響;
在看層疊等級和層疊順序之前,我們先來看下如何產生一個層疊上下文,特定的 HTML 元素或者 CSS 屬性產生層疊上下文,MDN 中給出了這麼一個列表,符合以下任一條件的元素都會產生層疊上下文:
html 文檔根元素
聲明 position: absolute/relative 且 z-index 值不為 auto 的元素;
聲明 position: fixed/sticky 的元素;
flex 容器的子元素,且 z-index 值不為 auto;
grid 容器的子元素,且 z-index 值不為 auto;
opacity 屬性值小於 1 的元素;
mix-blend-mode 屬性值不為 normal 的元素;
以下任意屬性值不為 none 的元素:
transform
filter
perspective
clip-path
mask / mask-image / mask-border
isolation 屬性值為 isolate 的元素;
-webkit-overflow-scrolling 屬性值為 touch 的元素;
will-change 值設定了任一屬性而該屬性在 non-initial 值時會創建層疊上下文的元素;
contain 屬性值為 layout、paint 或包含它們其中之一的合成值(比如 contain: strict、contain: content)的元素。
層疊等級
層疊等級指節點在三維空間 Z 軸上的上下順序。它分兩種情況:
在同一個層疊上下文中,它描述定義的是該層疊上下文中的層疊上下文元素在 Z 軸上的上下順序;
在其他普通元素中,它描述定義的是這些普通元素在 Z 軸上的上下順序;
普通節點的層疊等級優先由其所在的層疊上下文決定,層疊等級的比較只有在當前層疊上下文中才有意義,脱離當前層疊上下文的比較就變得無意義了。
層疊順序
在同一個層疊上下文中如果有多個元素,那麼他們之間的層疊順序是怎麼樣的呢?
以下這個列表越往下層疊優先級越高,視覺上的效果就是越容易被用户看到(不會被其他元素覆蓋):
層疊上下文的 border 和 background
z-index < 0 的子節點
標準流內塊級非定位的子節點
浮動非定位的子節點
標準流內行內非定位的子節點
z-index: auto/0 的子節點
z-index > 0 的子節點
如何比較兩個元素的層疊等級?
在同一個層疊上下文中,比較兩個元素就是按照上圖的介紹的層疊順序進行比較。
如果不在同一個層疊上下文中的時候,那就需要比較兩個元素分別所處的層疊上下文的等級。
如果兩個元素都在同一個層疊上下文,且層疊順序相同,則在 HTML 中定義越後面的層疊等級越高。
參考:徹底搞懂 CSS 層疊上下文、層疊等級、層疊順序、z-index
CSS 的聲明是由屬性和值組成的,而值的類型有許多種:
數值:長度值 ,用於指定例如元素 width、border-width、font-size 等屬性的值;
百分比:可以用於指定尺寸或長度,例如取決於父容器的 width、height 或默認的 font-size;
顏色:用於指定 background-color、color 等;
座標位置:以屏幕的左上角為座標原點定位元素的位置,比如常見的 background-position、top、right、bottom 和 left 等屬性;
函數:用於指定資源路徑或背景圖片的漸變,比如 url()、linear-gradient() 等;
而還有些值是需要帶單位的,比如 width: 100px,這裏的 px 就是表示長度的單位,長度單位除了 px 外,比較常用的還有 em、rem、vw/vh 等。那他們有什麼區別呢?又應該在什麼時候使用它們呢?
屏幕分辨率是指在屏幕的橫縱方向上的像素點數量,比如分辨率 1920×1080 意味着水平方向含有 1920 個像素數,垂直方向含有 1080 個像素數。
而 px 表示的是 CSS 中的像素,在 CSS 中它是絕對的長度單位,也是最基礎的單位,其他長度單位會自動被瀏覽器換算成 px。但是對於設備而言,它其實又是相對的長度單位,比如寬高都為 2px,在正常的屏幕下,其實就是 4 個像素點,而在設備像素比 (devicePixelRatio) 為 2 的 Retina 屏幕下,它就有 16 個像素點。所以屏幕尺寸一致的情況下,屏幕分辨率越高,顯示效果就越細膩。
講到這裏,還有一些相關的概念需要理清下:
設備像素(Device pixels)
設備屏幕的物理像素,表示的是屏幕的橫縱有多少像素點;和屏幕分辨率是差不多的意思。
設備像素比(DPR)
設備像素比表示 1 個 CSS 像素等於幾個物理像素。
計算公式:DPR = 物理像素數 / 邏輯像素數;
在瀏覽器中可以通過 window.devicePixelRatio 來獲取當前屏幕的 DPR。
像素密度(DPI/PPI)
像素密度也叫顯示密度或者屏幕密度,縮寫為 DPI(Dots Per Inch) 或者 PPI(Pixel Per Inch)。從技術角度説,PPI 只存在於計算機顯示領域,而 DPI 只出現於打印或印刷領域。
計算公式:像素密度 = 屏幕對角線的像素尺寸 / 物理尺寸
比如,對於分辨率為 750 * 1334 的 iPhone 6 來説,它的像素密度為:
1 |
Math.sqrt(750 * 750 + 1334 * 1334) / 4.7 = 326ppi |
設備獨立像素(DIP)
DIP 是特別針對 Android 設備而衍生出來的,原因是安卓屏幕的尺寸繁多,因此為了顯示能儘量和設備無關,而提出的這個概念。它是基於屏幕密度而計算的,認為當屏幕密度是 160 的時候,px = DIP。
計算公式:dip = px * 160 / dpi
em 是 CSS 中的相對長度單位中的一個。居然是相對的,那它到底是相對的誰呢?它有 2 層意思:
在 font-size 中使用是相對於父元素的 font-size 大小,比如父元素 font-size: 16px,當給子元素指定 font-size: 2em 的時候,經過計算後它的字體大小會是 32px;
在其他屬性中使用是相對於自身的字體大小,如 width/height/padding/margin 等;
我們都知道每個瀏覽器都會給 HTML 根元素 html 設置一個默認的 font-size,而這個值通常是 16px。這也就是為什麼 1em = 16px 的原因所在了。
em 在計算的時候是會層層計算的,比如:
1 |
<div> |
1 |
div { font-size: 2em; } |
對於如上一個結構的 HTML,由於根元素 html 的字體大小是 16px,所以 p 標籤最終計算出來後的字體大小會是 16 * 2 * 2 = 64px
rem(root em) 和 em 一樣,也是一個相對長度單位,不過 rem 相對的是 HTML 的根元素 html。
rem 由於是基於 html 的 font-size 來計算,所以通常用於自適應網站或者 H5 中。
比如在做 H5 的時候,前端通常會讓 UI 給 750px 寬的設計圖,而在開發的時候可以基於 iPhone X 的尺寸 375px * 812px 來寫頁面,這樣一來的話,就可以用下面的 JS 依據當前頁面的視口寬度自動計算出根元素 html 的基準 font-size 是多少。
1 |
(function (doc, win) { |
比如當視口是 375px 的時候,經過計算 html 的 font-size 會是 100px,這樣有什麼好處呢?好處就是方便寫樣式,比如從設計圖量出來的 header 高度是 50px 的,那我們寫樣式的時候就可以直接寫:
1 |
header { |
每個從設計圖量出來的尺寸只要除於 100 即可得到當前元素的 rem 值,都不用經過計算,非常方便。偷偷告訴你,如果你把上面那串計算 html 標籤 font-size 的 JS 代碼中的 200 替換成 2,那在計算 rem 的時候就不需要除於 100 了,從設計圖量出多大 px,就直接寫多少個 rem。
vw 和 vh 分別是相對於屏幕視口寬度和高度而言的長度單位:
1vw = 視口寬度均分成 100 份中 1 份的長度;
1vh = 視口高度均分成 100 份中 1 份的長度;
在 JS 中 100vw = window.innerWidth,100vh = window.innerHeight。
vw/vh 的出現使得多了一種寫自適應佈局的方案,開發者不再侷限於 rem 了。
相對視口的單位,除了 vw/vh 外,還有 vmin 和 vmax:
vmin:取 vw 和 vh 中值較小的;
vmax:取 vw 和 vh 中值較大的;
CSS 中用於表示顏色的值種類繁多,足夠構成一個體系,所以這裏就專門拿出一個小節來講解它。
根據 CSS 顏色草案 中提到的顏色值類型,大概可以把它們分為這幾類:
顏色關鍵字
transparent 關鍵字
currentColor 關鍵字
RGB 顏色
HSL 顏色
顏色關鍵字(color keywords)是不區分大小寫的標識符,它表示一個具體的顏色,比如 white(白),黑(black)等;
可接受的關鍵字列表在 CSS 的演變過程中發生了改變:
CSS 標準 1 只接受 16 個基本顏色,稱為 VGA 顏色,因為它們來源於 VGA 顯卡所顯示的顏色集合而被稱為 VGA colors (視頻圖形陣列色彩)。
CSS 標準 2 增加了 orange 關鍵字。
從一開始,瀏覽器接受其它的顏色,由於一些早期瀏覽器是 X11 應用程序,這些顏色大多數是 X11 命名的顏色列表,雖然有一點不同。SVG 1.0 是首個正式定義這些關鍵字的標準;CSS 色彩標準 3 也正式定義了這些關鍵字。它們經常被稱作擴展的顏色關鍵字, X11 顏色或 SVG 顏色 。
CSS 顏色標準 4 添加可 rebeccapurple 關鍵字來紀念 web 先鋒 Eric Meyer。
如下這張圖是 16 個基礎色,又叫 VGA 顏色。截止到目前為止 CSS 顏色關鍵字總共有 146 個,這裏可以查看 完整的色彩關鍵字列表。
需要注意的是如果聲明的時候的顏色關鍵字是錯誤的,瀏覽器會忽略它。
transparent 關鍵字表示一個完全透明的顏色,即該顏色看上去將是背景色。從技術上説,它是帶有 alpha 通道為最小值的黑色,是 rgba(0,0,0,0) 的簡寫。
透明關鍵字有什麼應用場景呢?
實現三角形
下面這個圖是用 4 條邊框填充的正方形,看懂了它你大概就知道該如何用 CSS 寫三角形了。
1 |
div { |
用 transparent 實現三角形的原理:
首先寬高必須是 0px,通過邊框的粗細來填充內容;
那條邊需要就要加上顏色,而不需要的邊則用 transparent;
想要什麼樣姿勢的三角形,完全由上下左右 4 條邊的中有顏色的邊和透明的邊的位置決定;
等腰三角形:設置一條邊有顏色,然後緊挨着的 2 邊是透明,且寬度是有顏色邊的一半;直角三角形:設置一條邊有顏色,然後緊挨着的任何一邊透明即可。
看下示例:
增大點擊區域
常常在移動端的時候點擊的按鈕的區域特別小,但是由於現實效果又不太好把它做大,所以常用的一個手段就是通過透明的邊框來增大按鈕的點擊區域:
1 |
.btn { |
currentColor 會取當前元素繼承父級元素的文本顏色值或聲明的文本顏色值,即 computed 後的 color 值。
比如,對於如下 CSS,該元素的邊框顏色會是 red:
1 |
.btn { |
RGB[A] 顏色是由 R(red)-G(green)-B(blue)-A(alpha) 組成的色彩空間。
在 CSS 中,它有兩種表示形式:
十六進制符號;
函數符;
十六進制符號
RGB 中的每種顏色的值範圍是 00~ff,值越大表示顏色越深。所以一個顏色正常是 6 個十六進制字符加上 # 組成,比如紅色就是 #ff0000。
如果 RGB 顏色需要加上不透明度,那就需要加上 alpha 通道的值,它的範圍也是 00~ff,比如一個帶不透明度為 67% 的紅色可以這樣寫 #ff0000aa。
使用十六進制符號表示顏色的時候,都是用 2 個十六進制表示一個顏色,如果這 2 個字符相同,還可以縮減成只寫 1 個,比如,紅色 #f00;帶 67% 不透明度的紅色 #f00a。
函數符
當 RGB 用函數表示的時候,每個值的範圍是 0255 或者 0%100%,所以紅色是 rgb(255, 0, 0), 或者 rgb(100%, 0, 0)。
如果需要使用函數來表示帶不透明度的顏色值,值的範圍是 01 及其之間的小數或者 0%100%,比如帶 67% 不透明度的紅色是 rgba(255, 0, 0, 0.67) 或者 rgba(100%, 0%, 0%, 67%)
需要注意的是 RGB 這 3 個顏色值需要保持一致的寫法,要嘛用數字要嘛用百分比,而不透明度的值的可以不用和 RGB 保持一致寫法。比如 rgb(100%, 0, 0) 這個寫法是無效的;而 rgb(100%, 0%, 0%, 0.67) 是有效的。
在第 4 代 CSS 顏色標準中,新增了一種新的函數寫法,即可以把 RGB 中值的分隔逗號改成空格,而把 RGB 和 alpha 中的逗號改成 /,比如帶 67% 不透明度的紅色可以這樣寫 rgba(255 0 0 / 0.67)。另外還把 rgba 的寫法合併到 rgb 函數中了,即 rgb 可以直接寫帶不透明度的顏色。
HSL[A] 顏色是由色相 (hue)- 飽和度 (saturation)- 亮度 (lightness)- 不透明度組成的顏色體系。
色相(H)是色彩的基本屬性,值範圍是 0360 或者 0deg360deg, 0 (或 360) 為紅色, 120 為綠色, 240 為藍色;
飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取 0~100% 的數值;0% 為灰色, 100% 全色;
亮度(L),取 0~100%,0% 為暗,100% 為白;
不透明度(A),取 0100%,或者 01 及之間的小數;
寫法上可以參考 RGB 的寫法,只是參數的值不一樣。
給一個按鈕設置不透明度為 67% 的紅色的 color 的寫法,以下全部寫法效果一致:
1 |
button { |
小提示:在 Chrome DevTools 中可以按住 shift + 鼠標左鍵可以切換顏色的表示方式。
媒體查詢是指針對不同的設備、特定的設備特徵或者參數進行定製化的修改網站的樣式。
你可以通過給 <link>
加上 media 屬性來指定該樣式文件只能對什麼設備生效,不指定的話默認是 all,即對所有設備都生效:
1 |
<link rel="stylesheet" src="styles.css" media="screen" /> |
都支持哪些設備類型?
all:適用於所有設備;
print:適用於在打印預覽模式下在屏幕上查看的分頁材料和文檔;
screen:主要用於屏幕;
speech:主要用於語音合成器。
需要注意的是:通過 media 指定的 資源儘管不匹配它的設備類型,但是瀏覽器依然會加載它。
除了通過 <link>
讓指定設備生效外,還可以通過 @media
讓 CSS 規則在特定的條件下才能生效。響應式頁面就是使用了 @media 才讓一個頁面能夠同時適配 PC、Pad 和手機端。
1 |
@media (min-width: 1000px) {} |
媒體查詢支持邏輯操作符:
and:查詢條件都滿足的時候才生效;
not:查詢條件取反;
only:整個查詢匹配的時候才生效,常用語兼容舊瀏覽器,使用時候必須指定媒體類型;
逗號或者 or:查詢條件滿足一項即可匹配;
媒體查詢還支持眾多的媒體特性,使得它可以寫出很複雜的查詢條件:
1 |
/* 用户設備的最小高度為680px或為縱向模式的屏幕設備 */ |
之前我們通常是在預處理器裏才可以使用變量,而現在 CSS 裏也支持了變量的用法。通過自定義屬性就可以在想要使用的地方引用它。
自定義屬性也和普通屬性一樣具有級聯性,申明在 :root 下的時候,在全文檔範圍內可用,而如果是在某個元素下申明自定義屬性,則只能在它及它的子元素下才可以使用。
自定義屬性必須通過 --x
的格式申明,比如:–theme-color: red; 使用自定義屬性的時候,需要用 var 函數。比如:
1 |
<!-- 定義自定義屬性 --> |
上圖這個是使用 CSS 自定義屬性配合 JS 實現的動態調整元素的 box-shadow,具體可以看這個 codepen demo。
Retina 顯示屏比普通的屏幕有着更高的分辨率,所以在移動端的 1px 邊框就會看起來比較粗,為了美觀通常需要把這個線條細化處理。這裏有篇文章列舉了 7 中方案可以參考一下:7 種方法解決移動端 Retina 屏幕 1px 邊框問題
而這裏附上最後一種通過偽類和 transform 實現的相對完美的解決方案:
只設置單條底部邊框:
1 |
.scale-1px-bottom { |
同時設置 4 條邊框:
1 |
.scale-1px { |
什麼是浮動:浮動元素會脱離文檔流並向左 / 向右浮動,直到碰到父元素或者另一個浮動元素。
為什麼要清楚浮動,它造成了什麼問題?
因為浮動元素會脱離正常的文檔流,並不會佔據文檔流的位置,所以如果一個父元素下面都是浮動元素,那麼這個父元素就無法被浮動元素所撐開,這樣一來父元素就丟失了高度,這就是所謂的浮動造成的父元素高度坍塌問題。
父元素高度一旦坍塌將對後面的元素佈局造成影響,為了解決這個問題,所以需要清除浮動,讓父元素恢復高度,那該如何做呢?
這裏介紹兩種方法:通過 BFC 來清除、通過 clear 來清除。
前面介紹 BFC 的時候提到過,計算 BFC 高度的時候浮動子元素的高度也將計算在內,利用這條規則就可以清楚浮動。
假設一個父元素 parent 內部只有 2 個子元素 child,且它們都是左浮動的,這個時候 parent 如果沒有設置高度的話,因為浮動造成了高度坍塌,所以 parent 的高度會是 0,此時只要給 parent 創造一個 BFC,那它的高度就能恢復了。
而產生 BFC 的方式很多,我們可以給父元素設置 overflow: auto 來簡單的實現 BFC 清除浮動,但是為了兼容 IE 最好用 overflow: hidden。
1 |
.parent { |
通過 overflow: hidden 來清除浮動並不完美,當元素有陰影或存在下拉菜單的時候會被截斷,所以該方法使用比較侷限。
我先把結論貼出來:
1 |
.clearfix { |
這種寫法的核心原理就是通過 ::after 偽元素為在父元素的最後一個子元素後面生成一個內容為空的塊級元素,然後通過 clear 將這個偽元素移動到所有它之前的浮動元素的後面,畫個圖來理解一下。
可以結合這個 codepen demo 一起理解上圖的 clear 清楚浮動原理。
上面這個 demo 或者圖裏為了展示需要所以給偽元素的內容設置為了 ::after,實際使用的時候需要設置為空字符串,讓它的高度為 0,從而父元素的高度都是由實際的子元素撐開。
該方式基本上是現在人人都在用的清除浮動的方案,非常通用。
針對同一個類型的 HTML 標籤,不同的瀏覽器往往有不同的表現,所以在網站製作的時候,開發者通常都是需要將這些瀏覽器的默認樣式清除,讓網頁在不同的瀏覽器上能夠保持一致。
針對清除瀏覽器默認樣式這件事,在很早之前 CSS 大師 Eric A. Meyer 就幹過。它就是寫一堆通用的樣式用來重置瀏覽器默認樣式,這些樣式通常會放到一個命名為 reset.css 文件中。比如大師的 reset.css 是這麼寫的:
1 |
html, body, div, span, applet, object, iframe, |
他的這份 reset.css 據説是被使用最廣泛的重設樣式的方案了。
除了 reset.css 外,後來又出現了 Normalize.css 。關於 Normalize.css, 其作者 necolas 專門寫了一篇文章介紹了它,並談到了它和 reset.css 的區別。這個是他寫那篇文章的翻譯版:讓我們談一談 Normalize.css。
文章介紹到:Normalize.css 只是一個很小的 CSS 文件,但它在默認的 HTML 元素樣式上提供了跨瀏覽器的高度一致性。相比於傳統的 CSS reset,Normalize.css 是一種現代的、為 HTML5 準備的優質替代方案,現在已經有很多知名的框架和網站在使用它了。
Normalize.css 的具體樣式可以看這裏 Normalize.css
區別於 reset.css,Normalize.css 有如下特點:
reset.css 幾乎為所有標籤都設置了默認樣式,而 Normalize.css 則是有選擇性的保護了部分有價值的默認值;
修復了很多瀏覽器的 bug,而這是 reset.css 沒做到的;
不會讓你的調試工具變的雜亂,相反 reset.css 由於設置了很多默認值,所以在瀏覽器調試工具中往往會看到一大堆的繼承樣式,顯得很雜亂;
Normalize.css 是模塊化的,所以可以選擇性的去掉永遠不會用到的部分,比如表單的一般化;
Normalize.css 有詳細的説明文檔;
默認:字符太長溢出了容器
字符超出部分換行
字符超出位置使用連字符
單行文本超出省略
多行文本超出省略
查看以上這些方案的示例: codepen demo
有意思的是剛好前兩天看到 chokcoco 針對文本溢出也寫了一篇文章,主要突出的是對整塊的文本溢出處理。啥叫整塊文本?比如,下面這種技術標籤就是屬於整塊文本:
另外他還對 iOS/Safari 做了兼容處理,感興趣的可以去閲讀下:CSS 整塊文本溢出省略特性探究。
讓元素在父元素中呈現出水平垂直居中的形態,無非就 2 種情況:
單行的文本、inline 或者 inline-block 元素;
固定寬高的塊級盒子;
不固定寬高的塊級盒子;
以下列到的所有水平垂直居中方案這裏寫了個 codepen demo,配合示例閲讀效果更佳。
水平居中
此類元素需要水平居中,則父級元素必須是塊級元素 (block level
),且父級元素上需要這樣設置樣式:
1 |
.parent { |
垂直居中
方法一:通過設置上下內間距一致達到垂直居中的效果:
1 |
.single-line { |
方法二:通過設置 height
和 line-height
一致達到垂直居中:
1 |
.single-line { |
方法一:absolute + 負 margin
方法二:absolute + margin auto
方法三:absolute + calc
這裏列了 6 種方法,參考了顏海鏡 寫的文章 ,其中的兩種 line-height 和 writing-mode 方案看後讓我驚呼:還有這種操作?學到了學到了。
方法一:absolute + transform
方法二:line-height + vertical-align
方法三:writing-mode
方法四:table-cell
方法五:flex
方法六:grid
針對以下這些方案寫了幾個示例: codepen demo
方法一:float + overflow(BFC 原理)
方法二:float + margin
方法三:flex
方法四:grid
針對以下這些方案寫了幾個示例: codepen demo
方法一:聖盃佈局
方法二:雙飛翼佈局
方法三:float + overflow(BFC 原理)
方法四:flex
方法五:grid
結合示例閲讀更佳:codepen demo
方法一:padding + 負 margin
方法二:設置父級背景圖片
列了 4 種方法,都是基於如下的 HTML 和 CSS 的,結合示例閲讀效果更佳:codepen demo
1 |
<div class="layout"> |
1 |
html, |
方法一:calc
方法二:absolute
方法三:flex
方法四:grid
這是我斷斷續續寫了 2 周完成的文章,算是自己對 CSS 的一個總結,雖然寫得很長,但不足以覆蓋所有 CSS 的知識,比如動畫和一些 CSS3 的新特性就完全沒涉及,因為這要寫下來估計得有大幾萬字(其實就是懶 😝 )。
碼字作圖不易,如果喜歡或者對你有絲毫幫助的話,幫忙點個👍 哈,點贊就是我的動力。同時也希望自己能堅持認真的寫下去,因為在總結提升自己的同時如果也能幫助更多的前端 er,那將會讓我感覺很開心。
2021-03-11 01:10:28
Date 類型使用自 UTC 世界協調時間 1970 年 1 月 1 日午夜零時開始經過的毫秒數
來保存日期
通過使用 new 操作符和 Date 構造函數來創建日期對象
var now = new Date()
Date()
可以選擇傳入參數,如果不傳入參數
不傳入參數
會依據系統設置的當前時間來創建一個Date對象,返回當前的日期和時間
傳入參數 Unix 时间戳
即 从1970-1-1 00:00:00 UTC 到该日期對象(UTC時間)的毫秒数
傳入 时间戳字符串
與下文的 Date.parse()
所需的參數一樣
傳入 日期成員
與 下文的 Date.UTC()
所需的參數一樣,但是 Date() 會以 本地時間 來處理參數,而不是 UTC。
1 |
// 可見最終的結果 兩個不一樣, 原因是 Date() 會以本地時間來處理參數 |
以一個函數的形式來調用 Date 對象(即不使用 new 操作符)會返回一個代表當前日期和時間的字符串
1 |
var d1 = new Date() |
JavaScript 提供了兩種方法可以快速獲取毫秒數
Date.parse()
該方法接受一個表示日期的字符串參數(符合RFC 2822 和 ISO 8601 的日期格式,其他格式也支持,但是結果可能會與預期不同),然後根據字符串返回相應的日期的毫秒數(从1970-1-1 00:00:00 UTC 到该日期對象(UTC時間)的毫秒数)。
如果傳入的參數無法識別,則會返回 NaN
如果參數沒有指定時區,默認使用本地時區。
在 ISO 8601 格式中
- ‘2011-02-22’ 這種僅日期格式的,將會使用 UTC 時區來處理解析這個參數
- 如果是日期加時間的,則使用本地時間處理
這個方法可能在不同瀏覽器和地區,有不一樣的結果
1 |
console.log(Date.parse('2012-02-02')) // 1328140800000 (utc 時間 2012-02-02 00:00:00) 以 UTC 時間處理 |
Date.UTC()
跟Date.parse()
一樣都是返回相應的日期的毫秒數(从1970-1-1 00:00:00 UTC 到该日期對象(UTC時間)的毫秒数),區別在於傳入的參數不同,其可以傳入很多參數。其傳入的參數會以 UTC 時區
處理。
Date.UTC(year,month[,date[,hrs[,min[,sec[,ms]]]]])
【必須】year 年份
可以是完整格式的年份,如 2022。
如果是 0 到 99 之間,代表著 1900 年後的日期(傳入 8,會被渲染為 1908年)
【必須】month 月份
0 到 11 之間的整數
date 天數
1 到 31 之間的整數
hrs 小時
0 到 23 之間的整數
min 分鐘
0 到 59 之間的整數
sec 秒
0 到 59 之間的整數
ms 毫秒
0 到 999 之間的整數
注意: 如果沒有傳入 date 天數,則默認爲 1。
而省略其它參數,這些參數都默認為 0
如果有一個指定的參數超出其合理範圍,則 UTC 方法會通過更新其他參數直到該參數在合理範圍內。例如,為月份指定 15,則年份將會加 1,然後月份將會使用 3。
1 |
console.log(Date.UTC(2021,1)) // 1612137600000 (utc 時間 2021-02-01 00:00:00) |
返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
等同於 new Date().getTime()
1 |
console.log(new Date().getTime()) // 1615389429001 |
方法 | 解釋 |
---|---|
getFullYear() | 根据本地时间返回指定日期对象的年份(四位数年份时返回四位数字) |
getMonth() | 根据本地时间返回指定日期对象的月份(0-11) |
getDate() | 根据本地时间返回指定日期对象的月份中的第几天(1-31) |
getHours() | 根据本地时间返回指定日期对象的小时(0-23) |
getMinutes() | 根据本地时间返回指定日期对象的分钟(0-59) |
getSeconds() | 根据本地时间返回指定日期对象的秒数(0-59) |
getMilliseconds() | 根据本地时间返回指定日期对象的毫秒(0-999) |
getDay() | 根据本地时间返回指定日期对象的星期中的第几天(0-6) 0 表示 星期日 |
getTime() | 返回从1970-1-1 00:00:00 UTC(协调世界时)到该日期经过的毫秒数,对于1970-1-1 00:00:00 UTC之前的时间返回负值。 |
getTimezoneOffset() | 返回协调世界时(UTC)相对于当前时区的时间差值,单位为分钟 |
getUTCFullYear() | 根据世界时返回特定日期对象所在的年份(4位数) |
getUTCMonth() | 根据世界时返回特定日期对象的月份(0-11) 0 代表 1 月,依此類推 |
getUTCDate() | 根据世界时返回特定日期对象一个月的第几天(1-31) |
getUTCHours() | 根据世界时返回特定日期对象当前的小时(0-23) |
getUTCMinutes() | 根据世界时返回特定日期对象的分钟数(0-59) |
getUTCSeconds() | 根据世界时返回特定日期对象的秒数(0-59) |
getUTCMilliseconds() | 根据世界时返回特定日期对象的毫秒数(0-999) |
getUTCDay() | 根据世界时返回特定日期对象一个星期的第几天(0-6) |
1 |
const today = new Date(2021,2,10,22,55,21,44) |
方法 | 解釋 |
---|---|
setDate() | 根据本地时间为指定的日期对象设置月份中的第几天 |
setFullYear() | 根据本地时间为指定日期对象设置完整年份(四位数年份是四个数字) |
setMonth() | 根据本地时间为指定日期对象设置月份 |
setHours() | 根据本地时间为指定日期对象设置小时数 |
setMinutes() | 根据本地时间为指定日期对象设置分钟数 |
setSeconds() | 根据本地时间为指定日期对象设置秒数 |
setMilliseconds() | 根据本地时间为指定日期对象设置毫秒数 |
setTime() | 通过指定从 1970-1-1 00:00:00 UTC 开始经过的毫秒数来设置日期对象的时间,对于早于 1970-1-1 00:00:00 UTC的时间可使用负值 |
setUTCDate() | 根据世界时设置 Date 对象中月份的一天 (1 ~ 31) |
setUTCFullYear() | 根据世界时设置 Date 对象中的年份(四位数字) |
setUTCMonth() | 根据世界时设置 Date 对象中的月份 (0 ~ 11) |
setUTCHours() | 根据世界时设置 Date 对象中的小时 (0 ~ 23) |
setUTCMinutes() | 根据世界时设置 Date 对象中的分钟 (0 ~ 59) |
setUTCSeconds() | 根据世界时设置 Date 对象中的秒钟 (0 ~ 59) |
setUTCMilliseconds() | 根据世界时设置 Date 对象中的毫秒 (0 ~ 999) |
方法 | 解釋 |
---|---|
toDateString() | 以美式英语和人类易读的形式返回该日期对象日期部分 的字符串 |
toISOString() | 把一个日期转换为符合 ISO 8601 扩展格式的字符串。 格式:YYYY-MM-DDTHH:mm:ss.sssZ ,时区总是UTC |
toJSON() | 調用 toISOString() 返回一个表示该日期的字符串。为了在 JSON.stringify() 方法中使用 |
toString() | 返回一个表示该日期对象的字符串。覆盖了Object.prototype.toString() 方法 |
toTimeString() | 以人类易读格式返回日期对象时间部分的字符串 |
toUTCString() | 把一个日期对象转换为一个以UTC时区计时的字符串 |
valueOf() | 返回一个日期对象的原始值。覆盖了 Object.prototype.valueOf() 方法 |
toLocaleString() | 返回一个表示该日期对象的字符串,该字符串与系统设置的地区关联(locality sensitive)。覆盖了 Object.prototype.toLocaleString() 方法 |
toLocaleTimeString() | 返回一个表示该日期对象时间部分的字符串,该字符串格式与系统设置的地区关联(locality sensitive) |
toLocaleDateString() | 返回一个表示该日期对象日期部分的字符串,该字符串格式与系统设置的地区关联(locality sensitive) |
1 |
const today = new Date(2021,2,10,22,55,21,44) |
toLocaleString()
toLocaleTimeString()
和 toLocaleDateString()
這3個方法都接受兩個參數
【可選】locales
指定語言代碼,例如 ‘zh-HK’
具體語言代碼 可參考 MDN Intl 文檔
當沒有指定語言代碼時,會返回一個使用運行時默認的語言環境和格式(options)的格式化字符串
【可選】options
指定日期時間等輸出(文字/格式 等)
具體 options 可參考 MDN 文檔
1 |
var today = new Date(2021,2,10,22,55,21,44) |
2021-03-11 01:09:06
ECMAScript 數組的每一項可以保存任何類型的數據。
ECMAScript 數組的大小是可以動態調整的,既可以隨著數據的添加自動增長以容納新數據。
使用 Array 構造函數
使用 new Array()
, new 可以省略不寫。
1 |
var colors = new Array(); |
使用數組字面量表示法
1 |
var color = ['red','blue'] |
1 |
var color = ['red','blue','green'] |
可以通過 length
獲取長度。也可以用 length
來從數組的末尾移除項或向數字添加項。
1 |
var colors = ['red','yello','blue'] |
可以通過 Array.isArray() 來判斷是不是數組
1 |
const arr = [1,2,3,4] |
所有的對象都具有 toLocaleString()
、 toString()
和 valueOf()
方法。
在這四個方法中,如果一個元素為 undefined 或 null,它會被轉換為空字符串。
valueOf()
返回對象的原始值,即數組本身
1 |
var a = [1,2,3,4] |
toString()
返回一個字符串,表示指定的數組和元素,用逗號相連。
1 |
var ab = [1,2,'3a','ab'] |
toLocaleString()
返回一個字符串表示數組中的元素。數組中的元素將使用各自的 toLocaleString() 方法轉成字符串,這些字符串將使用一個特定語言環境的字符串(例如一個逗號 “,”)隔開
1 |
const array1 = [1, 'a', new Date('21 Dec 1997 14:12:00 UTC')]; |
join()
將一個數組的所有元素連接成一個字符串並返回這個字符串。默認為 逗號(,)
1 |
var val = [1,2,3,4] |
push()
接受一個或多個參數,並將其添加到數組末尾,並返回修改後的數組長度。
1 |
var colors = ['red','yellow','blue'] |
pop()
刪除數組中的最後一個元素,並返回被刪除的元素值。
1 |
var colors = ["red", "yellow", "blue", "red", "black"] |
shift()
刪除數組中的第一個元素,並返回該元素。
1 |
var colors = ["red", "yellow", "blue", "red", "black"] |
unshift()
接受一個或多個參數,並將其添加到數組開頭,並返回修改後的數組長度。
1 |
var colors = ["blue", "red", "black"] |
reverse()
會反轉數組的順序,並返回新的數組。
1 |
var val = [1,2,3,4,5] |
sort()
會用 原地算法 對數組的元素進行排序,並返回數組。默認的排序會將元素轉為字符串,然後比較它們的 UTF-16代碼單元值序列時構建的
由於它一定具體實現,因此無法保證排序的時間和空間複雜性。
sort 會調用每個數組項的 toString() 轉型方法,然後比較得到的字符串。每個字符串由左到右進行對比。
1 |
|
sort([compareFunction])
可以接收一個比較函數作為參數,用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字符串的各個字符的Unicode位點進行排序
如果沒有指明 compareFunction ,那麼元素會按照轉換為的字符串的諸個字符的Unicode位點進行排序。例如 “Banana” 會被排列到 “cherry” 之前。當數字按由小到大排序時,9 出現在80 之前,但因為(沒有指明compareFunction),比較的數字會先被轉換為字符串,所以在Unicode順序上”80” 要比”9” 要靠前。
如果指明瞭 compareFunction ,那麼數組會按照調用該函數的返回值排序。即 a 和 b 是兩個將要被比較的元素:
以數字比較為例
1 |
var val4 = [1,21,3,10,8] |
concat()
基於當前數組中的所有項創建一個新數組。concat()
並不會修改原數組
這個方法會創建當前數組的一個副本,並把接收到的參數添加到副本的末尾。
concat方法創建一個新的數組,它由被調用的對像中的元素組成,每個參數的順序依次是該參數的元素(如果參數是數組)或參數本身(如果參數不是數組)。它不會遞歸到嵌套數組參數中。
concat方法不會改變this或任何作為參數提供的數組,而是返回一個淺拷貝,它包含與原始數組相結合的相同元素的副本。原始數組的元素將復製到新數組中,如下所示:
對象引用(而不是實際對象):concat將對象引用複製到新數組中。原始數組和新數組都引用相同的對象。也就是説,如果引用的對像被修改,則更改對於新數組和原始數組都是可見的。這包括也是數組的數組參數的元素。
數據類型如字符串,數字和布爾(不是String,Number 和 Boolean 對象):concat將字符串和數字的值複製到新數組中。
1 |
var val = [1,2,3,4] |
slice()
它能夠基於當前數組中的一個或多個項創建一個新數組。
slide(begin,end) 可以接受一個或兩個參數。這方法不會影響原始數組
一個參數
當只有一個參數時,會返回該參數從該參數指定位置開始到當前數組末尾的所有項
如果省略 begin,則 slice 從索引 0 開始。
如果 begin 超出原數組的索引範圍,則會返回空數組。
兩個參數
有兩個參數時,會返回起始和結束位置之間的項,但不包括結束位置的項。
如果 end 被省略,則 slice 會一直提取到原數組末尾。
如果 end 大於數組的長度,slice 也會一直提取到原數組末尾。
1 |
var val = ['a','b','c','d','e'] |
參數可能是負數,我們可以用數組長度加上該數來確認位置。 slice(-4,-1)
等同於 slice(1,4)
。
splice()
splice() 方法可以藉由刪除既有元素並/或加入新元素來改變一個陣列的內容。
其會返回被刪除的元素陣列,如沒有刪除,則返回空數組。
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
start:
陣列中要開始改動的元素索引(起始為 0)。若索引大於陣列長度,則實際開始的索引值會被設為陣列長度。若索引為負,則會從陣列中最後一個元素開始往前改動(起始為 -1)且若其絕對值大於陣列的長度,則會被設為 0。
deleteCount: 一個表示欲刪除的原陣列元素數量的整數。
若省略了 deleteCount
,或假如其值大於 array.length - start
(也就是 deleteCount
大於 start
算起的剩餘元素數量),則所有從 start
開始到陣列中最後一個元素都會被刪除。
若 deleteCount
為 0 或是負數,則不會有元素被刪除。 因此,你應該給定至少一個欲加入的新元素
item1, item2, …
從 start 開始,要加入到陣列的元素。 如果你沒有指定任何元素,則 splice() 只會依照 start 和 deleteCount 刪除陣列的元素。
1 |
// 刪除 |
1 |
// 插入 |
1 |
// 替換 |
indexOf()
和 lastIndexOf()
都接受兩個參數: 要查找的項 和 (可選)表示查找起點位置的索引。
返回值: 在陣列中找到的第一個元素索引值;沒找到則為 -1
indexOf()
是從數組的開頭向後查找。
lastIndexOf()
則從數組的末尾開始向前查找。
1 |
// indexOf() |
1 |
// lastIndexOf() |
這5個方法都接受2個參數
要在每一項運行的函數
函數會接受三個參數
【可選】運行該函數的作用域對象 - 影響 this 的值
every()
對數組中的每一項運行給定的函數,如果該函數對每一項都返回 true, 則返回 true。(全部都要返回 true)
1 |
|
some()
對數組中的每一項運行給定的函數,至少有一項是返回 true, 則返回 true。(只要一個返回 true)
1 |
var val = [1,2,3,4,5] |
filter()
利用指定的函數來返回數組中符合函數的數組元素。不會修改原數組。
1 |
// 返回大於 3 的元素 |
map()
返回一個數組,而這個數組的每一項都是在原始數組中對應項上運行傳入函數的結果。不會修改原數組。
1 |
// 返回一個數組 ,其每一項都是原數組對應項的值乘以 3 |
forEach()
它只是對數組中的每一項運行傳入的函數。這個數組沒有返回值。跟 for 循環本質一樣。
1 |
|
兩個方法都是接受兩個參數
用於處理每一個元素的函數 callback
該函數接受4個參數
【可選】initialValue 作為歸並基礎的初始值,如果沒有初始值,這數組的第一個元素將會作為初始值。
reduce()
將一個累加器及數組中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。
1 |
// 把數組的所有項從左到右相加 |
reduceRight()
將一個累加器及數組中每項元素(由右至左)傳入回呼函式,將陣列化為單一值。
1 |
// // 把數組的所有項從右到左相加 |
copyWithin()
方法會對數組的一部分進行淺拷貝至同一數組的另一位置並回傳此陣列,而不修改其大小。
返回被修改後的數組,原數組也會被修改。
arr.copyWithin(target, start, end)
target
要複製序列到這個位置的索引
如果是負數,target 從末尾開始算
如果 targrt 大於等於 arr.length, 則沒有項目被複製
【可選】start
開始複製的起始元素索引(起始為 0 )
【可選】end
結束複製的元素索引,會從 start 複製到 end, 但是不包括 end 的值
如果省略 end,將會一路複製到數組末項
1 |
var val = [1,2,3,4,5,6] |
會將數組中索引的第一個到最後一個的每個位置全部填入一個靜態的值。
arr.fill(value[, start[, end]])
value
想要插入的值
【可選】start
起始的位置,預設為 0
【可選】end
結束的位置,預設為 數組長度
注意:不包括 end 的位置
1 |
// 沒有 start 和 end,所以從 0 到數組的長度 |
find()
返回第一個滿足函數條件的元素值,否則返回 undefined
arr.find(callback[, thisArg])
接受 2 個參數 callback 和 thisArg
callback 函數
會處理數組每一個元素的函數,它接受三個參數
element
正被處理的函數
【可選】index
正被處理的函數索引
【可選】array
呼叫 find 方法的數組
【可選】thisArg
執行 callback 函式時被當作 this 的物件
1 |
// 返回符合 大於3 的第一個元素 |
findIndex()
返回第一個滿足函數條件的元素值索引,否則返回 -1
其與 find()
的區別在於,前者返回的元素值,後者返回的是元素值的索引值
arr.findIndex(callback[, thisArg])
接受 2 個參數 callback 和 thisArg
callback 函數
會處理數組每一個元素的函數,它接受三個參數
element
正被處理的函數
【可選】index
正被處理的函數索引
【可選】array
呼叫 find 方法的數組
【可選】thisArg
執行 callback 函式時被當作 this 的物件
1 |
// 返回符合 大於3 的第一個元素索引 |