Stylus彷佛並非頗有名,以致於不少人不知道它,但提到SASS相信有很多人據說過甚至使用過很長時間。其實不管是LESS、SASS仍是Stylus甚至是Absurd這些預處理工具,都是對CSS的一種延伸和強化。出現這些工具的緣由很簡單,CSS自己只是一種描述性質的東西,甚至它不能算是語言而是樣式表,因此咱們須要一個有條件語句和變量甚至是函數的東西去動態生成CSS代碼來達到提升效率和加強可維護性的目的。css
本文主要以Stylus語法自己和簡單的使用爲主要內容,它的目的是介紹和簡單指南。將不會過多涉及Javascript的API調用等問題。html
官方的介紹很是簡短而精煉:前端
Expressive, dynamic, robust CSSgit
富有表現力的動態的強壯的CSS,它反應了一些主要特色。github
首先Stylus相較於SASS更加簡潔,甚至冒號也均可以省略,初學Stylus時感到它太神奇了,僅僅以空格分隔屬性名和多個屬性值就能夠生成想要的CSS,並且還能夠拼接字符串等等。與此同時,相似Ruby或Python完善的縮進語法,Stylus在簡約自由中有效的防止了語法歧義。web
body border 10px*.1 soli+'d' darken(red,10%) // => body { border: 1px solid #e60000; }
其次是動態,這正是其精髓所在,Stylus由Javascript編譯,其結構語句也和Javascript相差很少,前端人員能夠很輕鬆的上手。雖然這方面Absurd是一個極端,但Stylus較之LESS則要優越很多,不只僅是可定義變量,如Javascript般的條件語句和循環語句也爲Stylus帶來各類可能,加上豐富的內置函數,能夠輕鬆判斷和操做各類變量。而利用這樣的動態性,就能夠寫出很是強壯的CSS以知足不一樣環境和條件下的須要。npm
pos(type, args) i = 0 position unquote(type) {args[i]} args[i + 1] is a 'unit' ? args[i += 1] : 0 {args[i += 1]} args[i + 1] is a 'unit' ? args[i += 1] : 0 absolute() pos('absolute', arguments) fixed() pos('fixed', arguments) #prompt absolute top 150px left 5px width 200px margin-left -(@width / 2) #logo fixed top left // => #prompt { position: absolute; top: 150px; left: 5px; width: 200px; margin-left: -100px; } #logo { position: fixed; top: 0; left: 0; }
能夠看到上面的代碼中使用了Mixin(混合)還有三目運算符等手段構建了一個針對position的方法,用來快速生成一個定位代碼片斷。有底向上來看這段代碼,#prompt和#logo是2個ID選擇器,在其中調用了一些Mixin,其實Mixin與Function的區別在於,Mixin的內容是一段CSS代碼,而Function應該是一個值並自動返回,因此調用它們的時候,前者將會替換爲一段CSS,然後者將返回一個Boolean或者像素或者顏色之類的東西,也許用於判斷也許直接放入CSS。而後其中的absolute和fixed分別調用了pos這個Mixin。數組
並且在調用時,也不必定要使用括號的形式,可使用CSS的形式,直接Mixin名加空格而後寫參數。因此有時候能夠直接寫一個Mixin來修改CSS屬性的功能,好比看看下面這個兼容全部標準瀏覽器陰影的寫法,能夠很方便的爲標準調用加上各標準瀏覽器的前綴:瀏覽器
box-shadow() -webkit-box-shadow arguments -moz-box-shadow arguments -ms-box-shadow arguments -o-box-shadow arguments box-shadow arguments box-shadow 2px 1px 10px red // => -webkit-box-shadow: 2px 1px 10px #f00; -moz-box-shadow: 2px 1px 10px #f00; -ms-box-shadow: 2px 1px 10px #f00; -o-box-shadow: 2px 1px 10px #f00; box-shadow: 2px 1px 10px #f00;
能夠看到調用時的寫法與通常的寫法同樣,可是由於Mixin的存在,box-shadow再也不是一個屬性,能夠變成5行帶有各瀏覽器前綴的CSS。不只僅是box-shadow,CSS3的許多屬性都須要添加前綴,那是否是能夠更近一步呢,來寫一個前綴Mixin吧:sass
// add prefix for attribute prefix(p_attr, argu...) $pfs = webkit moz ms o for $pf in $pfs -{$pf}-{p_attr} argu {p_attr} argu // box shadow mixin box-shadow() prefix(box-shadow, arguments) // run box-shadow 2px 1px 10px red
如同其餘CSS預處理工具同樣,Stylus在顏色方面也擁有許多內置函數,不管是判斷,提取仍是修改都十分強大。函數 red
, blue
, green
, alpha
將分別返回顏色對應的rgba值,dark
和 light
用於判斷顏色屬於亮色仍是暗色,hue
, saturation
, lightness
則分別返回顏色的色相、飽和度以及亮度,其中色相是在色環上的角度,單位是deg。我常常用的是lighten
和 darken
這兩個函數,其做用是增長或減小一個顏色的亮度,另外還有飽和度的操做函數 desaturate
和 satucate
。
彷佛沒有用於修改色相的函數,不過這個需求很容易經過其餘辦法搞定。首先使用hue等函數將原始色的色相、飽和度、亮度以及透明度取出,而後對色相的角度進行修改,好比加90deg,最後再使用hsla函數,把去除的對應值看成參數傳入便可。下面用一組三態按鈕來舉個栗子:
See the Pen Single Button by Zhang zhengzheng (@tychio) on CodePen
能夠看到Stylus中的第一行代碼 $clr = #99ff22
只要修改這個顏色值就能夠改變按鈕的總體風格,並沒有需考慮hover和active狀態時對應的顏色。好比邊框使用 darken
來加深,陰影泛光可使用 lighten
來加亮,在觸碰時總體使用了 saturate
來改變飽和度,按下的Active狀態我使用了 invert
函數,能夠翻轉顏色,在視覺設計中這個顏色叫作對位色,即色相處於色環的對面的兩種顏色,好比綠對紅,黃對藍,例子中使用了黃綠,因此對位色就是紫色。固然也可使用上面提到的複雜一些的方法來修改色相,達到使用間隔色之類的效果。
對於響應式的支持,Stylus的media也能夠省略花括號,但和Sass有一些區別。Stylus在@media的括號中會原樣輸出,也就是說,咱們不能使用變量或混合還有計算等手段來直接寫media query。好比通常狀況下須要寫一個min-width,若是這樣寫
$mobiWidth = 768px @media screen and (min-width $mobiWidth - 1px) body margin 0
產生的CSS代碼則仍然是
@media screen and (min-width $mobiWidth - 1px) { body { margin: 0; } }
這不是一個bug,儘管在Github上有無數的人提出issue或者在其後+1,做者仍然不爲所動,緣由不明,不過幸運地是有不少人都提出解決辦法,下面是一個比較好的方法:
media() join(' and ', arguments) $mobiWidth = 768px $media = media('screen', '(min-width: ' + ($mobiWidth - 1px) + ')') @media $media body margin 0 /// => @media screen and (min-width: 767px) { body { margin: 0; } }
這樣就可使用變量來做爲media的參數了,只是寫起來會比sass麻煩一些,但我以爲這樣也許更自由,你能夠改進這個方法,好比傳一個object來做爲query條件,而不是拼接一個字符串。另外這個方法還用到了 join
內置函數,和Javascript中的Array方法join同樣,很容易使用,除了它還有 push
, unshift
函數。
關於數組的定義,對於響應式來講有很是好的幫助,由於響應式每每是一系列的尺寸或設備,不管如何,使用數組能夠輕鬆的定義多組對應與索引的配套值。好比個人blog,對於不一樣寬度的設備中有不一樣的內容寬度以及邊距,來看看簡化的代碼:
$screen = 1920px 1280px 1024px 768px 640px 320px $width = 1600px 1080px 840px 600px 480px 300px $margin = 180px 100px 80px 40px 20px 0 media() join(' and ', arguments) responsive(p_index) body width $width[p_index] margin-left $margin[p_index] responsive(0) for $i in 0 1 2 3 4 5 $media = media('screen', '(max-width: ' + $screen[$i] + ')') @media $media responsive($i) // => body { width: 1600px; margin-left: 180px; } @media screen and (max-width: 1920px) { body { width: 1600px; margin-left: 180px; } } // ... @media screen and (max-width: 320px) { body { width: 300px; margin-left: 0; } }
固然響應式不是簡單的改變尺寸,若是你須要控制某些內容的顯示則可使用一個Boolean的數組來判斷是否顯示,控制結構或樣式則能夠字符串的數組來放置一些預先寫好的Mixin名稱。
對於CSS Sprite相信是全部切圖者的主要工做產出,之前我也推薦過一些在線的製做Sprite的工具,不過如今有了Stylus,也許咱們可能更快的完成這一切。以前公司有須要國旗icon,因此作了這個小項目national_flag用來建立和維護國旗icon的CSS Sprite。因爲國家數目衆多,每一個國家對應一個國家代碼,因此我定義了一個二維數組用來表現圖片中國旗的位置,而後在數組中填入代碼,用來拼接圖標的class名稱,而後按照數組中的序號和尺寸就能夠生成對應的background-position了。主要代碼以下:
iconBuild(id, col, row) .country-{id} background-position (0px - (row * $size)) (0px - (col * $size)) /*r /c-> 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16*/ $row00 = CN AF AZ BH BD BN KH TL IN ID IR IQ IL JP JO KZ KW $row01 = KG LA LB MY MV MN MM NP KP OM PK PS PH QA SA SG KR $row02 = LK SY TJ TH TM AE UZ VN YE DZ AO BJ BW BF BI CM CV $row03 = CF RO KM CG CI CD DJ EG GQ ER ET GA GH GN GW KE LS $row04 = LR __ MG MW ML MR MU MA MZ NA NE NG RW ST SN SC SL $row05 = SO ZA SD __ TZ __ TG TN UG ZM ZW __ __ __ __ __ __ $row06 = JM PR DO KN VC LC TT CR __ SV GT HN NI PA __ DE __ $row07 = MK AT __ __ __ BG CY __ __ DK SK SI ES EE FI FR __ $row08 = GR HU IE IS IT LV LI LT LU MT MD MC ME NO NL PL PT $row09 = UK CZ __ RU SM __ SE CH TR UA EU __ CA __ MX __ US $row10 = AR BO BR CL CO EC GY __ __ PE __ UY VE HK LY NZ RS $row11 = PY AU SR TJ FM AI __ __ __ __ __ __ __ __ __ __ __ $pos = $row00 $row01 $row02 $row03 $row04 $row05 $row06 $row07 $row08 $row09 $row10 $row11 for $rowList, $row in $pos for $country, $col in $rowList if $country != __ iconBuild($country, $row, $col)
其中for不一樣於Javascript,rowList爲數組遍歷出的一個元素,而$row爲索引,能夠這樣理解 for [value], [index] in [array]
。因此能夠在兩個嵌套的for中獲取縱橫的位置以及國家代碼,來生成CSS。
做爲預處理工具,Stylus天然也須要預處理器,不過它不像Sass須要Ruby環境,Stylus由Javascript實現,因此有Javascript就能夠處理Stylus。
不過說處處理文件,Grunt仍是個人最愛,尤爲Stylus是由Javascript實現,在Nodejs中天然是得天獨厚。npmjs上有許多用來處理Stylus的插件,下面簡單介紹一下Grunt的官方Stylus插件grunt-contrib-stylus。先來看看最簡單的配置方法:
stylus: { compile: { files: { 'path/to/result.css': 'path/to/source.styl' } } }
如此就能夠利用Grunt將source.styl文件中的Stylus代碼編譯爲result.css的CSS代碼。固然還可使用數組來進行多個Stylus文件的打包編譯。固然不只於此,先來看看主要的幾個配置項:
paths
將自動使用@import來引入一些Stylus文件,好比一些Mixin集合,放在一個Stylus文件中進行維護,寫在paths中後,就能夠在每一個Stylus文件中調用它們。define
能夠定義一些全局變量,而後在Stylus中使用,但我不喜歡使用這個配置,而是更喜歡把全局變量放在一個單獨的Stylus文件中,而後將這個文件加入paths的數組中。一句話,把全部不會直接產出CSS的Stylus代碼分紅若干個Stylus文件,而後所有添加到paths中,這樣在全部Stylus文件中均可以隨時調用了,但要注意這些Stylus文件的調用關係和使用前後順序。
compress
及 linenos
是兩個Boolean值,用來控制是否壓縮處理後的CSS代碼以及是否在CSS代碼中保留註釋。
banner
是一個字符串,會被放置在CSS文件的最前面,通常我用來寫註釋,好比
banner: '\/** \n * <%= pkg.name %> - <%= pkg.description %>\n * version <%= pkg.version %> \n * author <%= pkg.author %> \n * date <%= grunt.template.today() %> \n**/\n'
firebug
將控制是否使用一個Firebug的Stylus插件FireStylus for Firebug,能夠在Firefox中調試Stylus。
use
能夠引入一些Stylus的其餘grunt插件。
配合watch等Grunt插件就能夠達到自動化的Stylus開發,寫樣式將會很是有效率。
Stylus是一個由Javascript實現的CSS預處理工具,文件後綴爲styl,其擁有變量、函數、混合、條件及循環語句等功能,還有豐富的內置函數用於處理顏色、數字、數組等數據。在grunt的輔助下,Stylus將帶來極大的開發效率。
原文地址: http://www.tychio.net/tech/2013/11/16/stylus-guide.html