2017年8月30日 星期三

animate 草案.....省去 cssHook 方法

$('#box_1').maya({
                left: '80%'
            }, {
                    duration: 800
                }, function () {
                    // init-fun
                    // 取得與目標相同的單位
                    // 如 left: px or %
                    // 若單位不同,程式將自動檢視並不執行
                    return {
                        left: $(this).css('left')
                    };
                }, function (initData, finalData, ratio) {
                    // 每個 tick 會執行
                    // 此函式將隱身在後面
                    var initLeft = parseFloat(initData.left);
                    var final_left = finalData.left;
                    var current_left = (final_left - initLeft) * ratio + left - initLeft;

                    $(this).css({
                        left: current_left + (單位)
                    });
                });

2017年8月22日 星期二

vue2 Event Bus Example

var bus = new Vue();

var vueAwesomeCompare = new Vue({
 ... 
 components:{
    'vue-table':{
       // or mounted
       created:function(){
          bus.$on('popState', function(state){
             self.popState(state);
         });
       },
       methods:{
          popState:function(state){
          ...
         }
      }
    }
  ...
  }
 ...
});

window.onpopstate = function(event){
    bus.$emit('popState',event.state);
};
/////////////////////////////////////////////////////////////////////

var vueAwesomeCompare = new Vue({
      components:{
        'vue-table':{
            template:'#vue-table',
            
            props:[''],
            
            data:function(){
                return {
                    items:null,
                    brands:null,
                    brand:null,
                    comparing:false
                }
            },
       }
      ....
  },
});
console.log(vueAwesomeCompare.$data); //== Object {__ob__: Observer}
console.log(vueAwesomeCompare.$data.brand); //== undefined
console.log(vueAwesomeCompare.brand); //== undefined

/////////////////////////////////////////////////////////////////////
var bus = new Vue();

var vueAwesomeCompare = new Vue({
 ... 
 components:{
    'vue-table':{
       created:function(){
          bus.$on('popState', function(state){
             self.popState(state);
         });
       },
       methods:{
          popState:function(state){
          ...
         }
      }
    }
  ...
  }
 ...
});

window.onpopstate = function(event){
    bus.$emit('popState',event.state);
};

/////////////////////////////////////////////////////////////////////

export default {
      data () {
          return {
              title: '我的',
              headerInfo: []
          }
      },
      mounted: function () {
          this.$bus.on('getMessageCount', this.setMessageCount);
          this.$bus.on('setCenterHeader', this.setCenterHeader);
      },
      methods: {
          setMessageCount: function (params) {
              document.querySelector('.my_message').setAttribute('data-count', params.num)
          },
          setCenterHeader: function (params) {
              this.$set(this.$data, 'title', params.title)// 改变数据并且更新视图
              this.$set(this.$data, 'headerInfo', params)
          }
      }
  }


export default{
    data () {
        return {
            listData: [],
            loading: false,
            currentPageCount: 1,
            pageCount: 0
        }
    },
    mounted: function () {
        this.$bus.emit('setCenterHeader', {title: '消息中心', left: {className: 'back', href: ''}, 'right': {hide: true}})
    }
}

2017年8月17日 星期四

網頁在手機顯示下,要弄側邊 slide 要注意的

html {
        width: 100%;
        height: 100%;
        overflow-x: hidden; /* 不知如何解釋 ,有時沒設 
                                            body.overflow-x 會沒效果 */
    }
    body {
        width: 100%;
        min-height: 100%;
        overflow-x: hidden; /* 超過頁面就 cut 掉 */
        position: relative;
    }

html { overflow:auto;} 是默认的。
如果不设置html height怎么会有滚动条,原来html有点特殊,它的widht和height是有浏览器窗口大小决定的。

几乎所有的浏览器,默认的偏移margin是在body元素上,而不是html的padding.(通过做实验确实如此)有些还是body的padding,所有重置页边距用body{margin:0;padding:0}缺一不可

2017年8月11日 星期五

Promise 擴增,與 簡單的 $Deferred


(function () {

    if (typeof Promise !== 'function') {
        throw new Error('need Promise');
    }
    /*------------------------------------------------------------------------*/
    // promise.done()
    if (typeof Promise.prototype.done === 'undefined') {
        Promise.prototype.done = function (onFulfilled) {
            return this.then(onFulfilled, undefined);
        };
    }

    // promise.doneWith()
    if (typeof Promise.prototype.doneWith === 'undefined') {
        Promise.prototype.doneWith = function (onFulfilled, context) {
            onFulfilled = onFulfilled.bind(context);
            return this.then(onFulfilled, undefined);
        };
    }
    /*------------------------------------------------------------------------*/
    // promise.catchWith()
    if (typeof Promise.prototype.catchWith === 'undefined') {
        Promise.prototype.catchWith = function (onRejected, context) {
            onRejected = onRejected.bind(context);
            return this.then(undefined, onRejected);
        };
    }
    /*------------------------------------------------------------------------*/
    // promise.always()
    if (typeof Promise.prototype.always === 'undefined') {
        Promise.prototype.always = function (callback) {
            return this.then(function (data) {
                callback(false, data);
            }, function (error) {
                callback(true, error);
            });
        };
    }

    // promise.alwaysWith()
    if (typeof Promise.prototype.alwaysWith === 'undefined') {
        Promise.prototype.alwaysWith = function (callback, context) {

            callback = callback.bind(this);

            return this.then(function (data) {
                callback(false, data);
            }, function (error) {
                callback(true, error);
            });
        };
    }
    /*------------------------------------------------------------------------*/
    // setImmediate => process => setTimeout
    var async = typeof setImmediate !== 'undefined' ?
        (function (fn) {
            setImmediate(fn);
        }) : (typeof process !== 'undefined' && process.nextTick ?
            process.nextTick :
            function (fn) {
                setTimeout(fn, 0);
            });

    /*------------------------------------------------------------------------*/
    if (typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = $Deferred;
    } else if (typeof window === 'object') {
        window.$Deferred = window.$Deferred || $Deferred;
    }
    /*------------------------------------------------------------------------*/
    function $Deferred() {
        if (this === window) {
            return new $Deferred();
        }
        var self = this;
        this._reject;
        this._resolve;
        this._promise = new Promise(function (resolve, reject) {
            self._resolve = resolve;
            self._reject = reject;
        });
    }

    (function () {
        this.p = this.promise = function () {
            return this._promise;
        };
        /**********************************************************************/
        this.resolve = function (arg, nextTick) {

            var self = this;

            if (nextTick != null && nextTick === true) {

                var job = (function () {
                    // 避免某些情況有些瀏覽器會叫
                    this._resolve(arg);
                }).bind(this);

                async(job);
            } else {
                this._resolve(arg);
            }
        };
        /**********************************************************************/
        this.reject = function (arg, nextTick) {
            var self = this;
            if (nextTick != null && nextTick === true) {

                var job = (function () {
                    // 避免某些情況有些瀏覽器會叫
                    this._reject(arg);
                }).bind(this);

                async(job);
            } else {
                this._reject(arg);
            }
        };
        /**********************************************************************/
        this.then = function (onFulfilled, onRejected) {
            var def = $Deferred();
            var p = this.promise();

            p = p.then(function (data) {
                return onFulfilled(data);
            }, function (error) {
                return onRejected(error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };

        this.thenWith = function (onFulfilled, onRejected, context) {
            onFulfilled = onFulfilled.bind(context);
            onRejected = onRejected.bind(context);

            var def = $Deferred();
            var p = this.promise();

            p = p.then(function (data) {
                return onFulfilled(data);
            }, function (error) {
                return onRejected(error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };
        /**********************************************************************/
        this.done = function (onFulfilled) {
            var def = $Deferred();
            var p = this.promise();


            p = p.then(function (data) {
                return onFulfilled(data);
            }, undefined);
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };

        this.doneWith = function (onFulfilled, context) {
            onFulfilled = onFulfilled.bind(context);

            var def = $Deferred();
            var p = this.promise();

            p = p.then(function (data) {
                return onFulfilled(data);
            }, undefined);
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };
        /**********************************************************************/
        this.catch = function (onRejected) {
            var def = $Deferred();
            var p = this.promise();

            p = p.catch(function (error) {
                return onRejected(error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };

        this.catchWith = function (onRejected, context) {
            onRejected = onRejected.bind(context);

            var def = $Deferred();
            var p = this.promise();

            p = p.catch(function (error) {
                return onRejected(error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };
        /**********************************************************************/
        this.always = function (callback) {
            var def = $Deferred();
            var p = this.promise();

            p = p.then(function (data) {
                return callback(false, data);
            }, function (error) {
                return callback(true, error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };

        this.alwaysWith = function (callback, context) {
            callback = callback.binf(context);

            var def = $Deferred();
            var p = this.promise();

            p = p.then(function (data) {
                return callback(false, data);
            }, function (error) {
                return callback(true, error);
            });
            /*--------------------------*/
            p.then(function (data) {
                def.resolve(data);
            }, function (error) {
                def.reject(error);
            });
            return def;
        };
    }).call($Deferred.prototype);
})();



2017年8月4日 星期五

30個你必須記住的CSS選擇符

04 January 2014
號外號外:專注於移動端的fullPage.js來啦!!!快點我查看
所以你學會了基礎的id,類和後代選擇符,然後你就一直用它們了嗎?如果是這樣,你丟失了(css的)巨大的靈活性。在本文中提到的很多選擇器屬於CSS3規範的一部分,因此,只有在現代瀏覽器中才可使用。

1.*

* {  
 margin: 0;  
 padding: 0;  
}
對於初學者,在學習更多高級選擇器之前,最先瞭解的選擇器。
星號選擇器將匹配頁面裡的每一個元素。很多開發者使用這個技巧將外邊距和內邊距重置為零。雖然在快速測試時這確實很好用,但我建議你永遠不要再生產代碼中使用它。它給瀏覽器帶來大量不必要的負擔。
* 也能作為子選擇符使用。
#container * {  
 border: 1px solid black;  
} 
這將匹配#container div的每一個後代元素。再次強調,儘量不要使用這種技術。
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

2.#X

#container {  
   width: 960px;  
   margin: auto;  
}  
井號前綴允許我們選擇id。這是最常見的用法,不過應該慎重使用ID選擇器。
反覆問自己:我一定需要id來匹配要選擇的元素嗎?
id選擇符是唯一的,不允許重複使用。如果可能的話,先嘗試使用一個標籤名稱,一個新的HTML5元素,甚至是一個偽類。
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

3. .X

.error {  
  color: red;  
}
現在介紹的是類選擇符。id和類的不同之處在於後者可以多次使用。當你想給一組元素應用樣式的時候可以使用類選擇符。另外,當你緊想給特殊元素應用樣式的時候才使用id。
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

4. X Y

li a {  
  text-decoration: none;  
}
下一個最常用的選擇符是後代選擇符。當你需要給你的選擇符增加特殊性的時候你可以使用。例如,如果你只想匹配無序列表下的錨元素?此時後代選擇符派上用場。
小貼士——如果你的選擇符看起來像這樣 X Y Z A B.error,那你就錯了。時刻問自己使用這高的權重是否有必要。
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

5. X

a { color: red; }  
ul { margin-left: 0; }   
如果你想匹配頁面上的所有的元素,根據他們的類型,而不是id或類名?顯而易見,使用類型選擇符。如果你需要選擇所有的無序列表,請使用ul {}
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera
a:link { color: red; }  
a:visted { color: purple; } 
我們使用:link 偽類選擇符選擇所有已經被點擊過的錨標籤。
此外,我們也有:visited偽類選擇符,正如你期望的,允許我們僅給頁面上被點擊過的或被訪問過的錨標籤應用樣式。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

7. X + Y

ul + p {  
   color: red;  
} 
這被稱作相鄰選擇符。它將只選擇緊貼在X元素之後Y元素。上面的例子,僅每一個ul之後的第一個段落元素的文本為紅色。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

8. X > Y

div#container > ul {  
  border: 1px solid black;  
}  
X YX > Y之間的不同點是後者只選擇直接子代。例如,考慮如下的標記。
<div id="container">  
   <ul>  
      <li> List Item  
        <ul>  
           <li> Child </li>  
        </ul>  
      </li>  
      <li> List Item </li>  
      <li> List Item </li>  
      <li> List Item </li>  
   </ul>  
</div> 
選擇符#container > ul將只選擇id為container的div的直接子代ul。它不匹配更深層的li的子代的ul。
因此,使用子代選擇符有性能上的優勢。事實上,這同樣適用於基於css選擇器的javascript引擎。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

9. X ~ Y

ul ~ p {  
   color: red;  
}  
這是兄弟選擇符和X + Y一樣,然而,它沒有約束。與相鄰選擇符(ul + li)僅選擇前一個選擇符後面的第一個元素比起來,兄弟選擇符更寬泛。它會選擇,我們上面例子中跟在ul後面的任何p元素。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

10. X[title]

a[title] {  
   color: green;  
} 
被稱為屬性選擇器,在我們上面的例子裡,這只會選擇有title屬性的錨標籤。沒有此屬性的錨標籤將不受影像。但如果你需要更多的特性怎麼辦呢?呵呵……
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

11. X[href=」foo」]

a[href="http://net.tutsplus.com"] {  
  color: #1f6053; /* nettuts green */  
} 
上面的代碼段將給所有href屬性為http://net.tutsplus.com的錨標籤添加樣式;他們將會顯示為我們的品牌綠色。所有其他的錨標籤將不受影響。
注意我們將href值用引號包裹。記住,當使用javascript的css選擇符引擎時也這麼做。如果可能的話,儘可能使用css3選擇符代替非官方的方法。
這工作的很好,但有點不夠靈活。如果鏈接確實直接連接到Nettus+還好,但是,也許路徑是到nettust的相對路徑呢?在這種情況下,我們可以使用一點正則表達式語法。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

12. X[href*=」nettuts」]

a[href*="tuts"] {  
  color: #1f6053; /* nettuts green */  
} 
來了不是~這就是我們需要的代碼。*號指定了包含該屬性的值必須包含定義的值。就是說,這句代碼包含了href值為 nettuts.com,net.tutsplus.com或者tutsplus.com。
記住這個描述過於寬泛,如果是某個錨點標籤鏈接到某個連接中帶有tuts非Envato的網站(tutsplus屬於Envato旗下網站)呢?因此你需要更多特性來限制,分別使用^和&來限定字符串的開始和結束。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

13. X[href^=」http」]

a[href^="http"] {  
   background: url(path/to/external/icon.png) no-repeat;  
   padding-left: 10px;  
}   
有沒有想過某些網站是如何定義一個圖標的鏈接的?我確定你肯定看到過。這些鏈接很容易讓你跳轉到另一個網站。
使用^(carat)符灰常簡單啦。這個符號常常在正則表達式中表示字符串的開始。如果我們想指向所有以」http」開頭的」href」屬性的錨點的話,我們就可以使用類似於上面的那段代碼啦。
注意啦,我們不需要搜索」http://」,完全沒必要,因為我們還要包含以https://開頭的鏈接呢。
如果我們想為所有鏈接到圖片的鏈接定義樣式咋辦?這種情況下,我們得搜索字符串的結束了不是。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

14. X[href$=」.jpg」]

a[href$=".jpg"] {  
   color: red;  
}  
又來了,我們還是使用正則表達式符號,$(dolor),來作為字符串的結束標記。這種情況下,我們就會搜索所有url以.jpg為結尾的錨點啦。記住記住這種情況下gif和png格式的圖片不會被選擇哦。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

15. X[data-*=」foo」]

a[data-filetype="image"] {  
   color: red;  
}  
回顧最近一條,我們如何能包含各種圖片類型:png,jpeg,jpg,gif?很容易想到,我們能通過多個選擇器來不是,像這樣:
a[href$=".jpg"],  
a[href$=".jpeg"],  
a[href$=".png"],  
a[href$=".gif"] {  
   color: red;  
} 
不過,這樣很蛋疼,效率極低。另一個解決辦法是使用自定義屬性。如果我們加了一種自己的 data-filetype屬性給每一個鏈接到圖片的錨點的話呢?
<a href="path/to/image.jpg" data-filetype="image"> Image Link </a>  
這樣關聯後,我們就能使用標準的屬性選擇器來指定這些鏈接啦。看下面:
a[data-filetype="image"] {  
   color: red;  
}
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

16. X[foo~=」bar」]

a[data-info~="external"] {  
   color: red;  
}  
  
a[data-info~="image"] {  
   border: 1px solid black;  
} 
這兒有個鮮為人知的特殊技巧,絕對讓你印象時刻。~(tilda)符,它可以幫助我們指向那些以空格隔開多個值的屬性的元素(真拗口,這翻譯我自己都看不懂,水平問題)
以我們第15條的自定義屬性為例,上面的代碼中我們創建了 data-info屬性,這個屬性可以定義以空格分隔的多個值。這樣,這個鏈接本身就是個icon,並且指向的也是一個圖片鏈接,像下面這樣。
<a href="path/to/image.jpg" data-info="external image"> Click Me, Fool </a>  
有了這樣適當的標記,通過使用 ~ 屬性選擇器的技巧,我們就可以指向任何具有著兩種屬性的任何一種啦。
/* Target data-info attr that contains the value "external" */  
a[data-info~="external"] {  
   color: red;  
}  
  
/* And which contain the value "image" */  
a[data-info~="image"] {  
  border: 1px solid black;  
}
很棒,不是嗎?
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

17. X:checked

input[type=radio]:checked {  
   border: 1px solid black;  
}  
這種偽類只會匹配已經被選中的單選元素。就是這麼簡單。
兼容性
  • E9+
  • Firefox
  • Chrome
  • Safari
  • Opera

18. X:after

before 和 after 偽元素也很蛋疼。貌似人們每天都能找到或者發明一些新辦法來有效地使用它們。它們很容易控制選擇器周圍的內容。
很多第一次使用是因為他們需要對clear-fix進行改進。
.clearfix:after {  
    content: "";  
    display: block;  
    clear: both;  
    visibility: hidden;  
    font-size: 0;  
    height: 0;  
}  
  
.clearfix {   
   *display: inline-block;   
   _height: 1%;  
}
這個改進使用了:after偽類元素來在元素後增加一個空間,然後清除它。這個牛X的技巧你應該收藏到工具包裡,特別是當overflow:hidden方法無能為力的時候。
想看看其他創造性的用法:訪問我滴創建陰影的竅門
通過Css3選擇器的標準說明書,你應該有技巧地使用這些偽類語法——雙冒號::。不過為了兼容,瀏覽器會接受一個雙引號。
兼容性
  • IE8+
  • Firefox
  • Chrome
  • Safari
  • Opera

19. X:hover

div:hover {  
  background: #e3e3e3;  
}  
我去,這個你必須懂。典型的官方形式的用戶觸發偽類。聽起來會有點迷惑,不過實際上並非如此。想在用戶在某個元素上面懸停時定義個特別的樣式?這個屬性就是做這個的。
記住啦,較old版本的IE,只能在錨點標籤後使用這個hover。
這個選擇器你用得最多的情況,估計可能就是在錨點的懸停時加個border-bottom啦。
a:hover {  
 border-bottom: 1px solid black;  
}  
小貼士: border-bottom:1px solid black;比 text-decoration:underline;好看一點哦。(真的?我去)
兼容性
  • IE6+ (In IE6, :hover must be applied to an anchor element)
  • Firefox
  • Chrome
  • Safari
  • Opera

20. X:not(selector)

div:not(#container) {  
   color: blue;  
}
not偽類灰常有用。例如我要選擇所有的div,除了有id為container的。上面那個代碼片段就能完美的實現。
如果我想選擇除了p以外的所有元素,我可以這麼做:
*:not(p) {  
  color: green;  
} 
兼容性
  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

21. X::pseudoElement

p::first-line {  
   font-weight: bold;  
   font-size: 1.2em;  
}
我們可以使用偽元素(以::為表示)來定義元素的樣式。例如第一行,第一個字符,記住啦,這種方法只能應用於同級元素才有效。
偽元素由兩個冒號組成:::
指定p的第一個字符的樣式
p::first-letter {  
   float: left;  
   font-size: 2em;  
   font-weight: bold;  
   font-family: cursive;  
   padding-right: 2px;  
}
這段代碼會找到所有段落,然後再從中定義這些段落的第一個字符。
這常常使用在仿報紙的文章首字母樣式。
**指定p的首行樣式 **
p::first-line {  
   font-weight: bold;  
   font-size: 1.2em;  
} 
同樣,這個::first-line偽元素會像我們期望的那樣,只定義段落的第一行的樣式。
兼容性
  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

22. X:nth-child(n)

li:nth-child(3) {  
   color: red;  
} 
想想那些沒法從元素堆中選擇元素的日子。nth-child偽類解決了這個問題。
請注意 nth-child接收整數和變量,不過不是從0開始的,如果你想選定第二個li,使用 li:nth-child(2).
我們甚至使用這個辦法來選擇任意的子元素。例如,我們可以用 li:nth-child(4n)來完成4為倍數的所有元素的選擇。
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari

23. X:nth-last-child(n)

li:nth-last-child(2) {  
   color: red;  
} 
如果我有灰常多的li在ul裡面,我只想要最後3個li怎麼辦?不必使用li:nth-child(397),你可以使用nth-last-child偽類。
這種技巧和第六條幾乎一樣有效,不過兩者的不同之處在於它從結束開始收集,用回溯的方式進行。
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

24. X:nth-of-type(n)

ul:nth-of-type(3) {  
   border: 1px solid black;  
}
你應該有很多時候想要元素類型來選擇元素而不是通過孩子。
想像一下標記5個無序列表(UL)。如果你想定義第三個ul,並且沒有一個唯一的id來找到它,你就可以使用 nth-of-type(3)偽類了。在上面這個代碼段中,只有第三個ul才會有黑色的邊框。
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari

25. X:nth-last-of-type(n)

ul:nth-last-of-type(3) {  
   border: 1px solid black;  
} 
沒錯,我們一樣可以使用nth-last-of-type來從結束開始回溯這個選擇器,來找到我們想要的元素
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

26. X:first-child

ul li:first-child {  
   border-top: none;  
}  
這個結構的偽類讓我們可以選擇某個元素的第一個子孩子。你通常可以使用這個辦法來刪除第一個或者最後一個元素的邊框。
例如,你有一系列的rows,每一個都有border-top 和border-bottom。這種情況下,第一行和最後一行看起來會灰常怪。
很多設計師會使用first和last類來彌補這個缺陷。相反,你可以使用這些偽類來解決這些問題。
兼容性
  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

27. X:last-child

ul > li:last-child {  
   color: green;  
}
first-child相反,last-child會選擇父節點的最後一個子節點。
例子:
我們建立一些例子來示範這些類的可能的用法。我們會建立一種風格來展示。
標記
<ul>  
   <li> List Item </li>  
   <li> List Item </li>  
   <li> List Item </li>  
</ul> 
沒啥特別的,就是一個簡單的序列。
Css
ul {  
 width: 200px;  
 background: #292929;  
 color: white;  
 list-style: none;  
 padding-left: 0;  
}  
  
li {  
 padding: 10px;  
 border-bottom: 1px solid black;  
 border-top: 1px solid #3c3c3c;  
} 
這個樣式會設置一個背景,刪除瀏覽器默認的ul的padding值,並定義邊框給每一個li來提供一點深度。
如上圖所示,唯一的問題是最上面的邊框和最下面的邊框看起來有點兒怪。讓我們來使用:first-child:last-child來解決這個問題。
li:first-child {  
    border-top: none;  
}  
  
li:last-child {  
   border-bottom: none;  
} 
看上圖,解決了不是。
兼容性
  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera
是滴,IE8支持 first-child 不過不支持last-child。

28. X:only-child

div p:only-child {  
   color: red;  
}
實話說,你很可能會發現你不會經常使用 only-child偽類。儘管如此,它確實有用,你應該需要它。
它可以幫助你選擇是父節點的獨生子(沒別的孩子啦)的元素。例如,使用上面的代碼,只有是div的唯一子孩子的p段落才會定義其顏色為red。
讓我們來假定下面的標記。
<div><p> My paragraph here. </p></div>  
  
<div>  
   <p> Two paragraphs total. </p>  
   <p> Two paragraphs total. </p>  
</div> 
這樣,第二個div的p標籤的內容不會被選中。只有第一個div的p才會被選中。
兼容性
  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

29. X:only-of-type

li:only-of-type {  
   font-weight: bold;  
} 
這種結構的偽類有幾種灰常聰明的用法。它可以選定在其父節點內沒有兄弟節點的元素。例如,我們可以選擇只有一個li作為其子孩子的ul。
首先,取決於你想怎樣完成這一目標。你可以使用 ul li,不過,這回選擇所有li元素。唯一的辦法是使用only-of-type
ul > li:only-of-type {  
   font-weight: bold;  
}
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

30. X:first-of-type

first-of-type 偽類可以讓你選擇該類型的第一個兄弟節點。
一個測試
為了更好地理解它,讓我們來測試一下啊。拷貝下面的標記到你的編輯器。
<div>  
   <p> My paragraph here. </p>  
   <ul>  
      <li> List Item 1 </li>  
      <li> List Item 2 </li>  
   </ul>  
  
   <ul>  
      <li> List Item 3 </li>  
      <li> List Item 4 </li>  
   </ul>     
</div>  
現在,別急著往下讀,試試看如何能只選擇』LIST ITEM 2』?如果你搞定了(或者放棄了),繼續讀。
解決辦法1
有很多辦法能搞定這個測試。我們回顧其中一小部分。以使用first-of-type開始。
ul:first-of-type > li:nth-child(2) {  
   font-weight: bold;  
} 
這個代碼段本質上表示,「找到第一個無序列表,然後找到這裡面的li,然後,繼續使用過濾器直到找到第二個li。
解決辦法2
另一個可行的辦法是毗鄰選擇器。
p + ul li:last-child {  
   font-weight: bold;  
} 
在這個方案中,我們找到p的臨近節點ul,然後找到ul的li的最後一個孩子。
解決辦法3
我們可以隨心所欲滴選擇這些選擇器。
ul:first-of-type li:nth-last-child(1) {  
   font-weight: bold;     
}
這次,我們取到第一個ul,然後找到第一個元素,不過是從最後一個開始數。哈哈。
兼容性
  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

結論

如果你仍在為解決old瀏覽器的缺陷而糾結,如IE6。在使用這些新的選擇器方面,你仍然需要非常小心。不過,別因為這個阻礙了你對這些新玩意兒的學習。別虐待自己。確保關注這裡的兼容性列表。應一方面,你可以使用 Dean Edward's excellent IE9.js script 來為舊瀏覽器提供新的選擇器支持。(我去。cool)
其次,當使用javascript庫時,如流行的jQuery,最好儘可能使用這些css3本身的選擇器而不是使用庫的自定義方法/選擇器。這能讓你的代碼更快哦,因為這些選擇器引擎本身就能被瀏覽器解析,而不是用這些庫選擇器。
感謝閱讀,希望你能學到一兩個技巧。

譯者注

本文問翻譯文章,原文為「The 30 CSS Selectors you Must Memorize
歡迎訂閱我的微信公眾帳號,只推送原創文字。掃碼或搜索:顏海鏡