從 CSS sprite 進化到 SVG sprite

很久沒寫文章了,今天想跟大家分享 CSS sprite、Web icon font,以及 SVG sprite 這幾個東西的使用經驗。

這三個東西,雖然看似毫無關聯,但隱隱約約還是有種「進化」的感覺,如果你還在使用 CSS sprite 的技術,歡迎參考一下這篇文章,試著玩玩 Icon font 或 SVG sprite,瞭解並感受一下他們的特別之處吧 😄

CSS Sprite

當我們瞭解到每讀取一張圖,就會佔用一個 HTTP 需求時,我們改用 CSS sprite。
我們將所有網站會用到的 icon,全部集合起來放在同一張圖片裡,利用 class 再搭配 background-position 幫圖片做定位,就做到了 CSS sprite 的技術啦。

圖片取自 smashingmagazine

雖然可以有效減少 HTTP 需求,但他終究是圖片,只要把網站等比放大,圖片就可能會失真。在現今螢幕解析度提高,以及 RWD 網站盛行的環境下,用 CSS sprite 要面對的可能就是這種失真的小瑕疵。

另外一個比較惱人的困擾,就是要把所有的 icon 排在同一張圖片,再自己算出定位,其實很麻煩。雖然可以使用 compass 這樣的 CSS 預處理器幫忙,但也不是所有人都用 compass 啊 😊。


Web Icon Font

因為種種的因素,我們改用了另外一個技術:Web Icon Font (以下簡稱 icon font),我們利用一些字體文件,將文字轉成圖片。好處是解決了「失真」的困擾,因為即使放大縮小,它的本質還是文字,文字放大縮小是不會失真的,可以保持它原有的清晰度。

但困擾來了,正因為他是文字,所以必須乖乖遵守文字的規範,我們常碰到的問題就是在「鋸齒」與「抗拒齒」之間徘徊,通常瀏覽器都會替文字進行抗拒齒的優化,以免放大閱讀文字時,會有凹凸不平的鋸齒狀,有的時候,某些圖標我們需要這些鋸齒,但另外一些圖片我們需要抗鋸齒,線段類的圖案、圓弧狀的圖案 … 等等,會依照不同的樣式有不同的需求。

而且除了瀏覽器外,不同系統 (WIN, iOS)針對文字的抗拒齒演算法也不同,如果真的要錙銖必較的去調校,應該會調整的天荒地老。

當然,這篇文章不是要一味地告訴大家 Icon Font 的缺點,畢竟我自己也還在用 Icon Font XDD。

這種細微的的改變,一般肉眼看不太出來,而且在解析度較高的裝置觀看,這問題才會比較明顯。如果真的發生類似的問題,我們可以用font-smooth去調整:

CSS
CSS

但誠如 MDN 說的: this is non-standard and should not be used. (他們不是標準格式,不推薦使用在專案上)。

因此,如果真的有這類問題需要解決,我們可以改使用 SVG sprite。 Icon font 還有其他不方便的地方,例如受到font-size, line-height..等等字型屬性的限制。一次要載入上百張 Icon font 的字型檔,但實際上用到的只是那幾張小圖,浪費了讀取的時間。最後還有一點是各家的 Icon font 整合不易.. 等。 當然還是有一些網站服務可以解決部分問題,所以這邊只是把會碰到的狀況列出來,就不再細談了。


SVG sprite

在介紹 Icon font 文末提到有「網站服務」可解決部分問題,而這個網站也是我要介紹給大家的,就是 IcoMoon,他是一個整合眾家 Icon font 的網站,此外也支援 SVG 匯出。

該如何使用它?這邊不再贅述,我們只談 SVG sprite 的功能。

怎麼使用 SVG

在講 SVG sprite 之前,還是先簡單講一下什麼是 SVG 吧 XDDD。其實對我而言,SVG 的定義很簡單,就是用程式碼畫圖,這句話傳達了兩個意思:一、你必須要寫程式碼;二、他是不會失真的向量圖。

透過以上範例,你會發現這張圖片所有的線段(<path></path>)都是寫在 HTML 裡面,然後再利用 CSS 屬性去修改它的顏色、大小… 等樣式。

每一張圖片都有一個自己的<path></path>或者<circle></circle> … 這樣的屬性,通常會寫在網頁的最上方,再利用<use xlink:href="#icon-video-camera"></use>呼叫他。

雖然使用 SVG 可以有效解決解析度、鋸齒 … 等等這些問題,但參考我們上述語法,應該會發現,如果要載入多張不同的圖片,程式碼會拖得很長。為了解決這個問題,我們可以改用 SVG sprite,也就是將所有圖片存在 SVG 檔案,再從 HTML 呼叫他。

SVG sprite 實作

以 IcoMoon 網站為例,先選好你要的圖片,在匯出 SVG 之前勾選 Include Tiles (CSS Sprite)

解壓縮之後,找到sprite/目錄,裡面有一個sprite.svg,原理就跟 sprite.png 一樣,會把所有圖案排列整齊,差別在於它是向量圖,放大縮小都不會失真。

接下來只要在 HTML 載入這張 SVG 檔案,並且透過ID去呼叫對應的 icon 就可以了。

HTML

xlink:href的地方,就輸入這個 svg 檔案的相對路徑,後面再寫 ID 即可,跟 CSS sprite 相比是不是簡單很多呢。我們不需要再寫background-position去調整他的位子,往後要新增其他的 icon,直接打開 sprite.svg 編輯就可以啦!

因為 svg 目前不支援絕對路徑,所以我沒辦法直接放在 codepen 讓大家看,因此另外做了一份頁面,請參考 🌍 範例網頁觀看效果,也歡迎使用 dev tools 玩玩看。

➡️ 範例:SVG sprite HTML demo

使用 IcoMoon 的 SVG sprite 注意事項

因為 IcoMoon 可以直接提供我們 SVG 的 path 程式碼,而且可以個別匯出,所以我用 IcoMoon 舉例。但如果你以後想用 IcoMoon 做 SVG sprite,請特別注意一件事情,就是你可能需要自行修改它的 SVG 檔案。

什麼意思呢?因為 IcoMoon 把 icon 的顏色、大小都寫死在 SVG 檔案裡,而且我覺得不是很好管理。

icon-facebook為例,IcoMoon 是這樣寫的:

HTML

以下是我修改後的語法:

HTML

你可以發現我改用 <symbol></symbol> 管理 icon,並且移除了他們固定的樣式。

如果不把 IcoMoon 寫的樣式移除,我們將無法用 CSS 控制這些樣式,所以請特別記住這一點!

我也有把 IcoMoon 跟我修改後的 SVG 檔案放到網站上,大家可以自行打開原始碼比對。

以上跟大家介紹 SVG sprite 的使用方法,以及該怎麼管理。希望對大家有所幫助囉

初探 Sass Maps 與使用介紹

Sass Maps 是 Sass 3.3 版的新東西,我們可以利用它更有效的管理我們的變數;如果再搭配 if/else 條件式或 each 迴圈,可以寫出更簡單(也更程式導向) 的 CSS 語法。

雖然 Maps 有地圖或索引的意思,但你不妨把它想成是 JavaScript 的物件,這樣在觀念與使用上會比較接得起來 😊 ~

以往我們用 Sass 設定變數時,會用各種單字取名。通常會用這種比較沒有系統的寫法:

CSS

以上這些變數單拆開來,可能都看得懂。但真的要使用時,通常都要回頭翻閱;另外一個問題就是變數愈多管理愈不易。

所以我們可以利用 SASS Maps 幫我們解決這樣的問題。

Sass Maps 基本介紹

Sass Maps 的格式如下(Sass Maps 官方文件參考)

CSS

將剛剛那些變數按照 Sass Maps 格式整理一番,可以比較有系統化:

CSS

將上面的變數根據種類 / 屬性的不同,可以變成像物件一樣,需要哪一個資料再把它取出來即可。


利用 functions 包裝 Sass Maps

Sass Maps 看起來非常簡單也好上手,對吧!

不過每次都要寫 map-get 是不是覺得有點阿雜?如果不常用可能會忘記這段語法,又要回頭找資料。

會使用 Sass 的人,從本質上就是個懶鬼無誤,所以可以少寫幾個字,我們就要努力少寫幾個字💪,所以我們來利用 functions 幫我們包裝一下這段程式碼吧!

CSS

大家可以用 codepen 玩玩看


用迴圈跑 Sass Maps

除了 functions 之外,我們也可以用迴圈跑一段 Sass Maps 唷。

假設今天要做一個選單組合,而每個選單的背景顏色都不一樣,我們可以先用 Sass Maps 定義好每個選單的顏色:

CSS

接下來用迴圈跑出menu1menu5的顏色以及:hover

Sass

最後編譯出來的 CSS 如下:

CSS

有感受到,多寫一點迴圈可以省很多事情的 FU 嗎😊


我能使用 Sass Maps 嗎

文章最前面有提到,Sass Maps 是 Sass 3.3 版的新東西,因此只要你的 Sass 高於 3.3 版都可以使用喔!

簡單檢測方法,直接在 terminal 輸入sass -v就可以知道目前的 Sass 版本囉。

參考資料: Sass Maps – Jonathan Su

將 Google 搜尋框整合至 WordPress

WordPress 雖然是個非常強大的 CMS,但我覺得「搜尋」是他所有功能裡面最雞肋的,內建的搜尋功能無法結合多組字串,也沒有支援高亮或是進階搜尋等,其實不是很方便。有的人會選擇使用外掛增強 WordPress 內建的搜尋功能,或是額外自己寫一些 function 補足,不過我們也可以把搜尋這件事情交給強大的 Google,畢竟他們就是做搜尋起家的,透過 Google 搜尋我們的網站,比內建的方便很多喲。

▼ Google 搜尋結果示意圖

實際呈現結果,可以參考我的搜尋頁面:https://muki.tw/search/?q=muki

我最近也使用 Google Search 替換了內建的搜尋,使用方法很簡單,操作也是中文說明很好入手。不過要整合至 WordPress 還是有需要注意的部分,為了以後使用方便,特地將幾個重要的步驟記起來,也供大家參考使用。

使用 Google 自訂搜尋

Google 自訂搜尋改版後,總算將新舊控制台合併起來了,步驟也簡單許多,跟著以下的說明開始做吧!

步驟一

到新版 Google 自訂搜尋,新增你的網站資料。使用方法很簡單:

  • 「要搜尋的網站」欄位:填入你的 WordPress 位置
  • 「語言」:繁體中文
  • 「搜尋引擎的名稱」:填入你的網站名稱

最後按下藍色的「建立」按鈕,即可新建完成。

步驟二

在左側選單,點選「編輯搜尋引擎」,在下拉選單找到剛剛新增的搜尋引擎設定。點選後可以看到裡面有許多跟搜尋引擎相關的設定。請選擇「外觀和風格」,我們要調整搜尋顯示的樣式,才會更完整嵌入 WordPress。

  • 版面配置:請使用「2 頁」,它會讓搜尋框跟搜尋結果分開顯示。
  • 圖片搜尋結果的版面配置:隨便選,自己開心就好。
  • 選擇或自定樣式:可以選擇自己喜愛的樣式,也可以自定,之後都可以再回來修改。

▼ 不太清楚怎麼選擇的話,可以參考我的設定圖片,照著選就好囉!記得按下儲存才會更新你的設定。

步驟三(重要!)

終於到重頭戲了!在「外觀與風格」的選單內,找到下方的「儲存並取得程式碼」,我們要在這邊設定 WordPress 的一些資訊。
點擊「搜尋結果詳細資料」,會跳出一個視窗:

  • 指定要顯示搜尋結果的目標網站完整網址:這邊請填上你的 WordPress 網址,就是你的搜尋結果網址。網址結構可以從 WordPress 自訂。我是寫 https://muki.tw/wordpress/search/
  • 指定網址的內嵌查詢參數名稱:請輸入 q

最後記得按下「儲存」喔。

▼ 可參考以下截圖的設定

Google 搜尋的設定先到此告一段落,接下來請打開你的 WordPress 後台,要開始修改 WordPress 的檔案囉。


修改 WordPress 設定

步驟一

請複製剛剛 Google 提供的程式碼,請參考圖片,先複製紅框處的

▼ 參考圖片的紅框處範圍,進行選取與複製。

步驟二

打開header.php,找到,在他的上面貼上剛剛你複製的那段程式碼。

步驟三

同樣在header.php,搜尋search關鍵字,這邊會根據佈景主題的寫法而有所不同。你有可能會找到這段程式碼:

PHP

或者是找到input這樣的表單語法:

PHP

不管是那一種呈現方式,我們要找的程式碼是用來「顯示搜尋框」的語法。找到的後請替換成:

PHP

步驟四

再來進入 WordPress 控制台,選擇「頁面」→「新增頁面」。我們要在這個頁面顯示 Google 的搜尋結果,所以請先將編輯器切換成「文字」模式,然後輸入以下語法:

PHP

接著我們要確認使用搜尋框之後,搜尋會跳到這一頁才對。還記得我們在設定 Google 搜尋的第 3 個步驟,有設定「指定要顯示搜尋結果的目標網站完整網址」嗎?我們要利用 WordPress 可以自定網址結構的特性,將這個 URL 新增到 WordPress 頁面的網址結構中。

我之前設定的網址是https://muki.tw/wordpress/search,所以我在固定網址的地方,只要打上search即可。

▼ 文字不懂沒關係,請看圖片示意:

最後按下「發表」,這樣使用 google 自訂搜尋框搜尋關鍵字之後,就會利用參數q代入我們的搜尋字串,然後將結果顯示在頁面上。

實際呈現結果,可以參考我的搜尋頁面:https://muki.tw/search/?q=muki

Google 搜尋框其他設定

要整合至 WordPress,最重要的步驟就是前面那大兩部分,包含在 Google 搜尋控制台,以及在 WordPress 的設定。最繁複的先做好,先讓 Google 搜尋框可以跑,後面的設定對你應該都是小兒科啦!

在「外觀風格」的選單,可以自由調整搜尋樣式;還有其他選單可以自行玩玩看,因為都是中文介紹,所以應該很好上手!

希望大家都可以自由打造屬於自己的搜尋喲~ enjoy it!

用 css 讓區塊水平垂直置中

有時候我們需要做個前導頁或是簡單的名片形象頁,在內容不多的情況下,可能需要讓 DIV 垂直以及水平置中;除了 DIV 外,甚至連文字也需要垂直與水平置中。

就如同下圖範例,這是一個很簡單的名片形象頁,深灰色底是一個 DIV。可以看到除了 DIV 之外,文字也是垂直水平置中。

另外當你移動畫面時,他也會固定在畫面中央,不會因為視窗縮放而有任何跑版情況。(線上 DEMO 網址:http://codepen.io/mukiwu/full/Iuncz/

看起來很難的效果,其實只要短短幾行語法就能達成。就讓我們一步一步的拆解吧 🙂


DIV 垂直水平置中

先跟大家分享一張非常清楚的圖解,取自 Smashing Magazine 的大作。

(圖片來源:smashingmagazine

如圖所示,不管該元素(DIV)多大,我們都可以先用position: absolute 讓元素放在中央。

CSS

但事情可沒那麼簡單,利用absolute調整位子的基準,是從該元素的「左上角」開始算起。所以如果在 X 以及 Y 軸各設 50%,是針對元素左上角(紅色點)的 50%


▼ 因此該元素(DIV)位子會掉到淺灰色區塊的地方,但是紅點剛好在畫面正中央。

我們必須要再給予元素明確的高與寬,利用margin-top以及margin-left把元素往回推。往回推的數值就是(高/2)以及(寬/2)。如果高是300px,就往回推150px,依此類推。

最後垂直置中的程式碼會如下所示:

CSS

文字垂直水平置中

想讓文字水平置中,只要寫text-align:center就可以囉!算是置中規則裡最簡單的一種。

而垂直置中卻沒那麼直覺,單純寫上vertical-align:middle,瀏覽器是不會鳥你的。

垂直置中有很多種解法,今天跟大家分享其中一種,透過display改變元素的形態,進而讓垂直置中有用。

HTML 必須要有一組二層的巢狀結構:

HTML

利用 CSS 修改display

CSS

使用這種方法就可以讓文字垂直置中囉 ~。

延伸閱讀:In the Woods 有提供更多種垂直置中的解法,好處與壞處也寫得很詳細,可以參考看看。

最後你也可以將兩種垂直置中的效果合併在一起,完整的程式碼請參考我的 DEMO:http://codepen.io/mukiwu/full/Iuncz/

利用純 CSS3 做出自適應的 lightbox

因為工作需求,要做一個使用說明頁。但「使用說明」並非這個案子的主要需求,所以決定利用 Lightbox 取代多做一頁 HTML,但使用功能強大的 Lightbox plugin 有些大材小用,所以思考了一下,決定使用純 CSS3 寫一個簡單、又能自適應的 Lightbox。

關於「純 CSS」到底有什麼好處?這邊就不再贅述了,簡單好上手、讀取速度快算是兩大特點;雖然不是所有瀏覽器都支援 CSS3,但我這個案子是應用在手機上,基本上沒有手機不支援 CSS3,所以不用太過擔心這方面的需求。

以下先放上範例讓大家試玩,點選按鈕「Click Me」或者是旁邊的圖片,都可以看到 Lightbox 的效果喲!

HTML 結構

要製作純 CSS 的 Lightbox 並不難,我們先從 HTML 開始寫起吧!
關於點擊後,要展開哪個 Lightbox?只需利用相同的id名稱即可做到。此外重點只有三個元件,分別為:

  • 打開 Lightbox 的元件(例如按鈕、圖片)
  • Lightbox 展開後的內容
  • 關閉 Lightbox 的元件

所以 HTML 結構可以這麼寫:

HTML

這邊特地帶出body標籤,是要提醒大家,請把lightbox-target(Lightbox 展開後的內容)拉出來,寫在body的子層。

大家可以想像一下,正常點選 Lightbox 後,整個螢幕都會黑掉,Lightbox 會出現在螢幕的正中央才是正確的。如果將lightbox-target包在任何的div裡,就會受到該div的定位或寬度限制,讓你的 Lightbox 位置變得很詭異。

如果看不太懂沒關係,讓我們做成圖解吧!

▼ 正常的 Lightbox

▼ 錯位的 Lightbox

因為我們會利用lightbox-target製作透明的覆蓋底層,所以透過圖解,應該可以清楚瞭解他們的差異吧!總之lightbox-target的位置會影響到整個版面就對了 XD

以上就是 Lightbox 的 HTML 結構,接下來要使用 CSS 做出 Lightbox 的展開與關閉。

CSS 樣式與寫法

樣式的部分,會分成以下幾個區塊:

  • lightbox-target:Lightbox 的黑底背景,即俗稱的 overlay
  • content以及img:設定跳出 Lightbox 時,出現的內容或圖片樣式
  • lightbox-target:target:我們利用:target設定當「點選的元件變為目標時」,會出現的 CSS 樣式。
  • lightbox-close:關閉 Lightbox 的「X」樣式。

可以參考我的 CSS 寫法(我有在裡面加上註解,大家可以參考相關註解歐):

Sass

利用 HTML 跟 CSS 就可以很快速的做出簡易的 Lightbox 囉,而且可以支援 HTML,或是單純的展示圖片,非常好用呢!!!

有興趣的朋友,也可以自行修改 Lightbox 的樣式,讓他更符合每個網站的需求 🙂

display: table-cell 無法使用 margin/ padding 的解法

只要是使用 HTML+DIV 排版的人,應該都很清楚table 是用來繪製表格,而非用來排版的這件事情。然而因為 DIV 真的太好用了,現在很多人幾乎都不知道table, tr, td… 該怎麼互相搭配與運用。雖然不清楚是哪些因素影響,但是 W3C 卻在 CSS 的display屬性裡面支援table值,讓我們可以使用 DIV 就做出跟 HTML 的 table 標籤一樣的效果。(該說是 CSS 跟 HTML 互打臉嗎?)

關於display: table的介紹與運用,知名部落客香腸已經有一篇很深入淺出的文章,我就不多贅述了。完全沒用過display: table的朋友、或想了解該怎麼使用的朋友,可以參考香腸的:用CSS+DIV畫表格(table)進行網頁排版

我這篇針對的族群,是已實際用過display: table的朋友,當你們在使用的時候,也許會碰到「間距調整」的問題,例如要在每一個table-cell裡頭設定margin等間距調整,卻發現修改無效。假設你碰過這種狀況,不妨參考一下我推薦的解法


話不多說,先上個範例!我使用圖片+圖說當作範例,例子包含:

  • 正常狀況下,圖片緊密排列
  • 使用margin調整的結果
  • 將寬度寫死的結果
  • 使用border-spacing調整的結果

如果看完例子還是似懂非懂,或想更了解原理的朋友,可以繼續往下閱讀喲。

正常狀況下,圖片緊密排列

一般我們要做水平排列的圖層,多半會使用floatdisplay等屬性設定。如果今天你有製表的需求,或是其它因素考量,也可以嘗試使用display:table達成。

display:table在預設情況下,只要我們給他一個寬度,裡面的元素就會自動依據總寬度分散對齊。

在這邊,因為每張圖寬為 120px,所以我先設定總寬是 480px,這樣他們就會緊密排列在一起,如下圖所示:

使用 margin 調整的結果

如果我們希望每張圖都有一點空隙,不要緊密排列的話。正常思維下,都會使用margin達成。因此我在範例二加入了這段語法:

CSS

▼ 顯示結果為(你可以嘗試將 10px 修改成 100px,會發現沒有任何作用):

因此可以發現,margindisplay:table*一家子是沒有任何作用的。透過 MSDN Document 對 margin 的介紹可以了解

Applies to: all elements except elements with table display types other than table-caption, table and inline-table
除了 display 為 table 的屬性不支援外,適用所有元素(包含 table-caption, table, inline-table )。

margin – CSS | MSDN

因為不支援margin,所以沒有任何效果也是正常的喔。

將寬度寫死的結果

既然margin沒有任何作用,我們可能會利用display:table分散排列的特性,手動設定寬度讓圖片對齊。

例如:4x120px + 5x5px = 480 + 25 = 505px

將整體寬度設定為 505px 後,就會根據寬度分散對齊,變成下面的圖片效果:

乍看之下達到了我們想要的效果,每張圖片中間都有間隙。但仔細研究後你會發現兩個問題:

  1. 第一張圖片的最左邊還是貼齊 div,沒有任何空隙
  2. 假使圖片超過四張,間隙就會消失了(因為圖片寬度寫死,所以沒彈性)

由此可知,將寬度寫死,絕對不是一個好解法。曾經嘗試過用這種解法的朋友,建議把它拋諸腦後吧!

使用 border-spacing 調整的結果

利用border-spacing,是目前普遍認為較適當的解法。

我們只要在display:table-cell的父層,也就是display:table這層加上第 3 跟 4 行的兩行語法就可以囉:

CSS

▼ 顯示結果如下

跟剛剛使用寬度寫死的範例圖片相比,可以方便每一張圖片的左右空隙都是一樣的,不管是第一張或是最後一張,都留有 5px 的空隙。

但因為我們必須將這個設定寫在父層,所以在image-list底下的所有display:table-cell都會套用此設定,如果有的 table 不想要有空隙設定,就必須單獨把 HTML 的結構拉出來,或是再用 CSS 權重覆蓋,算是比較麻煩的一點。

目前還無法只針對table-cell做調整,希望以後 W3C 可以增加更多對display:table*的支援度囉!

最後再看一次線上範例,加深自己的印象吧!請記得,將寬度寫死,絕對不是一個好解法喲 🙂

使用 CSS:not 與 data-index 即時搜尋頁面

去年看了一篇文章「Client-side full-text search in CSS」可以在單一頁面即時搜尋資料,覺得非常的好用,之前也有在粉絲團分享過這篇文章。原本不打算重新寫教學(因為原作者已寫的很詳細),但是最近發現有朋友不知道這功能,所以轉念想想,還是記錄下來順便推廣一下這好用的功能吧 🙂

我有將這個功能實作在前公司的網站(fanxin.tv),如果你有登入,可以進入我的動態點選「朋友列表」或「尋友工具」的分頁觀看效果,或者可以參考以下我用 codepen 做的範例

直接在搜尋框打上要搜尋的人名(可以用J,j搜尋),可以看到頁面即時篩選出正確的名字

這個範例有搭配 JavaScript,原作者使用的是原生的 JavaScript,而我為了稍作區別,將它改成了 jQuery,所以想瞭解怎麼用 jQuery 寫的朋友可以參考我的範例 🙂

這個即時頁面使用了 :not 以及 data-* 完成(不得不說, data-* 真的超好用的 XD),以下簡單介紹如何使用它們達成該功能。

在 html 加入 data-* 屬性

從頁面看,感覺是搜尋類別 name ,但其實我們要在 name 的父層 wrap 加上 data-index ,利用 data-index 做搜尋,而不是用 name

因此可以看到我在每個 wrap 裡加上了 data-index ,值跟 name 一樣都是填上名字。(第 1 & 3 行、第 6 & 8 行)

HTML

唯一不同的是,即使原本的 name 有大小寫,我在data-index一律改成小寫表示,如果要透過後端產生資料,可以從後端作處理,在樣板輸出的時候就先將大寫轉成小寫。

使用 :not 屬性做篩選

接著我們在 HTML 頁面加入以下語法(可以加在搜尋框的後面):

HTML

我們會利用 jQuery 動態在 style id="m-search" 裡加入 :not 語法,這樣就可以即時在頁面做篩選了。

:not是 CSS 的偽元素,跟 :nth-child 有異曲同工之妙,他可以幫我們做到元素篩選,假設今天我們搜尋「j」,希望出現所有名字有「j」的人,可以利用:not寫成:

CSS

這段意思是:「只要 data-index 的值沒有 J,就隱藏他」。

使用 data-index*= 是因為我們要做模糊比對,只要 data-index 有出現這個字都可以,畢竟我們不希望只搜尋字首或字尾,而是搜尋全部。

利用 jQuery 即時搜尋

最後,就可以利用 jQuery 即時搜尋,只要搜尋框有「改變、鍵盤輸入、貼上」等事件,我們就即時在 style id="m-search" 裡加入 :not 篩選,而他的篩選依據就是我們搜尋框的值:

JS

結語

以上就是整個過程,只要利用 CSS 以及 JavaScript(jQuery) 就可以做到即時搜尋,但是他只能搜尋這個頁面的東西,畢竟只是單純抓取 HTML DOM,如果要搜尋後端資料,還是要用 ajax 囉。

相關 jQuery 插件應用

3/12 更新:

有朋友將該功能做成 jQuery 插件釋出,有興趣想玩玩看的話,可以直接套用 jQuery 插件喔。

插件安裝與介紹:https://github.com/dca/jquery-msearch

用 data-* 屬性做出純 CSS 的 tooltip

最近因為案子需求,要做「tooltip」的功能,簡單來說,tooltip 是一種「當滑鼠移過文字時,會跳出一個簡短的提示說明」的特效。

tooltip 技術已存在很久,發展也有一段時間了,不論是用純 CSS 製作,或是透過 JavaScript 控制都有人寫過,不過最近我發現還可以利用 HTML5 的新標籤 data-* 達成。去年我有寫過一篇利用data-*在 HTML 以及 jQuery 存取資料的文章,但 data-* 厲害的地方不僅在此,我們還可以直接利用 CSS 的 attrdata-* 資料抓出來噢!!

那話不多說,就先上範例吧:

可以看到當滑鼠移過「Hover Me」的文字時,右方會淡出一個提示訊息;滑鼠移過「Push you mouse here」文字時,右方會出現多行的提示。

在此跟各位簡單介紹一下,如何使用 data-* 達成該功能。

在 html 加入 data-* 屬性

首先要做的第一件事情,就是設定 tooltip 的 html 程式碼。我的寫法為:

HTML

span裡面寫上data-tooltip的屬性,然後可以把它當作 HTML 屬性直接使用,在值(value)裡寫上提示文字。data-tooltip的「tooltip」名字可以自取,只要前面的格式以data-為開頭即可。

在 CSS 利用 attr 抓取 data-* 屬性

CSS 的偽元素是個很強大的東西,我們可以利用他做很多運用,通常為了做一些效果,content:" "多半會留空,但其實可以在裡面寫上attr抓資料歐!

我們可以這樣寫:

CSS

attr裡面塞入我們在 html 新增的data-tooltip屬性,這樣偽元素(:before) 就會得到該值。

利用 pre 解決 tooltip 自動換行

將 tooltip 的樣式做好後,也許你會發現文字的換行有點奇怪,可能會出現這樣的情況:

「Hello World」文字並沒有按照預期的情況換行,簡單來說是因為預設會使用空白換行,因此我們可以使用pre標籤保留空白字元,寫法為white-space: pre;

利用 Unicode 字元顯示多行 tooltip

最後,如果我們希望 tooltip 可以顯示多行文字該怎麼辦呢?
一開始我很直覺的在 data-tooltip 裡面加入 br 標籤,但他會直接將br秀出來:

後來我發現 bootstrap 有寫好 tooltip 的元件,他的做法是如果你要在 data-* 裡面使用 HTML 標籤,就必須加入一行 data-html="true" 的設定,當時看完覺得超神奇的,他把這串設定寫在 javascript 裡面做判斷,但我還是似懂非懂,不知道 bootstrap 的具體設定方法。

最後,我採用 Unicode \a 作處理。

在想要換行的地方改用&#xa ;取代br,這樣文字就會自動換行囉!!

HTML

☞ 補充

; 的前面其實不需要空格,但如果我不空格,字元會被編輯器吃掉。想看比較完整的語法可以參考 codepen 範例喔。

參考來源:http://stackoverflow.com/questions/16451553/css-data-attribute-new-line-character-pseudo-element-content-value

雖然我還是很想知道 bootstrap 到底是怎麼寫的,有在 FB 問過朋友,但其實還是看不懂,OTL

總之,data-* 真的是一個強大又好玩的東西,不僅可以自定義屬性(把自己當成 HTML 的規則制定者?),還可以透過 jQuery & CSS 存取~,大家一起來玩吧 😀

在 wp nav menu 前後增加自定義連結

WordPress 有一個很好用的 WP_nav_menu function,可以在 WordPress 控制台直接新增選單內容。

但要特別注意的是,如果我們想在新增有 class 或 id 的選單,就沒辦法直接從控制台新增,因為控制台的選單無法讓我們填寫 id 或 class。

選單只能讓我們新增連結文字、位置,以及屬性,如下圖:

因此我們可以利用 wp_nav_menu 提供的函式自己手動加上想要的連結。

假設今天我們希望在選單的後面加上以下語法:

HTML

可以先找到以下語法 (通常在 header.php) 裡:

PHP
header.php

這個語法就是用來設定 wp_nav_menu 的一些樣式,如果你對製作這樣的選單有興趣,可以參考這篇文章:WordPress 內建階層選單製作

回到手動添加連結的部分,假使我們想要將連結加在選單的後面,請依照'items_wrap' => '連結語法'的格式添加進去,語法請參考(第 7 行是我新增的部分):

PHP

這樣你手動增加的 custom link 連結就會永遠放在自定義選單的最後一個位置。

如果你想要把手動增加的連結放在最前面,就只要把%3$s跟你的語法對調即可,請參考:

PHP

WordPress Nav Menu 還有很多參數可以使用,有興趣的朋友可以自行閱讀官方文件:Function Reference / wp nav menu

用 Photoshop 做出相機圖示

今天參考了網路上的教學,用 PhotoShop 做出相機圖示。其實像這類的 icon 應該要用 Illustrator 比較恰當,畢竟使用向量圖在放大 & 縮小的時候都不會失真。不過我也只會用 PhotoShop,剛好教學也是用 PS 做的,超開心 XDD

原文的教學寫得非常清楚,連他設定的數值都秀出來給大家看,所以只要會基本的 PhotoShop,都可以手把手做出一樣的相機圖示喲。不同的頂多就是發揮自己的創意再修修改改吧 :)

教學網址:原創/自譯教程:教你用一個圖層搞定相機圖標(原創文章) (版權內容屬於原作者,我只是單純備份圖片)

使用 CSS nth-child 必須要注意的事情

之前有寫過一篇 利用 :nth-child() 讓網頁展示商品時左右對齊 的文章,裏面有稍微提到:nth-child()的使用方法。

其實:nth-child()好用的地方就在於他可以針對每個元素做個別的樣式設定,不用再像以往一樣用程式判斷然後算半天。不過我最近發現,有一些排版,沒辦法直接使用:nth-child()達到我想要的效果,所以最後我還是改用 jQuery 撰寫。如果你常使用:nth-child()寫網頁,不妨可以參考一下唷。

再次引用 W3C 的解釋(請特別記住這句話,接下來的範例,受到這句話的影響非常深刻唷)

:nth-child(n) 選擇器匹配屬於其父元素的第 N 個子元素,不論元素的類型。n可以是數字、關鍵詞或公式。

【範例】規定屬於其父元素的第二個子元素的每個 p 的背景色:p:nth-child(2) { background:#ff0000; }

CSS3 :nth-child() 選擇器 / W3SCHOOL

看完如果似懂非懂的朋友,沒關係,請先記住這句話,下面會再詳細解說。這篇文章先當作大家已經會使用基本的:nth-child()

範例

話不多說,直接上範例,CSS & HTML 語法請看我的 codepen,或參考以下 DEMO:

以上這個網頁結構,分作主課程 (WordPress, CSS, Html) 以及子課程 (install plugin, install theme…等) 兩種;在範例中,我想要做的效果是「當子課程是偶數欄時,背景會變咖啡色」。

左邊是用 CSS 的:nth-child(odd)語法,右邊則是用 jQuery 的:odd selector,大家可以看到最後呈現的兩種效果不太一樣。(是的,你沒看錯,odd 是奇數不是偶數,為什麼我會用 odd 而不用 even,後面會解釋)

就常理而言,應該是右邊的「Use jQuery(:odd)」會比較好閱讀,左邊的欄位變色感覺有些不連貫。如果你有看 codepen 的語法,應該會發現我都是使用:odd來控制,那為什麼計算的結果不一樣呢?難道是 CSS 跟 jQuery 對 odd 的計算方式不同嗎?

其實可以說是,也不是。事實上,這跟 HTML DOM 有比較大的關聯。

版面解析

讓我們先來拆解這個 HTML 版面。這是一個課程清單表,主課程底下會有很多子課程,所以用類似「合併儲存格」的功能,把最前面的主課程欄位合併,這樣在看課程的時候較一目了然。因此,我是這麼寫的:

HTML

我用.class-wrap包住最大的課程類別,再用.content包住子課程。所以簡化版的 HTML 會長這樣:

HTML

接著,回到原本我們想做的網頁效果:「子課程的偶數欄位要變色」。

我們想要變色的 class 是.content,然後是偶數(even) 欄位。假使我們用:nth-child來寫的話,正常毫無疑問會這麼寫:

CSS

但你會發現,用:nth-child(even)後,居然是奇數欄位變色了!! (也可以直接編輯我的 codepen 看結果唷)

揪竟是為什麼呢!?只能說:nth-child是個非常奇妙的東西,尤其碰到像範例這種複雜的排版,整個計算方式會跟常理認知的不太一樣呢!讓我們來慢慢的、一步步了解吧。


一、先了解:nth-child(n)的初始值是 0 還是 1 ?

:nth-child(n)的初始值是 1 ,依序 1、2、3、4 這樣算下來。因此沒有:nth-child(0)這種東西

二、再了解:nth-child(n)的定義

重點 ★ 請把剛才我請你記住的那句話,關於:nth-child(n)的定義,拿出來複習一下:「:nth-child(n)選擇器匹配屬於其父元素的第 N 個子元素,不論元素的類型」。

接著,我們再把剛剛的 CSS code.content:nth-child(even),改成跟定義一樣的句子:「.content選擇器,匹配其父元素.class-wrap的第偶數(even)個子元素」

… 好吧,我覺得大家一定看不懂,讓我改用白話文說一遍 (嗚嗚,要講解這一部分好難啊,不要逼我自暴自棄 T^T)

  1. 先找到.content的父元素:.class-wrap
  2. 找出.class-wrap底下的所有子元素,以剛剛的語法範例來看,第 1 個子元素是class="class"的主課程標題,第 2 個子元素才是class="content"的子課程 1 。 主課程標題 1 子課程 1 子課程 2
  3. 因此,原本我們以為「子課程 1 」會是匹配父元素的第 1 個元素,但因為.content前面還有一個.class,所以「子課程 1 」變成了匹配父元素的第 2 個元素。
  4. 再重新把.content:nth-child(even)拿回來看,其實符合偶數(even)的元素是這些:

這樣大家清楚嗎?因為前面多了一個不是.content的 class,但他也是.class-wrap的子元素阿!所以全部算下來,原本我們以為的偶數會是奇數、奇數會變偶數。因此我的範例語法才會寫:odd而非:even

如果了解,就讓我們繼續進行下去。

三、為什麼 n 的計算不是從 1 到 100 呢?

因為:nth-child(n)是以父元素.class-wrap作為起始點。假設第一個主課程底下有 4 個子課程,他的元素依序計算為 1、2、3、4;但,到了第二個主課程又會重新從 1 開始計算,並不會從 5 繼續數下去。

這就是為什麼我們看到左邊的範例會感覺參差不齊,但如果你把每個.class-wrap都當作一個段落,就會發現他其實偶數的元素還是會變色的。


圖解

那,到底每個子課程的:nth-child(n)是多少?

還是不太清楚的朋友,可以再看看我寫的 codepen:http://codepen.io/mukiwu/full/nmlkt ,然後隨意點選任何子課程的欄位。你會看到如下結果:

如果你點選了任意子課程的欄位,可以在紅底的區塊看到一些數字。

簡單總結:

  • 「Use CSS nth-child(odd)」:以主課程作為區塊,每個主課程結束以後,會重新開始計算。這邊出現的數字是該欄位的:nth-child(n)的 n 值
  • 「Use jQuery(:odd)」:單純計算有多少子課程,不受主課程影響,所以會從 0 算到最大個數。這邊出現的數字是所有子課程的 index 值

以上是兩種寫法主要的差別。

利用 jQuery :odd 撰寫

就如前面所說,為了視覺的平衡,我們幾乎都會採用右邊的表現手法,所以可以改用 jQuery 撰寫:

JS

只是要特別注意的是,jQuery(":odd")的初始值是 0 不是 1,所以第 1 個子課程是偶數、第 2 個子課程才是奇數… 以此類推。

我們以為偶數的欄位是奇數,以為奇數的欄位是偶數,這樣的情況會再度發生。

總結

如果你會用到像我這樣的排版,直覺的使用CSS nth-child來撰寫的話,也許會碰到同樣的問題。因此,可以嘗試使用 jQuery 解決。如果有可以直接用 CSS 解掉的方法,也歡迎告訴我唷:)

以後,我會將一些寫的較漂亮的範例轉移到 codepen,如果你喜歡我寫的範例,也歡迎到我的 codepen 支持我唷

WordPress 內建階層選單製作

WordPress 3.0 改版後,新增的內建選單功能,算是我最愛的功能之一,做佈景的時候也常常會用到。所以決定筆記一下階層選單的製作方法,不用每次製作都要 google 一次 XD。

步驟一

打開 header.php,把選單的語法加入:

PHP

步驟二

打開 style.css,加入 css 語法。

這邊加了有子選單的時候,滑鼠滑過才會展開。主要是由 11~13 行控制,利用:hover後尋找自己下一個ul,再把 displaynone 改為 block

CSS

步驟三

最後到 wordpress 後台「外觀」 → 「選單」開始添加選單即可。 補充

當前選單有一個 .current 屬性可用,可以讓讀者知道現在這篇文章,在哪一個選單裡面,我直接抓自己的部落格語法補充在下面:

CSS