2013-02-05 24 views
6

爲了得到IE 6/7/8 CSS3效果(邊界半徑,箱陰影......),我使用css3piecss3pie弄亂了DOM,結果在jQuery選擇錯誤

但是,css3pie在DOM中生成一些css3-container (v1)/css3pie (v2)標記,這會使預期的體系結構出現混亂。這裏有一個例子:

CSS

pre { 
    border: 1px solid #aaa; 
    border-radius: 5px; 
    behavior: url(pie.htc); 
} 

HTML

<div class="foo">bar</div> 
<p class="getme">paragraph</p> 
<pre>preformatted</pre> 

jQuery的

// undefined  expected: getme 
alert($("pre").prev().attr("class")); 

// css3-container expected: p 
alert($("pre").prev()[0].tagName); 

// getme   expected: foo 
alert($("pre").prev().prev().attr("class")); 

// 4    expected: 3 
alert($("body").children().size()); 

// will not set  expected: Impact 
$("p+pre").css({fontFamily: "Impact"}); 

// it almost affects all such jQuery selctors 

實際根兒如下:

<DIV class="foo">bar</DIV> 
<P class="paragraph">paragraph</P> 
<css3-container...> 
    <border...> 
     <shape...><stroke></stroke><stroke></stroke></shape> 
    </border> 
</css3-container> 
<PRE>preformatted</PRE> 

有沒有人遇到過這種問題?任何解決方法?有沒有替代css3pie讓CSS3在IE 6/7/8上工作?

+0

這不值得。 IE 6和7不支持微軟,那麼爲什麼你要支持他們100%? :)但嚴重的是 - 對於使用大多數互聯網看起來很糟糕的瀏覽器的人來說,圓角都很重要?使它與圓角一起工作會損害性能,並可能使舊站點無法使用該站點。 – naugtur

回答

3

我也嘗試過使用CSS3PIE,並面臨類似的問題(主要與jQuery和媒體查詢)。事實上,我找不到任何簡單/實用的解決方案。

我的建議是使用Modernizr's load逐步增強舊版IE的用戶體驗。它需要更難/更長的過程,因爲您必須爲每個CSS3功能設置單個polyfill。由於mario.tco已經告訴你,Modernizr的回購有list of cross-browser polyfills。這裏有一個feature detection片段的列表。

也看看html5pleasecaniuse

關於IE6和7,除非您的網站統計信息指出不同的東西,否則使用率爲below 1% on average(有些例外,請檢查ie6countdown),因此您幾乎可以忽略它們。但是,對於conditional comments,您可以針對每個具有特定回退的IE版本。

請記住,您並不需要在IE <上使用盒子陰影和其他視覺裝飾(除非它們是可用性所必需的)。事實上,任何回退都可能導致巨大的性能問題(想想IE7用戶可以擁有哪些硬件)。 Websites don't need to look exactly the same in any browser

+0

只要我們想要在舊版瀏覽器上看起來奇怪,看起來這是一個無法解決的問題。我實際上從我的項目中刪除了css3pie,就像@naugtur說的那樣......這不值得。好...我必須選擇一個接受的答案,並且您提供的信息似乎很有用。 – user1643156

+0

謝謝@ user1643156,祝你的項目順利 – Giona

0

而不是僅僅使用原始prev()添加CSS選擇器,它縮小搜索

$("pre").prevUntil('p').attr("class"); 
// OR 
$("pre").prevUntil('.paragraph').attr("class"); 

如果你打算使用CSS3「黑客」以6/7/8正確的行爲使IE當走DOM時,不要試圖依賴預期的DOM結構,試圖更具體。

編輯

改爲prevUntil()prev()函數調用

+0

'prev('p')''或'prev('。段落')'將**不工作,因爲'jQuery引用:prev() - 立即獲取** **兄弟之前...應該是使用'prevUntil'。但是......如果prev元素是未知的呢? – user1643156

+0

感謝您指出 - 我更新了我的答案 - 在這種情況下,我認爲您可能需要更少地依賴於DOM結構,如果它將在您採取行動之前進行更改。 –

2

CSS3PIE是模擬CSS3圓角一個非常有用和強大的方式 - 在我的公司這是我們選擇的一個,但有有很多其他的方式來做到這一點。

CSS3PIE創建圓角的方式會創建<css3-container>標記,作爲具有behavior屬性的元素的前一個兄弟元素,因此它將更改DOM結構並打破prev()調用。 CSS容器非常重要,因爲它是<pre>標籤後面的圓角背景的VML圖。你可以這樣做

一種方法是來包裝你<pre>標籤別的東西像<div>,然後使用<div>使用prev()功能導航DOM。

你可以做到這一點的另一種方式是創建這樣

/* This adds a plugin prevPie and nextPie - it is the same as the 
    existing prev and next, but it will ignore css3-containers. */ 
(function($){ 
    function addPlugin(name) { 
     $.fn[name + 'Pie'] = function() { 
      var result = []; 
      this[name]().each(function(i,el){ 
       if (el.tagName == 'css3-container') { 
        var val = $(el)[name]()[0]; 
        val && result.push(val); 
       } else { 
        result.push(el); 
       } 
      }); 
      return $(result); 
     } 
    } 
    addPlugin('prev'); 
    addPlugin('next'); 
})(jQuery); 

一個jQuery插件,現在下面的工作應該像你希望它在所有瀏覽器。

// undefined  expected: getme 
alert($("pre").prevPie().attr("class")); 
// css3-container expected: p 
alert($("pre").prevPie()[0].tagName); 

// getme   expected: foo 
alert($("pre").prevPie().prevPie().attr("class")); 
// P    expected: div 
alert($("pre").prevPie().prevPie()[0].tagName)); 
+0

你的插件可以解決這個特定的'prev'問題。但是css3pie仍然存在很多問題,它幾乎影響了所有的jQuery選擇器......例如, $(「body」)。children()。size()'將在我的例子中返回4而不是3。編寫一個插件來解決所有這些錯誤似乎不是一個完美的解決方案。 – user1643156

+0

是的,總的來說,我已經瞭解到在使用css3pie時使用這些類型的選擇器並不是一個好主意。當測試你的代碼時,只要確保你每次測試IE都是因爲這些問題。你可能想要做的一件事是在你需要查找或計算的大多數元素上提供類名,並在你的選擇器中使用這些類名,這樣無論這些額外的css3容器元素如何,它都會工作。 – codefactor

+0

感謝您的回覆,codefactor。但問題是,有時我們不知道id/class,prev元素可能完全不知道。至於圓角和陰影,我可以做一些額外的工作來使用IE 6/7/8的圖像編寫插件,但實際上並不是那麼絕望。因此,直到有人提出了一個完美的解決方案,我想我必須從我的應用程序中刪除css3pie。 – user1643156

1

這可能不是你要找的答案,但不是試圖讓jQuery的忽視PIE的注入元素,我建議(重新)編寫的jQuery使用類/ IDS越來越少依賴在頁面結構上。這有利於使您的代碼更適應其他頁面結構更改,並使代碼更具可移植性和可重用性。

當你必須遍歷DOM,大部分(如果不是全部)jQuery's traversal methods包括過濾器,選擇參數,你可以用它來排除PIE的元素,例如:

$("pre").prevUntil('*', 'not(css3-container)') 

$("body").children('not(css3-container)')