利用手帳達成學習目標

最近參加了 FB 社團:手帳筆記工作術的活動,活動是每個月都會發布一個主題,例如這個月是學習。只要一個月堅持七天有持續並記錄,就算是順利完成該活動。

這對手帳荒廢已久的人,或是不知道要記錄什麼的人來說,我覺得還蠻實用的,至少可以給大家一個方向吧。

(閱讀全文…)

難解的 CSS 排版:認識對齊(下)

本文為參加第 11 屆「iT 邦幫忙鐵人賽」系列文章,會優先在部落格發文,再貼到 iT 邦幫忙~。
如果文章對您有幫助,歡迎到 iT 邦幫忙給我一個訂閱與肯定 ^___^。
好久沒寫文了,也希望自己可以堅持 30 天,加油(握拳

昨天講了text-align以及vertical-align這兩個常見的對齊語法,但他們可以對齊的範圍都比較小,偏向對齊元件,而非版面。
如果要讓版面置中,或是再更複雜的一些排版,我們還可以有更多選擇。

版面置中的好幫手: margin

這個應該很多人都用到爛掉了,但有的朋友可能不太懂原理,在此簡單介紹一下。

我們在切一個大版面時,如果要讓他左右置中,現在普遍最快的方法是使用以下語法:

CSS

然後版面就可以置中了。

margin: 0 auto;margin: 0 auto 0 auto; 的簡寫,表示上下邊界為 0 ,左右為auto表示自己均分。margin會去判斷.container的寬度以及螢幕的寬度,相減之後除以二就是左右邊界的數值了。

至於該如何得到.container的寬度呢?就是必須要在 CSS 寫上寬度,如果沒寫寬度是不會有效果的。

margin大到版面,小到元件,只要有指定元素的寬度,幾乎都可以用這個方法左右置中。

CSS

更多的 margin

☞ 圖片一樣可以使用margin: 0 auto;置中
margin可以讓版面置中,但沒辦法讓文字置中唷。


讓 padding 幫你實現簡單的垂直置中

如果說margin是負責版面,那padding就是負責裡面的元素了。

我們可以利用padding將 Box Model 往外推的特性做到置中的效果,只要上下數值一樣就可以囉。

CSS

選單文字垂直置中的首選 line-height

▼ 假設今天要製作一個類似這樣的選單,文字需要垂直置中,同時又有限定元素的高度。

因為有限定高度,所以我們沒辦法用padding去推 Box Model;另外一個原因是,如果選單再複雜一點,padding通常都另有用途。

所以假設今天需求是:

  • 有限定元素高度
  • 文字需垂直置中
  • 文字非常單純只有一行

在上述的情況下,可以直接用line-height解決,只要讓line-heightheight高度相同即可

CSS

用 position 讓你的版面水平垂直置中

position的解法,我之前在部落格有寫過了,所以容我直接跳過~
有興趣的朋友可以直接參考這一篇文章:用 css 讓區塊水平垂直置中


用 transform 做出與 position 類似的置中效果

transformposition類似,都是直接將 Box Model 推移到特定的位置上,達到置中的效果。

使用position可以再利用margin去推算要定位的位置,但前提是你必須要知道元素的寬跟高,才有辦法回推。但使用positiontransform就不用特別設定寬跟高,非常的方便

CSS

難解的 CSS 排版:認識對齊(上)

我一直很想寫這系列的文章,一來是 CSS 博大精深,有太多難解的觀念在裡頭。二來是常常要切很多重複卻又複雜的版型,所以想要系統化這些資訊,供日後快速查閱。

因此,這系列算是我自己的筆記,也算是經驗分享吧!也希望能幫到各位 m(_ _)m

廢話不多說,直接上重點 XD。

(閱讀全文…)

CSS Flexbox 介紹與解析

老實說我到現在都還沒開始用 flex 做網站,最大的原因就是 IE 相容問題,不過這也不能當作不學習的原因,畢竟這行就是要不斷的學習新知識😂,而且剛好在某次前端課程中有同學問我能否介紹 flex,所以想想,乾脆就寫一篇文章吧!不僅是幫自己做個筆記,以後也可以當作課堂上的補充講義~。

▼ flex 相容一覽圖 / caniuse.com

什麼是 Flexbox

簡單來說,Flexbox 是一種 CSS 的排版語法,就跟我們以往用的 position, float, display…一樣,只是 Flexbox 是 CSS3 的新語法,所以才有瀏覽器相容的問題。

Flexbox 相關屬性與值

我覺得 Flexbox 較難上手的原因,就是他的屬性跟值太多了,不像 float 很單純的只有 left, right, none 這三種,但當然好處就是彈性非常大,幾乎很多複雜的排版都可以靠 Flexbox 輕鬆解決。

在這邊也參考了 W3C 的網站,列出所有 flexbox 的屬性跟值給大家參考,至於詳細的介紹還是可以看 W3C 關於 Flexbox 的文件喔!

屬性屬性介紹可用的值預設值影響
flex-flow將 flex-direction 以及 flex-wrap 合併寫在一起flex-direction |flex-wrapflex containers
flex-direction
排列方向
rowrowflex containers
row-reverse
column
column-reverse
flex-wrap
換行nowrapnowrapflex containers
wrap
wrap-resverse
order
調整元素排列的順序<整數>0
flex
將 flex-grow、flex-shrink 以及 flex-basis 合併寫在一起flex-grow|flex-shrink|flex-basisflex items
flex-grow
<數字>0flex items
flex-shrink<數字>1flex items
flex-basis<寬度>autoflex items
justify-content
水平對齊設定flex-startflex-startflex containers
flex-end
center
space-between
space-around
align-items
垂直對齊 (元素單行排列)flex-startstretchflex containers
flex-end
center
baseline
stretch
align-selfflex-startautoflex items
flex-end
center
baseline
strech
align-content
垂直對齊 (元素排列超過兩行以上)flex-startstretch多行 flex containers
flex-end
center
space-between
space-around
stretch

常用的 Flexbox 排版語法

要使用 flex 前,必須先在該容器指定:

CSS

而特別有趣的是,就連行內元素都可以用 flex 唷:

CSS

接下來,我們用一小段 HTML 語法表示 Flexbox 的架構:

HTML

承上,這個很常見的巢狀排版恰恰能表達flex的兩大主角:flex-container以及flex-item,前者表示的是一個巨大的容器(container),後者則是各個獨立的項目(item)。

flex的屬性,有的會影響的是容器,有的則影響項目。如果不太清楚屬性影響的是哪一塊,可以回到前一頁看表格的「影響」欄位做參考。


基本的 Flexbox 排版

flex-direction

我們先介紹最簡單的左右版面,以往直接用float: left解決,那麼換成flex的話可以這麼寫:

CSS
  • Flexbox 是 Box Model 的一種表現形式,以前我們用display去改變每個元素的 Box Model,在此也是一樣,我們要在flex-container先設定display: flex,確保自己以及裡面的子元素 Box Model 都會轉成flex的設定。
  • flex-direction表示 flex 的水平排列方向,第一頁的 Flexbox 屬性表上有提到,flex-direction必須放在 flex container 的父層架構下,而不是 flex item 這個子層,所以這句話寫在.flex-container裡,如果你把它放在.flex-item會發現沒作用。(再次提醒:對照屬性表會更加清楚該放在哪裡喔。)

最後我們來把flex-direction所有的值都寫一遍吧!

See the Pen QEGbMm by MUKi (@mukiwu) on CodePen.

在值裡面,用到的rowcolumn,一個是水平排列、一個是垂直排列;而reverse是反轉的意思,稍微對照一下上面的範例應該不難了解唷!


flex-wrap

接下來再加一個新的語法flex-wrap,這個同樣要放在.flex-container裡面,wrap是斷行的意思,可以利用這個語法決定是否要換行。

設定nowrap表示即使有多少區塊,也必須都放在同一行內(會自動分配寬度)。設定wrap則是會依照內容或寬度自動換行。

See the Pen oLYjqG by MUKi (@mukiwu) on CodePen.

flex是三個屬性的合併縮寫:flex-grow, flex-shrink, flex-basis,可以看作是 FLexbox 的核心設定。 註:flex 的這些屬性影響的是 flex items。


flex-grow

我們都知道,區塊預設的寬度是元素內容的寬度,如下圖所示 ▼

如果想要調整寬度,一般可以用width設定,但也能用flex-grow唷!flex-grow的預設值為 0,表示寬度就是元素內容的寬。而從 1開始,數字愈大,占的寬度比例也會愈大。

CSS

範例圖如下所示 ▼


flex-shrink

flex-shrinkflex-grow相反,是表示當父元素寬度空間不足時,子元素壓縮的比例。預設值為 1,但設為 0 同樣表示不壓縮,數字愈大,被壓縮的幅度就愈大。

CSS

範例圖如下所示 ▼


flex-basis

可以在flex-basis設定寬度或高度,設定好後會自動分配該區塊的寬度或高度。

CSS

假設父元素寬度是500px,我在裡面設了兩個子元素分別為200px以及600px,他會依照比例分別給予子元素寬度,如圖所示 ▼

以上這三個語法因為有比較多的彈性,所以可以用在製作 RWD 網站上。


flex

最後,再次提到flex這個語法,是用來合併以上三個屬性,規格為:

CSS

flex 還有兩個更簡短的縮寫:

CSS

以上關於flex的範例程式碼,請參考:http://codepen.io/mukiwu/pen/qNRJPv


Flexbox 還有一些屬性沒有提到,因為我有點累了,所以暫時解說到這邊。但我覺得剩下的都是比較簡單而且很容易上手的語法,所以等待以後有空補完 XDD。

Flex 版面實例介紹

版面垂直置中

幾千萬年以來傷透腦筋的垂直置中,超級適合用flex解的喔!在這邊我們會用到兩個屬性:

  • justify-content
  • align-items

而這兩個屬性我前面通通都、沒、說(炸),但真的很簡單,所以直接上程式碼啦!

CSS

範例請參考 codepen:


動態三欄式

除了用flex-grow動態調整他們的大小外,還用了order調整版面的順序


不同的圖片 / 區塊排列

這種排版變化比較多一點,但不知道怎麼稱呼它,所以直接看範例比較清楚 XDDD。

一樣是大量運用到flex屬性做調整,在這個例子中,flex-basis尤其為最重要,當然還有一些對齊的語法也不能少。以下是有用到的語法:

  • flex-wrap
  • flex-basis
  • justify-content

以上三種排版,是我目前想到可能比較有趣,或是比較實際的例子 XD,如果有特別想要了解某些版面換成flex該怎麼寫的話,也可以留言給我唷!

iOS APP 程式入門課程紀錄

開始了為期一個月的 iOS 程式入門課。

為什麼要報這個課程?一來是有自己想要做的東西,雖然我知道不太可能上完入門課就會做,但至少可以拉拉畫面呀,或是寫一些簡單的 code XD;二來也是想參考一下講師們的授課方式,看看自己有什麼待改進的部分 XD

因為這堂課有一些回家作業,所以就決定統一整理記錄在自己的部落格啦,以後等作業愈來愈多,再採用分頁截斷,現階段就統一放在這篇文章裡 😊

(閱讀全文…)

inline element 與 padding 的二三事

前兩天在台大上課時,剛好提到 display 的各種形態,然後很嗨森的告訴同學,如果你設定任一元素(element)為 display: inline 時,padding-top 以及 padding-bottom 是不會有作用的唷 😆 😆 😆

結果!!就在我邊說邊示範的這個 moment 時!!!!!

他居然 work 惹 🙀 🙀 🙀 🙀 🙀 🙀

當下整個尷尬的無以復加 XD,所以回家找了一些針對 inline element 的說明,然後順便糾正一下自己的觀念 T皿T

OK,以上內心小劇場 + 碎碎唸完畢,讓我們開始認真吸收一下觀念吧~


我在 Head First HTML with CSS & XHTML 找到了一段針對 inline element 的說明,這段內容敘述非常清楚,可以瞬間導正自己的觀念,所以分享給大家:

You can add padding to the top and bottom of inline element, but the padding doesn’t affect the spacing of the other inline elements around it, so the padding will overlap other inline elements

Head First HTML with CSS & XHTML

簡單來說,inline element 的確可以使用 padding-top 以及 padding-bottom的語法,但 padding 不會推擠周圍的 inline elements,反而會覆蓋其他的 inline elements

不太懂也沒關係,我們就直接來看範例囉~

以 padding-bottom 為例

第一段是以p作範例(display:block),第二段是span(dispaly:inline)。在同樣使用padding-bottom: 1em的設定下,來看一下他們有什麼差別吧!

就我們認知的 HTML element 都是以「堆疊」模式排列而成,所以透過範例可以發現,正常情況我們設定元素的下間距時,他下方的所有元素會因此被往下推擠;但如果將元素的型態改為 inline 時,他下方的元素不會被推擠,反而會讓下方的元素把自己給蓋住。

以 padding-top 為例

我們再來看一個更明顯的例子,現在我把 padding-bottom 改為 padding-top ,看看會發生什麼事情。

如同剛剛說的,元素型態為 inline 時,設定padding-top並不會讓自己的往下推移,而是會覆蓋掉前面的元素。

你可以試著把我在 HTML 寫的這段語法加上 class 變成<span class="padding">

那麼你會發現,同樣的他不會讓自己往下推移,而是會蓋掉前面的元素:

也因此,雖然 inline elements 可以吃到 padding-top 以及 padding-bottom 的設定,但卻不會讓其他元素跟著被推移,造成排版上的一些困擾。我想這就是大家不常使用的原因,導致我只記得結論就是不用 top 跟 bottom XDDD。

如果你之前上過我的課,或是跟我一樣有這種觀念的朋友,希望閱讀這篇文章後可以一起把這個觀念修正過來唷😁

SASS, LESS 退散,原生 CSS 可以使用變數啦!

今天要跟大家分享一個新的 CSS 語法:變數。而且這個變數是原生的 CSS 就有的語法,不是其他預處理器例如 SASS, LESS… 的功能喔!

一想到以後可以使用 CSS 寫變數就超級興奮的😊~,但正因為這是 CSS 的新功能,想當然要考慮的第一個問題就是「瀏覽器的相容度」,透過 Can I Use 查詢後,可以發現支援度真是滿江紅啊 XDDD (紅色=不支援,綠色=支援) 2019.08 更新:現在各大瀏覽器對 CSS 變數的支援度已經慢慢在增加囉!

但因為這功能實在是太實用了,即使支援度不好,我還是想介紹給各位,希望未來所有瀏覽器都能支援,就可以輕鬆地運用在網站上囉!Chrome 跟 Firefox 都有支援 CSS 變數的語法,歡迎使用這兩個瀏覽器觀看效果。

CSS 變數的基本語法

如同我們使用各種預處理器設定變數般,首先要命名變數與設定值,接下來在適當的地方呼叫該變數。

以下是一段簡單的範例語法:

CSS

把握幾個原則:

  • :root命名變數,我們也可以在任意的選擇器內命名變數,後面會提到該怎麼寫,以及怎麼使用。
  • --main-color是變數名字,#369是該變數的值。
  • 承上,變數命名的規則為:開頭必須是兩個破折號 --
  • 在要呼叫變數的選擇器裡面,使用var()呼叫該變數,可以把它想成 function。
  • 變數的大小寫是兩個不同的變數,例:--main-color--Main-Color是不同的變數喔。

變數的命名規則看起來有點麻煩,有一些開發者曾經回饋:「為什麼不用$foo呢?」,而針對這個討論,他們的回應是,不排除這個需求,未來可能會允許使用$作為命名規則,相關的閱讀可以參考這篇文章

CSS 變數繼承觀念

前面有提到,除了可以將變數寫在:root外,還能寫在任意的選擇器,以下是範例語法:

CSS
HTML

也可以從 CodePen 看到實際效果 (記得確認瀏覽器有支援喔)

我們在通用選擇器( * )使用--bg-color語法,照理說,所有的 HTML 都會套用:root的設定。

但同時,我們又特別為h3以及#main設定了不同的背景顏色,因此,當我們的 HTML 有使用這兩個標籤時,他就會自動套用這兩個標籤設定的變數顏色囉!

也因此我們了解到,變數可以因應不同的狀況而更改它的數值 (這不就是變數的精髓嗎 XDDD),我們還能利用這種特性設計 RWD 網站:

CSS

▼ 變數的另外一個特性:可以互相 assign 來 assign 去,也能在 CSS 變數中實現喔!

CSS

這時候呼叫--font-color,他的顏色就是 #369


var() function 結構

var()的完整結構如下:

CSS

cutsom-property-name 是我們呼叫的變數,例如前面使用的--bg-color。我們也能在 declaration-value 設定其他的值,避免自定義的屬性無效時產生錯誤。如果寫成邏輯方程式大概就是:

JS

這種寫法有一種高檔的名詞叫做 fallback,如果你有機會閱讀 W3C 官方文件,會發現他們用 fallback 稱呼該處理。

declaration-value要用「逗號」去分隔多個數值,例如var(--bg-color, #369, black);。但如果要處理例如marginpadding的 fallback 時,請注意他們原本的值就沒有逗號,所以不需加逗號,例:var(--padding, 10px 20px);

如用 CSS 語法表示 fallback 應用,請看以下範例:

CSS

至於這個東西可以怎麼用呢?我暫時也不太懂 XDDD,不過看了一些 CSS Variables 的介紹後,有人提到可以用來作為元件的樣式設定,例如用 fallback 設定元件初始樣式,變數則是當作元件的 hook。

以下做了一個簡單的範例給大家參考,希望可以給大家更多的靈感囉:

CSS
HTML


常見的 var() 錯誤寫法

使用 var() 時,有一些要特別注意的地方

1. var() 的位置

var() 只能設定值,不能作為屬性的變數,以下是錯誤寫法:

CSS

2. var() 不能直接合併單位

CSS

上述寫法並不等於marign-top: 20px,如果我們要這樣設定,必須改用calc()幫我們計算數值。

利用 calc() 計算數值

以前面提到的 margin-top: 20px 為例子,我們可以改寫為:

CSS

calc()是個很好用的計算工具,更多的介紹可以參考 W3C 的 calc() 文件


利用 JavaScript 讀寫 CSS 變數

最後,我們也可以使用 JS 來讀寫 CSS 變數的設定。

  • 讀取:getPropertyValue()
  • 寫入:setProperty()

請直接看以下語法與範例介紹:

JS

使用 Codepen 觀看效果時,記得把第 8 行的註解打開以看不同的效果:


已經很習慣使用預處理器的朋友,可能會對 CSS 變數有所疑問:「我用 SASS 或 LESS 不就好了嗎?」

當然,這些預處理器推出的原意,就是為了補足 CSS 本身的不足,如果今天原生的 CSS 提供了變數的功能,我還是很樂意去了解以及使用,如果一味使用預處理器而不去管原生的 CSS 推出了什麼改變,不覺得有點本末倒置嗎 XDDD。

另外在 W3C 文件裡,也有提到 CSS 變數其實有很多變化,例如以下這段語法:

CSS

雖然我不知道這段語法該怎麼運用,但是從文件看來,這段語法應該是正確且可以跟 JavaScript 有所連結的。這樣看來 CSS 變數真的可以延伸出很多有趣的東西,這些改變都令我非常期待 XD。

也能參考 Google Developers 有趣的一段敘述

While this would not be useful as a variable, as it would be invalid in any normal property, it could potentially be read and acted upon with JavaScript at runtime. This means custom properties have the potential to unlock all kinds of interesting techniques not currently possible with today’s CSS preprocessors. So if you’re thinking 「yawn I have SASS so who cares…」 then take a second look! These are not the variables you’re used to working with.
CSS Variables: Why Should You Care?

以上,希望大家會喜歡這次的介紹囉,有任何問題都可以留言給我 ❤️

參考資料:

設計網站版面最重要的一環

圖片來源: Slate – Eduardo Santos

好的設計帶你上天堂,這句耳熟能詳的話大家應該都會背了。但我們都很清楚,「設計」真的是很主觀的,每個人對美的定義都不同,透過網站視覺所接收到的訊息也不同。但撇開一些極端的例子不談,設計還是有所謂的「安全範圍」,而這個安全範圍,是可以安全到讓人點頭稱好的。

那麼,揪竟在設計「安全範圍」的網站時,該把握哪一項要素,才能讓客戶點頭稱好呢?

那項要素,就叫做「整體的質感」。

同樣撇開有天分的設計師不談,每個人可以駕馭的風格都不太一樣,比如玩遊戲你選擇了元素師職業,也會有擅長與不擅長的元素,而決定你要轉職風火水雷哪一個元素。對設計師來說這也是一樣的道理,「色彩繽紛的」、「復古的」、「簡潔的」、「炫麗的」、「扁平的」、「立體的」….,我相信不是每個設計師都擅長所有的網站風格。但即使如此,依然要注重「整體的質感」。

只要設計網站時,質感抓到了,即使物件排列些微詭異、色彩運用些微不妥,也不會第一眼就被別人打槍。因為設計師交稿一定是先給 JPEG 檔案,業主第一眼一定是先看縮圖的整體視覺,才會細看裡面的配置,整體性有了、質感有了,剩下的小調整隻要在容許範圍內,都可稱得上是好的合作模式。

所以建議設計師,在設計網站時,除了過度專注在某一區塊的微調時,也請時不時的「ctrl + 0」一下,看看整體的版面風格,是否有過於跳 tone,或是粗糙的地方。因為唯有綜觀全局,你才能發現配色、細緻度、以及物件之間的連結性,是否有需要修正的地方。

我在逛網站特別注重整體質感以及細節的精緻度,當我看到一個平凡,沒質感又不精緻的網站,實在讓我沒有動力瀏覽下去。如果你跟我一樣有這種詭異的毛病,歡迎與我分享你覺得好看的網站,大家一起讓眼睛吃冰淇淋 😀

Dribbble 所賜,許多厲害的設計師會將他們的作品放在上面供人膜拜欣賞;要找出我覺得很醜的網站、非常多,但我心臟沒那麼大顆,不敢明目張膽的秀出來,所以只好反其道而行,放上我覺得有「整體質感」的網站給大家欣賞 (多來自 Dribbble) 。


1. Slate – Eduardo Santos

適當的留白與簡單的風格,還有重點突出的配色,不會讓人覺得很突兀,而且黑白的 Flat design,是非常安全的質感色。

圖片來源: Slate – Eduardo Santos

2. Blog Design – Mani

當然,不一定只有黑白灰才能做出質感,暗色背景與淺灰的搭配,還有按鈕的精緻度也很重要。而精緻這件事情,並不是要你做的多複雜、多花俏,簡單的線條也可能做到精緻的效果,當然這就要看個人的設計功力了。

圖片來源: Blog Design – Mani

3. Google+ Grid – Haraldur Thorleifsson

只要顏色運用得當,色彩繽紛的風格也不會給人雜亂的感覺,反而會覺得很豐富;另外區塊愈大、色彩愈多,留白也變得相對重要。色彩是門學問,以這個網站縮圖的例子來說,即使他用的顏色很多,主要還是繞著紅、綠、藍、黃這四種配色,如果不會掌握明度與彩度, Dribbble 的設計都有提供色碼,可以多多參考運用。

圖片來源: Google+ Grid – Haraldur Thorleifsson

4. Hypo

官方網站要做的有質感,商攝也是重要的因素之一。選出好看的照片做搭配,可以讓網站風格大加分,搭配像木頭架子這樣故事性強烈的畫面,是不是非常賞心悅目又不突兀呢。官方網站有時需要嚴謹的作風因此不能太跳 tone,但是設計師如果可以搭配官方產品做出不一樣的巧思,一定可以讓業主感受到用心。畢竟天下模板一大抄,別人無法複製的卻是你的用心與創意。

圖片來源: Hypo

最後附上我私藏多年的個人網站 🙂

5. PEPPER

誰說十年前的個人網站就不能有質感? PEPPER 是個人網站盛行的時候,我非常喜歡的一個素材網站,撇開當時的環境盛行用 table 排版不談,網站很有主題性,風格也一致,手繪的向量 icon 同樣很精緻,這就像我前面提到的,誰說一定要複雜才叫精緻?簡單俐落的線條也可以呈現出質感。

圖片來源: PEPPER

其他像是復古風、絢麗風…等等的網站,其實概念大同小異。我覺得優質的設計一定要包含:

  • 適當的間距與留白
  • 細緻的物件與元素 (再次強調。簡單的線條也可以呈現細緻感)
  • 細節 (例如區塊的陰影是否會讓畫面有骯髒的感覺,還有按鈕和文字間的比例…等等)
  • 整體的質感

設計是一項值得尊敬的專業,也是一門高深的學問。我絕對不敢說自己會設計,但我期望朝著自己心中優質的設計之路邁進,也希望每個設計師的心中,也有一條自己的優質設計路,用模板也許可以快速地做出一個網站,但事後想想,你真的能自豪地說這是你的設計嗎?

設計也需要設計師的用心與巧思,你可以選擇做出一個很安全的版面讓業主點頭過關,但如果可以在這安全的層面上,加上多一點的質感,我想不僅業主滿意,設計師也會有成就感,這才是工作上的雙贏 :)。

jQuery Ajax API 實作以及 Template 介紹

前陣子在上前端基礎課,有教大家怎麼利用 jQuery AJAX 實現簡單的 CRUD 效果,後來覺得這對初學者來說,應該是個需要反覆思考才能融會貫通的小門檻,剛好最近也有學生對此表示不懂😱,所以就借這篇文章簡單跟大家介紹囉!

我會用在課堂上的教材跟大家拆解語法,但為了避免大家練習時灌爆我的 API,所以我不會透露 API 網址,一律用變數 ajax_url 代替。

什麼是 API

用程式介面(英語:Application Programming Interface,簡稱:API),又稱為應用編程介面,就是軟體系統不同組成部分銜接的約定。

維基百科

對網站開發人員而言,API 就是前後端溝通的一個接口。後端可以透過各種方法操作資料庫裡的資料;但對前端來說,我們該怎麼操作資料呢?我們可以利用後端人員提供的 API(通常是一串網址)去操作資料,只要有了 API,我們就可以用 JavaScript 搭配 AJAX 實現 CRUD 。

如果還是霧煞煞也沒關係,接下來會用程式碼讓大家加深印象,原理神馬的,可以透過實作去了解 😊。

什麼是 CRUD

CRUD 是四個單字的簡稱,就像我們在學 CSS 時一定要會使用選擇器(selector),而後端在學操作資料庫時,一定要先會 CRUD。
這四個單字分別意思為:

  • C:Create (新建資料)
  • R:Read (讀取資料)
  • U:Update (更新資料)
  • D:Delete (刪除資料)

實作留言板的 CRUD

接下來要跟大家分享的是,如何透過前端實作一個留言板,這個留言板要有 CRUD 的功能,就是我們常說的:新增、刪除、修改 留言。

那因為新增留言是我這期學生的期末考題,所以等他們考完試,我會再把新增留言的程式碼放上來,現在我們先來學習刪除、修改,以及顯示留言吧😋

在此先用 Bootstrap 做了一個非常簡單的留言版,你可以在 HTML 裡面看到要放留言的區塊,只有一行 <div class="result"></div> ,其他什麼都沒有。

HTML

在沒有樣板輔助的情況下,我們需要透過 jQuery 語法將 HTML 的字串組出來,因此所有的留言資料、排版,都必須寫在 jQuery 檔案裡。

顯示留言(Read)

顯示留言的邏輯大概是這樣:

  1. 讀取網頁
  2. 透過 jQuery 語法 (AJAX) 得知現在要撈出該 API 裡的資料
  3. 使用 GET 方法撈出資料
  4. 將撈出來的資料,利用 jQuery 改變 DOM 之後,秀在網頁上

轉換成語法則是:

JS

$.ajax是 jQuery 包裝後的函式,因此他的格式都是固定的,我們只要把對應的資料寫進去,如果 url 跟 type(method) 正確,基本上資料都讀得到。

最後再透過 success 偵測資料成功被讀取後,應該要做的事情:
因此留言的資料非常多,所以我們要利用迴圈,將e物件的所有資料顯示出來,並透過append()把資料一筆一筆的接在後面。

組字串時把握兩個原則:

  • 當變數碰到 html 時,需要用+串接
  • 單引號用來包變數與 jQuery 語法,雙引號用來包 HTML 語法

組字串需要耐心跟細心,如果還是看不太懂他們的規則,我會建議先實作再透過開發者工具看 render 出來的 HTML 程式碼,相互對照會更加清楚他們的邏輯。

更新留言(Update)

更新留言的邏輯比較繁瑣一些,如果寫成文字大致如下:

  1. 點擊更新留言的按鈕
  2. 該篇留言會自動變成可編輯的表單,而且表單預設值是原本留言的內容
  3. 輸入完要更新的資料後,按下送出,表單會變回更新後的資料
  4. 如果按下取消,表單會變成原始資料,不會更新

因為有點複雜,所以我錄了一個 GIF 表示整個流程

轉為程式碼,也可以感受到他比 READ 還複雜許多,而且重點是這個程式碼我還沒寫完 哈哈哈 XDDDD

JS

雖然沒有寫完,但是的確可以成功將留言更新,但更新後的樣式如果要用組字串的方式來寫,會太過於繁瑣,所以我後來採用 jQuery Template 實作(後面會再提到如何用 Template 改寫)。

但我們還是要簡單說一下這段程式碼,之後再把樣板加進來會比較好懂。

上述程式碼 highlight 的第 3 ~ 8 行(以下簡稱 A 段),以及 19 ~ 24 行(以下簡稱 B 段),乍看之下其實很類似,但兩個功能大不相同。

A 段代表的是上述邏輯的第二句話:留言會自動變成可編輯的表單,而且表單預設值是原本留言的內容。所以當我點下「更新按鈕」的時候,會利用 A 段將作者、標題、網址 … 等資料存到變數裡,這邊利用的是 DOM 的 text() 方法,接下來在updateTemplate 裡塞入表單元件,可以用 value="" 讓元件預設出現內容,所以在裡面塞入了各個變數。

而 B 段表示的,是當我更新完留言送出之後,會傳至 API 的實際內容。以name變數為例:name = fullMsg.find('.name').val();,將該表單元件的值存了起來,如果要得到元件的值,可以用 val() 方法。

最後再利用 $.ajax 加上 put 這個 type(method),將資料一個一個的傳回去。你可以利用 sucess 印出結果,如果傳送的物件是更新後的結果,表示程式正確。

如果參考我上面寫的文字流程,成功之後應該要讓畫面回到「顯示留言」的樣子,但是如果用這種方法寫,程式碼可能會又臭又長,所以才想用 template 改寫,因此斷尾了 XDDD。但大家有興趣,也可以試著想一下該怎麼把這個功能寫出來唷 🙂

刪除留言(Delete)

相較於更新,刪除真的是簡單許多,我們的 API 設計,是只要得到該留言的 ID 值,就能透過 ID 將留言刪除。

但根據我的 HTML 結構,我是將 ID 寫在最外面,刪除留言則是放在裡面:

HTML

所以點擊「刪除留言」之後,該如何利用 jQuery 找到這一篇文章的 ID 呢?我使用了closest()方法,以「刪除留言」為中心點,找到離他最近的.full-msg

JS

如果成功刪除留言,必須要有一些簡單的回饋,讓使用者知道留言被刪除了 (就和更新留言是一樣的道理)。
只不過刪除比較簡單,我直接讓這一篇留言 fadeOut(),再秀出「留言已刪除」的字即可。


以上就是簡單的 CRUD 操作,希望對大家有所幫助。雖然語法看上去有點複雜,但其實觀念只有兩個,一是利用$.ajax操作 API,二是利用 jQuery 操作 DOM 讓使用者感受到回饋。

有時間會再更新如何使用樣板。我會以「更新留言」為例子,將他改寫成 template 的樣式,因為我們要的功能非常單純,所以我使用的是 jQuery Template,有興趣的朋友可以先閱讀他的官方文件。

超級初心者適用的 JavaScript 觀念 (暫停更新)

最近除了跳級研究 jQuery 之外,也從基礎開始認識 JavaScript,不得不說,歐萊禮真是個恐怖且強大的出版社阿(膜拜),我最近在看歐萊禮出版的「深入淺出 JavaScript」,其實一開始去書店翻找這本書的時候,還對他的排版嗤之以鼻,想說怎麼搞得那麼亂,還用一堆裝可愛的外國人來作對話式教學。

但,事實證明我錯了,利用這種情境 & 對話式的教學,還有摘要的重點,真的是可以讓初學者快速上手啊!!! 所以歐萊禮,請容我深深地跟你道歉,以及至上我最高的敬意 <(_ _)>

那麼以下分享我看了這本書之後導正 & 瞭解的一些觀念,分享給跟我一樣的超級初心者。希望能讓你們在學習 JavaScript 的路上有所幫助!! (高手別來阿 XD )

閱讀進度 CH1 ~ 2

CH1:互動性網站
CH2:儲存資料

  1. alert()也是函數的一種,他是 JavaScript 的內置函數。每個 JavaScript 函數都會用()包住要傳給函數的訊息。
  2. 事件 = 告訴 JavaScript 當使用者在網頁上「做了某件事情」,才會觸發裡面的程式碼。例如onclick(點擊了某個按鈕)就是一種事件。
  3. 函數 = 可以重複執行的程式碼。
  4. if(userName)表示當userName這個變數有值(可以被取得),就執行以下的動作。 var userName = prompt("What is your name?" , "Enter your name here"); if (typeof(userName) !== 'undefined' ) { alert("welcome, " + userName); } 原本在取得變數的部分我是寫if(userName),不過這樣寫很容易讓程式無法執行(感謝 Kuro 指正),如果userName是空值,或是未定義…等一些特殊狀態,裡面的alert()就不會被執行。
    所以改用if typeof(userName)就可以避免這種狀況,以下是另一種範例參考: //or you can change userName as null, undefined var userName = ''; if (typeof(userName) !== 'undefined') { // if(userName){ alert("OK"); } }
  5. JavaScript 的數據類型有變數(variable)以及常數(constant)兩種。變數呼叫方式 var test,常數呼叫方式 const test。常數的值一旦被定義了,就永遠無法被改變。
  6. 變數、常數的標示符 (identifier) 命名須注意事項:
    • 不能重複,是唯一性。
    • 開頭只能用英文字母、下底線_以及錢號$
    • 第二個字母之後可用數字、下底線_以及錢號$
    • 不能使用空格以及其他特殊符號
  7. 變數、常數的標示符 (identifier) 可用「小寫駝峰」作為命名規則:
    – 當有兩個以上的字母組合為標示符時,為了方便識別,可以用大小寫作為區分。例如用flyNumberDate取代fly_number_date
  8. NaN = Not a Number,所以如果為 true,表示他不是數字;為 false,表示是數字。因為一開始就是否定狀態,所以請用負負得正的觀念。
  9. 另外一種用NaN來檢索值是否為數字的寫法: if (isNaN(document.getElementById("xxxxxid").value)) alert("this is not a number");
  10. alert()函數只能儲存string,不能儲存number型態的數字,所以我們會先將數字轉成string再儲存之。
  11. 常數的宣告範例: //常數名稱為全部大寫,以跟變數區分 const TAX = 9;
  12. toFixed(X)用來四捨五入到小數點後 X 位
  13. getElementById是方法,並非函數。
  14. parseFloat()parseInt()都可以幫忙將字串轉成數字

閱讀進度 CH3 ~ 5

CH3:探索用戶端
CH4:決策 (if / else…)
CH5:迴圈

  1. setTimeout()是單次計時器,setInterval()是會一直重複的間歇計時器。
  2. 使用clearInterval()清除重複計時器,使用方法為clearInterval(timerID)
  3. 可以利用document.body.clentHeight取得用戶端視窗的高度。
  4. cookie 會存在同個地方,並用「;」分隔。
    • readCookie():讀取 Cookie
    • writeCookie():寫入 Cookie
    • eraseCookie():清除 cookie
  5. 如須嚴謹判斷瀏覽器是否支援 cookie,可使用navigator.cookieEnabled
  6. 大括號不需分號結尾,分號只用在單一敘述的結尾
  7. for 迴圈適合計數的任務,像是倒數至零,或是倒數至某個數
  8. 如果不知道計數幾次,可改用 while 迴圈。
  9. 如果要在 for 迴圈設定不同的變數,可以使用陣列 array[i]
  10. 一旦 for 迴圈的條件句為false時,迴圈會立刻跳出結束,不會執行裡面的程式碼。
  11. confirm()函式讓使用者回答是或否,並回傳 true / false 值。
  12. break;是跳出整個迴圈;continue;是跳出當前迴圈,並直接進行下一輪迴圈。
  13. 巢狀的 if 判斷可以用 boolean 運算子合併:if(seats[i] && seats[i + 1] && seats[i + 2])
  14. 可以使用巢狀迴圈處理二維陣列的資料: for (var i = 0; i < seats.length; i++) { for (var j = 0; j < seats[i].length; j++) { //something } }

閱讀進度 CH6 ~ 7

CH6:函式
CH7:表單與驗證

  1. 可以傳入任何資料至function(參數),例如常數(Math, PI),變數(temp),或實數(72)。
  2. 函式遇到return;後將立即結束,因此return可用來結束該函式。
  3. 使用某物!=null來判斷某物是否存在
  4. onblur適合作為觸發資料驗證,onchange相較之下,因為如果欄位沒填資料就不會觸發,所以比較不適合。
  5. 要取得表單資料,除了可以使用getElementById()之外,也能使用 form 的物件,例如:
  6. 正規運算式用於比對文字樣式
  7. 正規式用斜線開始和結束,例:/\d/
  8. 同上,正規式是個有點複雜的東西,如果你也有購買此書,正規式的重點從 P.320 開始
  9. 可以用test()方法檢查字串是否符合正規式,以下是一個簡單的郵遞區號(五碼)檢測: var regex = /^\d{5}$/; if(!regex.test(inputField.value)) //郵遞區號格式不正確

閱讀進度 CH8 ~ 9

CH8:利用 DOM 分割 HTML
CH9:物件

  1. 改變節點文字的三步驟:
    1. removeChild(): 移除所有子節點
    2. createTextNode(): 根據新內容,建立新的文字節點
    3. appendChild(): 把新建立的文字子節點,附加在節點下
  2. 承上,寫成 Javascript 為: var node = document.getElementById("story"); while (node.firstChild) node.removeChild(node.firstChild); node.appendChild(document.createTextNode("Some text..."));
  3. CSS class 和 JS class 是兩個完全不同的東西,前者是樣式,後者則是建立 JS 物件的樣板。
  4. 物件中的特性與方法,等於物件外的變數與函式
  5. // 物件名稱.方法名稱(); invitation.deliver();
  6. 建立物件必須要用建構式new,例如: var invitation = new Invitation( "Somebody", "Something" );
  7. Date物件也要用new運算子建立:new Date("06/16/2016")
  8. array.sort()可以做陣列的排序
  9. 要在陣列中做字串比對,可用indexOf(),會回傳比對到的索引值,再利用array[i].body顯示該字串內容。
  10. 使用Math()物件產生亂數,常見的幾個方法如下:
    • round(): 把浮點數四捨五入為整數
    • floor(): 把浮點數無條件捨去為整數
    • ceil(): 把浮點數無條件進位為整數
    • random(): 產生介於 0 ~ 1 之間的亂數,但不包含 1 (可看作 0 ~ 0.9*N 循環的無窮小數)
    做一個亂數擲骰的程式: var oneToSix = Math.floor(Math.random() * 6) + 1;

codyhouse 的 tooltip 線上教學筆記與心得

剛剛收到一封 codyhouse 的線上課程通知,這一期他們推廣的是 CSS animation 應用,好奇點進去後發現有一堂課程是免費的,所以就打開來聽聽看啦 ~

▼ 有 play 可以選的 tooltip 就是這期的免費課程啦

花了半小時聽完後覺得受益良多,雖然講者的口音有點重,但可以把影片字幕打開,也可以直接看程式碼,聽完之後也是對其他付費課程有所心動 XD,非常棒的行銷手法呢,先試聽一堂課喜歡再買 😀

因為他的 youtube 影片連結是公開的,所以我也放一份在我的 blog 裡面,以下是自己聽完做的一些筆記跟重點,很多語法我自己也已實作了,所以看到國外講師也是這樣寫覺得很開心 😊

總之我覺得不錯的語法都會重點摘錄出來給大家參考,希望對你們有所幫助 🌹

筆記與心得

  • aria-hidden:HTML5 語意,用於屏幕閱讀器的,幫助殘障人士更好的訪問網站。(參考來源)
  • 萬年水平垂直置中的另一種方法:
CSS
  • 文字如果要垂直置中,可以將height以及line-height設定成一樣的高度,但文字必須維持一行才有用。
  • 如果不希望hover影響隱藏的元素,可以改用visibility: hidden將元素隱藏,這樣滑鼠移過之後也不會啟動hover效果
  • visibility可以用在transition,但display不行
  • 假設元素的寬度是50px可以善用calc(50% - 25px)將元素置中
  • 利用偽元素製作三角形:
CSS

偶爾聽聽外國人的線上課程也很棒,可以學到很多不一樣的寫法以及詮釋的方法,codyhouse 的範例跟教學品質都很棒,有興趣可以連回他們的網站看更多資料唷: https://codyhouse.co/

從 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 的使用方法,以及該怎麼管理。希望對大家有所幫助囉