整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JS正則表達(dá)式完整教程(二)「值得收藏」

          JS正則表達(dá)式完整教程(二)「值得收藏」

          者:前端藏經(jīng)閣

          轉(zhuǎn)發(fā)鏈接:https://www.yuque.com/xwifrr/qbgcq0/vkczro

          擊上方 "程序員小樂"關(guān)注, 星標(biāo)或置頂一起成長

          每天凌晨00點00分, 第一時間與你相約


          每日英文

          Sometimes being too nice is dangerous, you have to show your mean side once in a while to avoid getting hurt.

          有時候,太善良也是種危險。偶爾你也得厲害一點,才能免受傷害。


          每日掏心話

          做人不要太玻璃心,不要別人一條信息沒回,就覺得自己做錯了什么,不要被人一句”呵呵“,就覺得對方是討厭自己。玻璃心,想太多,什么事都對號入座,何必那么累。


          來自:Badd | 責(zé)編:樂樂

          鏈接:juejin.im/post/5cebb52651882530be7b16a4

          程序員小樂(ID:study_tech)第 789 次推文 圖片來自百度


          往日回顧:30 張圖帶你徹底理解紅黑樹


          正文


          對很多人來說,創(chuàng)建布局是前端開發(fā)領(lǐng)域中最難啃的骨頭之一。

          你肯定經(jīng)歷過耗費數(shù)個小時,換著花樣地嘗試所有可能起作用的 CSS 屬性、一遍遍地從 Stack Overflow 上復(fù)制粘貼代碼,寄希望于誤打誤撞地賭中那個能實現(xiàn)預(yù)期效果的魔幻組合。

          如果你的慣用策略就是按部就班地組合布局 —— 先把 A 元素放在這兒,好了,A 元素就位了,我再看怎么把 B 放在那兒 …… 那你沒有挫敗感才怪呢。CSS 的玩法可與 SKetch 或者 Photoshop 的玩法不一樣。

          在本文中,我將向你展示如何以統(tǒng)籌全局的思維實現(xiàn) CSS 布局,根治布局難產(chǎn)的頑疾。

          我們將用一個小案例貫穿全文,我會把所有的 CSS 代碼都解釋給你聽,因此即使你不知道或者忘記了 position 和 display 的用法,即使你分不清 align-items 和 justify-content 的區(qū)別,你仍會有所斬獲。

          而且我們會用純 HTML 和 CSS 代碼來演示,因此你不需要 React、Vue、Angular、CSS-in-JS 甚至是 JavaScript 方面的知識儲備。

          聽起來很棒吧?那就開始吧。

          布局小例子

          在本文中,我們要比照 Twitter 的推文組件自己仿寫一個:

          不論是一個像這樣的草圖,還是一個細(xì)節(jié)精美的原型圖,“有章可循” 總是個好主意。

          要避免一邊在腦海里設(shè)計,一邊在瀏覽器中七拼八湊地攢布局,這樣的開發(fā)過程才會更順暢。你當(dāng)然可以達(dá)到那種手腦合一的境界!但鑒于你還在乖乖地讀這篇文章,我可以假設(shè)你還沒有那么神通廣大。:)

          第一步:分而治之

          在動手敲代碼之前,我們先把布局的各個單元區(qū)分開來:

          在用 CSS 鋪排布局時,用行和列的形式去構(gòu)思大有裨益。因此,要么你把元素從上到下排列,要么從左到右排列。這種行和列的思路完美對應(yīng)了 CSS 中兩種布局技術(shù):Flexbox 和 Grid。

          當(dāng)然了,我們的示例布局并不是中規(guī)中矩的行列。它有一張圖片鑲嵌在左側(cè),其他元素排列在右側(cè)。

          第二步:沿著各個單元畫方框

          畫一些方框把這些元素框起來,看看行和列是否初具規(guī)模。我們把方向一致的單元歸到同一個方框中。

          在頁面中的 HTML 元素基本上都可視為矩形。當(dāng)然,有些元素有圓角,有些元素是圓形,或者是復(fù)雜的 SVG 形狀等。通常你看不到頁面上有一堆矩形。但你可以用矩形邊框的模式去分析它們。這樣的想象能幫你理解布局。

          之所以提到矩形,是因為你要把一系列元素對齊 —— 如第一行的用戶名、@handle(譯者注:handle 屬于專有名詞,指 Twitter 中的用戶 ID,所以在本文中保留不譯。詳見 www.urbandictionary.com/define.php?…)和時間以及最后一行的圖標(biāo) —— 把它們用方框包起來便于規(guī)劃。

          按目前的規(guī)劃,把布局用 HTML 代碼實現(xiàn)出來大概如下所示:

          <article>
          <img
          src="http://www.gravatar.com/avatar"
          alt="Name"
          />
          <div>
          <span>@handle</span>
          <span>Name</span>
          <span>3h ago</span>
          </div>
          <p>
          Some insightful message.
          </p>
          <ul>
          <li><button>Reply</button></li>
          <li><button>Retweet</button></li>
          <li><button>Like</button></li>
          <li><button>...</button></li>
          </ul></article>

          展示出的效果是這樣的(可以點擊這里調(diào)試代碼):

          這離我們想要的效果還遠(yuǎn)呢。但是!所有所需的內(nèi)容都齊全了。有些元素還以從左到右的順序排列。

          我們可以認(rèn)為,即使不用進(jìn)一步設(shè)置樣式,目前的布局效果也能達(dá)到網(wǎng)頁想表達(dá)的要點,這也是一個優(yōu)秀的 HTML 應(yīng)該達(dá)到檢查標(biāo)準(zhǔn)。

          關(guān)于語義化 HTML 的說明

          你可能會好奇,為何我選的是那些元素 —— article、p 等等。為何不都用 div 呢?

          為何要這樣寫:

          <article>
          <img ... />
          <div>
          <span/>
          <span/>
          <span/>
          </div>
          <p> ... </p>
          <ul>
          <li>
          <button> ... </button>
          </li>
          </ul></article>

          而不這樣寫?

          <div>
          <img ... />
          <div>
          <div/>
          <div/>
          <div/>
          </div>
          <div> ... </div>
          <div>
          <button> ... </button>
          </div></div>

          其實,每個 HTML 元素的名稱都有其特定含義,在不同場景中恰如其分地使用語義上與它們所表示的內(nèi)容匹配的元素,是很好的語義化實踐。

          這種寫法,首先,有助于開發(fā)者理解代碼;其次,對使用屏幕閱讀器等輔助設(shè)備的用戶比較友好。同時這樣用標(biāo)簽也有利于 SEO —— 搜索引擎會試著理解這個頁面的含義,以便于顯示相關(guān)廣告來盈利、幫助搜索者找到滿意結(jié)果。

          article 標(biāo)簽代表文章類內(nèi)容,而你可以認(rèn)為推文這種東西有點類似于一篇文章。

          p 標(biāo)簽代表段落,而推文的內(nèi)容文本有點類似于一個段落。

          ul 標(biāo)簽代表無序列表(與有序列表或數(shù)字序號列表相對應(yīng)),在本示例中,你可以用它來存放列表信息。

          我們無法用只言片語就說清楚 HTML 元素的語義,以及何種情況用何種標(biāo)簽。但大多數(shù)情況下,一個語義化元素即使其語義再不貼切,也比用 div 強(qiáng),div 標(biāo)簽只代表 “一塊區(qū)域”。

          元素的默認(rèn)樣式

          是什么決定了元素的樣式?為什么有的元素獨占一行,而有的元素能共處一行?

          這要歸因于元素的默認(rèn)樣式,這其中就有我們要探討的第一個 CSS 知識點:行內(nèi)元素和塊級元素。

          行內(nèi)元素們肩并肩擠在一行里(就像句子中的詞一樣,必要時會折行)。根據(jù)再瀏覽器中的默認(rèn)樣式劃分,span、button 以及 img 都是行內(nèi)元素。

          而塊級元素,總是踽踽獨行。以控制臺輸出的方式去理解,你可以認(rèn)為塊級元素前后各有一個換行符 \n。就好像console.log(“\ndiv\n”)。article、div、li、ul 以及 p 標(biāo)簽都是塊級元素。

          注意,在上面的例子中,為什么即使 img 標(biāo)簽是行內(nèi)元素,頭像圖片依然獨占一行?因為它下方的 div 是塊級元素。

          然后要注意,為什么 @handle、用戶名和時間都在同一行?原因是它們都在 span 標(biāo)簽中,而 span 是行內(nèi)元素。

          這三個 span 和 文字 “insightful message” 處于不同行,因為(a)它們被包在一個 div 中,div 后面自然要另起一行;(b)p 標(biāo)簽同樣是塊級元素,它自然從新行開始排列。(之所有沒有出現(xiàn)兩個空行,是因為 HTML 合并了相鄰的空行,與相鄰空格同理。)

          如果你再看得仔細(xì)點,你會發(fā)現(xiàn) “insightful message” 的上下方空間,要比頭像圖片以及 handle、用戶名、時間的上下方空間要大。此空間的大小也由默認(rèn)樣式控制:p 標(biāo)簽的頂部和底部都有 margin。

          你也會注意到按鈕列表的圓點,以及列表的縮進(jìn)行為。這些也都是默認(rèn)樣式。我們馬上就要修改這些默認(rèn)樣式了。

          第三步:再畫一些方框

          我們想把頭像圖片放在左側(cè),其余元素放在右側(cè)。你可能會根據(jù)剛剛探討的行內(nèi)和塊級知識來推斷,認(rèn)為只要把右側(cè)的元素都包裹到一個如 span 標(biāo)簽般的行內(nèi)元素中,就完事大吉了。

          但這是行不通的。行內(nèi)元素并不能阻止其內(nèi)部的塊級元素另起一行。

          為了把這些元素收拾得服服帖帖,我們需要用一些更強(qiáng)大的技術(shù),比如 Flexbox 或者 Grid 布局。這次我們選用 Flexbox 來解決。

          Flexbox 的原理

          CSS 的 Flex 布局能夠把元素以行或者列的形式排布。這是一種單向的布局系統(tǒng)。為了實現(xiàn)交叉的行和列(正如推文組件的設(shè)計那樣),我們需要添加一些容器元素來扭轉(zhuǎn)方向。

          你可以在容器上設(shè)置 display: flex; 來啟用 Flex 布局。容器本身是塊級元素(得以獨占一行),其內(nèi)部元素會成為 “Flex 子項” —— 即它們不再是行內(nèi)或塊級元素了;它們都受 Flex 容器控制。

          在本例中,我們會設(shè)置一些嵌套的 Flex 容器,讓該成行的成行,該成列的成列。

          我們把外層容器(綠色方框)設(shè)置為列,藍(lán)色方框設(shè)置為行,而紅色方框中的元素排布在列中。

          為何選 Flexbox 布局,不選 Grid 布局?

          由于一些原因,我決定用 Flexbox 布局而不用 Grid 布局。我覺得 Flexbox 布局更易于學(xué)習(xí),也更適用于輕量級的布局。當(dāng)布局中主要是行或者主要是列時,F(xiàn)lexbox 布局的表現(xiàn)更出色。

          另一個重點就是,即使 Grid 布局比 Flexbox 布局年輕,前者也撼動不了后者的地位。它們各自適用于不同的場景,對于二者,我們都要學(xué)習(xí),技不壓身。有些情況你甚至?xí)瑫r使用二者 —— 例如 Grid 布局排布整體頁面,而 Flexbox 布局調(diào)控頁面中的一個表單。

          沒錯沒錯,在 Web 開發(fā)的世界,普遍的更替法則是后浪推前浪,但 CSS 并不如此。Flexbox 和 Grid 能夠和諧共存。

          用 CSS 解決問題,條條大路通羅馬!

          第四步:應(yīng)用 Flexbox

          好了,既然我們已經(jīng)打定主意,那就開動吧。我把左側(cè)元素包進(jìn)一個 div,并給元素們設(shè)置類名,便于應(yīng)用 CSS 選擇器。

          <article class="tweet">
          <img
          class="avatar"
          src="http://www.gravatar.com/avatar"
          alt="Name"
          />
          <div class="content">
          <div class="author-meta">
          <span class="handle">@handle</span>
          <span class="name">Name</span>
          <span class="time">3h ago</span>
          </div>
          <p>
          Some insightful message.
          </p>
          <ul class="actions">
          <li><button>Reply</button></li>
          <li><button>Retweet</button></li>
          <li><button>Like</button></li>
          <li><button>...</button></li>
          </ul>
          </div></article>

          看著好像沒有變化。

          這是因為 div 作為塊級元素(如果沒有空行就引入一個)是看不見的。當(dāng)你需要一個包裹其他元素的容器,除了 div 之外沒有更貼合語義的選擇了。

          下面咱們的第一段 CSS 代碼,我們會把它放在 HTML 文檔中 head 標(biāo)簽的 style 里:

          .tweet {
          display: flex;}

          干得漂亮!我們用類選擇器鎖定了所有類名為 tweet 的元素。當(dāng)然目前只有一個這樣的元素,但如果有十個,那它們將都會是 Flex 容器了。

          CSS 中以 . 開頭的選擇器代表類選擇器。為什么是 .?我可不知道。你只要記住這條規(guī)則就行了。

          現(xiàn)在文字內(nèi)容都到頭像右側(cè)去了。問題是頭像圖片都扭曲變形了。

          因為 Flex 容器會默認(rèn):


          • 把子項排成一行;

          • 讓子項與其內(nèi)容等寬,并 ——

          • 把所有子項的高度拉平為最高子項的高度。


          我們可以用 align-items 屬性來控制垂直方向的對齊方式。

          .tweet {
          display: flex;
          align-items: flex-start;}

          align-items 的默認(rèn)值是 stretch,而將其設(shè)為 flex-start 后,會讓子項沿著容器頂部對齊,并且讓子項保持各自的高度。

          方向的辯證:行還是列?

          另外,F(xiàn)lex 容器的默認(rèn)排列方向是 flex-direction: row;。是的,這個方向是 “行”,即使我們可能感覺那更像是兩列。要把它想成是子項們排成一行,這樣理解就舒服多了。

          有點像這張花瓶的圖片,或者說兩張臉的圖片。橫看成嶺側(cè)成峰。

          給文字內(nèi)容更多的空間

          Flex 布局的子項僅取其所需寬度,但我們需要 content 區(qū)域盡量寬敞一些。

          因此,我們要給 content 這個 div 設(shè)置 flex: 1; 屬性。(該 div 有類名,那我們就又可以用類選擇器啦!)

          .content {
          flex: 1;}

          我們也要給頭像設(shè)置 margin,好在頭像和文字之間加點空隙:

          .avatar {
          margin-right: 10px;}

          看起來順眼一些了吧!

          margin 和 padding

          那…… 為什么用 margin 而不用 padding?為什么要設(shè)置在頭像右側(cè),而不是文字內(nèi)容左側(cè)呢?

          這是一條約定俗成的規(guī)則:在元素右側(cè)和下方設(shè)置 margin,不去碰左側(cè)和上方的 margin。

          至少是在英文界面的布局中,文檔流的方向是從左到右、從上到下的,因此,每個元素都 “依賴” 其左側(cè)和上方的元素。

          在 CSS 中,每個元素的定位都受到其左側(cè)和上方的元素的影響。(至少在你遇見 position: absolute 那幫家伙之前是這樣的。)

          SoC 原則(Separation of Concerns)

          從技術(shù)實現(xiàn)的角度來說,怎樣設(shè)置 avatar 和 content 之間的空隙都一樣。該是多寬就是多寬,沒有 border 的干擾(padding 在 border 的內(nèi)側(cè);而 margin 在外側(cè))。

          但當(dāng)事關(guān)可維護(hù)性、對元素的全局觀時,這就有區(qū)別了。

          我曾嘗試把元素理解為一個個獨立個體,就像每個 JavaScript 函數(shù)只實現(xiàn)單一功能一樣:如果它們都僅僅扮演單一的角色,那么寫起代碼來就很容易,報錯時調(diào)試也很容易。

          如果我們把 margin 設(shè)置到 content 的左側(cè),后來有一天我們?nèi)サ袅?avatar,可是以前的縫隙還留在那。我們還得排查導(dǎo)致額外空間的原因(是來自 tweet 容器嗎?還是來自 content 呢?)并把它處理掉。
          或者,如果 content 設(shè)置了左側(cè)的 margin,而我們想要把 content 替換成別的元素,我們還要記著再把之前那個空隙補(bǔ)上。

          好了好了,為了 10 像素的事,沒必要費這么多口舌,干脆就把 margin 設(shè)在頭像的右側(cè)和下方。讓我們繼續(xù)埋頭敲代碼吧。

          移除列表的樣式

          無序列表 ul 和其中的列表項 li 在左側(cè)窩藏了很大空間,還有一些圓點。這都不是我們想要的效果。
          我們可以把無序列表左側(cè)的空隙都清除掉。我們還要把它變成一個 Flex 容器,這樣里面的按鈕就能排成一行了(用 flex-direction: row)。

          列表項有個屬性是 list-style-type,默認(rèn)值為 disc,使得每個列表項以圓點開頭,我們用 list-style: none; (list-style 是一個縮寫屬性,整合了幾個其他屬性,其中就包括 list-style-type)將該效果關(guān)閉。

          .actions {
          display: flex;
          padding: 0;}.actions li {
          list-style: none;}

          .actions 又是一個類選擇器。原汁原味。

          而 .actions li 選擇器,意即 “actions 類元素中所有的 li 元素”。它是類選擇器和元素選擇器的結(jié)合。

          復(fù)合選擇器中用以分隔的空格代表著選擇范圍的縮小。事實上,CSS 是以倒序讀取選擇器的。其過程是 “先找到頁面中所有的 li,然后在這些 li 中找到類名是 actions 的那些”。但無論你用正序還是倒序的方式去理解,結(jié)果都是一樣的。(在 StackOverflow 查看更多詳解)

          橫排按鈕

          要橫排按鈕有好幾種方式。

          一種就是設(shè)置 Flex 子項的對齊方式。你應(yīng)該對設(shè)置對齊方式很熟悉,每個富文本編輯器頂部都有這種功能的按鈕:

          它們把文本進(jìn)行左對齊、居中對齊、右對齊以及 “兩端對齊”,也就是鋪滿整行。

          在 Flexbox 布局中,你可以用 justify-content 屬性來實現(xiàn)對齊。設(shè)置了 flex-direction: row(默認(rèn)值,也是本文中一直在用的設(shè)置)后,可以通過 justify-content 把子項進(jìn)行或左或右地對齊。justify-content 的默認(rèn)值為 flex-start(因此所有元素都向左看齊)。如果我們給 .actions 元素設(shè)置 justify-content: space-between,它們就會均勻地鋪滿整行,就像這樣:

          可我們想要的不是這樣的效果。如果這幾個按鈕可以不占滿整行會更好。所以得換一種方式。

          這次,我們給每個列表項設(shè)置一個右側(cè)的 margin,把它們分隔開來。還要給整個推文組件設(shè)置一個邊框,以便我們能夠直觀地衡量效果。用 1px solid #ccc 設(shè)置一個 1 像素寬的灰色實線邊框。

          .tweet {
          display: flex;
          align-items: flex-start;
          border: 1px solid #ccc;}.actions li {
          list-style: none;
          margin-right: 30px;}

          現(xiàn)在效果如下:

          按鈕的排列看起來優(yōu)雅多了,但灰色邊框告訴我們,所有元素都過于靠左了。還是用 padding 分配點空間吧。

          .tweet {
          display: flex;
          align-items: flex-start;
          border: 1px solid #ccc;
          padding: 10px;}

          現(xiàn)在推文組件有內(nèi)邊距了,但有些地方還是很空。如果我們用瀏覽器調(diào)試工具將元素高亮顯示,就會發(fā)現(xiàn) p 和 ul 元素有默認(rèn)的上下 margin(在 Chrome 的調(diào)試工具中,margin 以橙色顯示,而 padding 以綠色顯示):

          還有一處有意思的細(xì)節(jié);行與行之間的上下 margin 是等距的 —— 并沒有疊加出雙倍間距!因為 CSS 在豎直方向上有 margin 坍塌現(xiàn)象。當(dāng)上下兩個 margin 短兵相接時,數(shù)值大的 margin 會 “吃掉” 小的。詳情參見 CSS 技巧:margin 坍塌。

          對于本例的布局,我會手動調(diào)整 .author-meta、p 和 ul 的右側(cè) margin。如果要真刀真槍地開發(fā)網(wǎng)站,建議你考慮用 CSS reset 作為開發(fā)基礎(chǔ),有利于跨瀏覽器兼容。

          p, ul {
          margin: 0;}.author-meta, p {
          margin-bottom: 1em;}

          用 , 將選擇器隔開,可以一次性把樣式應(yīng)用到多個選擇器上。因此 p , ul 的含義就是 “所有的 p 元素,以及所有的 ul 元素”。亦即二者的合集。

          在這里我們使用了新的尺寸單位,1em 中的 em。一個單位的 em 等于 body 標(biāo)簽上的以像素為單位的字號大小。body 標(biāo)簽的默認(rèn)字號為 16px(16 像素高),所以本例中的 1em 相當(dāng)于 16px。em 隨字號改變而改變,因此可以用 1em 來表達(dá) “我想讓文字下方的 margin 和文字的高度一樣,不論文字高度是多少”。
          現(xiàn)在的效果如下:

          現(xiàn)在讓我們把圖片縮小一些,并將其設(shè)置為圓形。我們將其寬高設(shè)置為 48 像素,正和 Twitter 的頭像寬高一樣。

          .avatar {
          margin-right: 10px;
          width: 48px;
          border-radius: 50%;}

          我們用 border-radius 屬性來設(shè)置圓角,有好幾種方式來定義該屬性的值。如果你想要小圓角效果,可以用帶 px、em 或其他單位名稱的數(shù)字賦值。例如 border-radius: 5px 的效果:

          如果將 border-radius 設(shè)為寬和高的一半(在本例中即為 24 像素),其效果就是一個圓形。但更方便的寫法是 border-radius:50%,這樣我們就不必知道具體尺寸,CSS 會計算出確切結(jié)果。甚至,如果以后寬高值變了,也無需重新修改屬性值了!

          再接再厲

          眼下還有一些需要潤色之處。

          我們要把字體設(shè)為 Helvetica(Twitter 用的那一款)、把字號縮小一些、把用戶名加粗,還有,翻轉(zhuǎn) “@handle 用戶名 的順序(在 HTML 代碼中),使之與 Twitter 一模一樣。:D

          .tweet {
          display: flex;
          align-items: flex-start;
          border: 1px solid #ccc;
          padding: 10px;
          /*
          更改字體和字號。
          在 .tweet 選擇器上設(shè)置的 CSS 效果,其所有子元素都會繼承。
          (除了按鈕。按鈕不太合群)
          */
          font-family: Helvetica, Arial, sans-serif;
          font-size: 14px;}.name {
          font-weight: 600;}.handle,.time {
          color: #657786;}

          font-weight: 600; 的效果等同于 font-weight: bold;。字體有很多不同程度的字重,范圍是從 100 到 900(最淡到最濃)。normal(默認(rèn)值)等價于 400。

          另外,CSS 中的注釋寫法與 JavaScript 或其他語言不用,不允許以 // 開頭。某些瀏覽器支持 // 風(fēng)格的 CSS 注釋,但并非所有瀏覽器都如此。用 C 語言風(fēng)格的 / / 包圍注釋內(nèi)容即可高枕無憂。

          還有一個小竅門:可以用 偽元素在 “handle” 與 “時間” 之間添加一個凸點。這個凸點符號單純?yōu)榱搜b飾,不具有具體語義,所以用 CSS 實現(xiàn)不會污染 HTML 語義結(jié)構(gòu)。

          .handle::after {
          content: " > content: " \00b7";}<>

          ::after 創(chuàng)建了一個偽元素,它位于 .handle 元素內(nèi)部的最后方(“落后” 于元素的內(nèi)容)。你還可以用 ::before 創(chuàng)建偽元素。可以給 content 屬性賦值任何文字內(nèi)容,包括 Unicode 字符。你可以恣意發(fā)揮,像給任何其他元素設(shè)置樣式一樣。偽元素用來實現(xiàn)標(biāo)記(badge)、消息提醒或其他小花樣最合適不過了。

          圖標(biāo)按鈕

          還有一項工作要做,那就是用圖標(biāo)替換按鈕。我們要在 head 標(biāo)簽里添加 Font Awesome 圖標(biāo)字體:

          <link
          rel="stylesheet"

          integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
          crossorigin="anonymous"/>

          然后用下列代碼替換原來的 ul,新列表中的每個按鈕里有圖標(biāo)和隱藏文字:

          <ul class="actions">
          <li>
          <button>
          <i
          class="fas fa-reply"
          aria-hidden="true"
          ></i>
          <span class="sr-only">Reply</span>
          </button>
          </li>
          <li>
          <button>
          <i
          class="fas fa-retweet"
          aria-hidden="true"
          ></i>
          <span class="sr-only">Retweet</span>
          </button>
          </li>
          <li>
          <button>
          <i
          class="fas fa-heart"
          aria-hidden="true"
          ></i>
          <span class="sr-only">Like</span>
          </button>
          </li>
          <li>
          <button>
          <span aria-hidden="true">...</span>
          <span class="sr-only">More Actions</span>
          </button>
          </li></ul>

          Font Awesome 是一款圖標(biāo)字體,它配合斜體標(biāo)簽 i 可以展示圖標(biāo)。正因為它是字體,那些可以用于文字的 CSS 屬性(例如 color 和 font-size)都適用于圖標(biāo)字體。

          我們在這兒做了些微調(diào),來提升按鈕的可訪問性:


          • 特性 aria-hidden=”true” 使屏幕閱讀器忽略此圖標(biāo)。

          • sr-only 類是 Font Awesome 內(nèi)置的類。它讓元素在你眼前隱身,但屏幕閱讀器能讀取到它。


          現(xiàn)在我們將要給按鈕添加一些樣式 —— 移除邊框、上色以及加大字號。還要設(shè)置 cursor: pointer,把鼠標(biāo)光標(biāo)變成 “手” 型,就像超鏈接的效果那樣。最后,用 .actions button:hover 選擇處于 hover 狀態(tài)的按鈕,把它們變成藍(lán)色。

          .actions button {
          border: none;
          color: #657786;
          font-size: 16px;
          cursor: pointer;}.actions button:hover {
          color: #1da1f2;}

          下面就是推文組件光芒四射的最終效果:

          如何精進(jìn) CSS 水平

          最能提高 CSS 水平的就是實踐。

          仿寫你喜歡的網(wǎng)站。設(shè)計者和藝術(shù)家稱其為 “臨摹”。我寫過一篇用臨摹的方法學(xué) React,其中的原則也適用于 CSS。

          選一些有意思的、你覺得難度大的樣式效果。用 HTML 和 CSS 臨摹該效果。如果卡殼了,用瀏覽器的調(diào)試工具看看原網(wǎng)站的效果是如何實現(xiàn)的。“栽秧苗、腿跟上、抬頭看看直不直。” :)

          歡迎在留言區(qū)留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發(fā),學(xué)習(xí)能力的提升上有新的認(rèn)識,歡迎轉(zhuǎn)發(fā)分享給更多人。


          猜你還想看


          阿里、騰訊、百度、華為、京東最新面試題匯集

          微服務(wù)的生離死別,看這篇就對了!

          Java中的對象都是在堆上分配的嗎?

          在Spring Boot項目中整合使用Activiti

          關(guān)注訂閱號「程序員小樂」,收看更多精彩內(nèi)容
          嘿,你在看嗎?

          . forObject

          此代碼片段遍歷對象的每個屬性,并分別為每個屬性迭代一個回調(diào)。

          const forObject=(obj, callback)=>
              Object.keys(obj).forEach((key)=> callback(obj[key], key, obj));
          
          const testObj={
              title: "每天學(xué)習(xí)10個實用Javascript代碼片段(一)",
              author: "天行無忌",
          };
          forObject(testObj, (val, key)=> {
              console.log(`${key}:${val}`);
          });
          // title:每天學(xué)習(xí)10個實用Javascript代碼片段(一)
          // author:天行無忌
          

          2. forReverse

          此代碼片段倒序遍歷數(shù)組,即從數(shù)組的最后一個元素開始向前遍歷數(shù)組的每個元素并執(zhí)行一個回調(diào)函數(shù)。

          const forReverse=(array, callback)=>
              array.slice(0).reverse().forEach(callback);
          
          const testArray=[1, 2, 3, 4];
          forReverse(testArray, (val)=> console.log(val));
          
          // 4
          // 3
          // 2
          // 1
          

          3. flatten

          此代碼片段使用遞歸將數(shù)組展平到指定的深度,ES6中有現(xiàn)成的函數(shù)可以實現(xiàn),在這里有介紹《7 個你應(yīng)該掌握的 JavaScript 編碼技巧》。

          const flatten=(array, depth=1)=>
              array.reduce(
                  (acc, current)=>
                      acc.concat(
                          depth > 1 && Array.isArray(current)
                              ? flatten(current, depth - 1)
                              : current
                      ),
                  []
              );
          const arrayTest=[0, 1, 2, [[[3, 4, [5]]]]];
          
          console.log(flatten(arrayTest)); // [ 0, 1, 2, [ [ 3, 4, [Array] ] ] ]
          console.log(arrayTest.flat()); // [ 0, 1, 2, [ [ 3, 4, [Array] ] ] ]
          
          const depth=3;
          console.log(flatten(arrayTest, depth)); // [ 0, 1, 2, 3, 4, [ 5 ] ]
          console.log(arrayTest.flat(depth)); // [ 0, 1, 2, 3, 4, [ 5 ] ]
          

          4. deepFlatten

          此代碼片段使用遞歸將數(shù)組全部展平,和上面的函數(shù)相比,此函數(shù)無需指定深度,全部展平。

          const deepFlatten=(array)=>
              [].concat(
                  ...array.map((item)=> (Array.isArray(item) ? deepFlatten(item) : item))
              );
          
          const arrayTest=[0, 1, 2, [[[3, 4, [5]]]]];
          console.log(deepFlatten(arrayTest)); // [ 0, 1, 2, 3, 4, 5 ]
          

          5. findKey

          此代碼片段通過鍵值查找對象,返回滿足給定函數(shù)的第一個 key

          const findKey=(obj, fn)=>
              Object.keys(obj).find((key)=> fn(obj[key], key, obj));
          
          const testObj={
              hballard: { age: 36 },
              sguzman: { age: 40 },
              plowe: { age: 32 },
          };
          
          console.log(findKey(testObj, (item)=> item.age > 32)); // hballard
          

          6. filterDuplicate

          此代碼片段過濾數(shù)組中的重復(fù)項,這是 Set 比較經(jīng)典的使用場景。關(guān)于 Set 的使用可以參閱《JavaScript中的Set數(shù)據(jù)操作:交集、差集、交集、對稱差集》。

          const filterDuplicate=(arr)=> [...new Set(arr)];
          const testArray=[1, 3, 4, 5, 5, 5, 6, 2, 9];
          console.log(filterDuplicate(testArray)); // [1, 3, 4, 5, 6, 2, 9]
          

          7. dropWhile

          此代碼片段從數(shù)組中刪除元素,直到傳遞的函數(shù)返回 true 。即從數(shù)組第一個元素開始刪除,直到刪除的元素滿足函數(shù)返回 true 就停止。

          const dropWhile=(array, fn)=> {
              while (array.length > 0 && !fn(array[0])) array=array.slice(1);
              return array;
          };
          const testArray=[30, 29, 33, 31, 28];
          
          console.log(dropWhile(testArray, (item)=> item >=33)); // [ 33, 31, 28 ]
          

          8. digitize

          此代碼片段將數(shù)字拆分為單個數(shù)字組成的數(shù)組,這個是擴(kuò)展運算符 ... 的比較經(jīng)典的使用方法。更多擴(kuò)展運算符的使用請參閱《ES6中擴(kuò)展運算符的8種用法》

          const digitize=(number)=> [...`${number}`].map((item)=> parseInt(item));
          
          console.log(digitize(2021)); // [ 2, 0, 2, 1 ]
          

          9 .differenceWith

          此代碼片段刪除了比較器函數(shù)返回為 false 的值,其實也可以用來求兩個數(shù)組的差集。

          const differenceWith=(array1, array2, comp)=>
              array1.filter((a)=> array2.findIndex((b)=> comp(a, b))===-1);
          const a1=[1, 2, 3, 4];
          const a2=[3, 4, 5, 6];
          console.log(differenceWith(a1, a2, (a, b)=> a===b)); // [ 1, 2 ]
          

          10. defer

          此代碼片段將延遲函數(shù)的執(zhí)行,直到當(dāng)前調(diào)用堆棧全部執(zhí)行完畢。


          主站蜘蛛池模板: 亚洲AV无码一区二区三区牛牛| 精品一区二区三区高清免费观看| 国产成人无码精品一区二区三区 | 国产亚洲一区二区三区在线| 国产精品熟女视频一区二区| 无码人妻视频一区二区三区| 久久久久久人妻一区精品| 伊人色综合一区二区三区| 日韩人妻无码一区二区三区| 国产免费一区二区视频| 国产区精品一区二区不卡中文| 自慰无码一区二区三区| 日韩电影一区二区三区| 国产午夜精品一区理论片| 老熟妇仑乱视频一区二区 | 精品无码一区二区三区电影| 亚洲一区在线免费观看| 亚洲国产欧美国产综合一区| 在线电影一区二区三区| 视频一区二区三区在线观看| 精品成人一区二区三区四区| 中文字幕色AV一区二区三区| 在线播放国产一区二区三区| 国产乱码精品一区二区三区中| 色一情一乱一区二区三区啪啪高| 冲田杏梨AV一区二区三区| 国产人妖视频一区在线观看| 亚洲国产综合精品中文第一区| 久久青草精品一区二区三区| 蜜臀Av午夜一区二区三区| 亚洲国产AV无码一区二区三区| 精品国产一区二区三区AV | 人成精品视频三区二区一区| 国精产品一区二区三区糖心| 一区二区三区视频在线观看| 麻豆精品人妻一区二区三区蜜桃| 国产一区二区三区无码免费| 日韩精品无码一区二区视频| 精品无码一区二区三区在线| 天天看高清无码一区二区三区| 国模吧一区二区三区|