Tarayıcılar neden CSS seçicileri sağdan sola eşleştiriyor?


560

CSS Seçicileri, tarayıcı motorları tarafından sağdan sola eşleştirilir. Bu yüzden önce çocukları bulurlar ve daha sonra kuralın geri kalan kısmıyla eşleşip eşleşmediklerini görmek için ebeveynlerini kontrol ederler.

  1. Bu neden?
  2. Sadece spec söylediği için mi?
  3. Soldan sağa değerlendirildiyse nihai yerleşimi etkiler mi?

Bana göre bunu yapmanın en basit yolu, en az sayıda öğeye sahip seçicileri kullanmak olacaktır. Önce kimlikler (sadece 1 öğe döndürmeleri gerektiği için). Sonra sınıflar veya en az sayıda düğüme sahip bir öğe olabilir - örneğin, sayfada yalnızca bir açıklık olabilir, bu nedenle açıklığa başvuran herhangi bir kuralla doğrudan bu düğüme gidin.

İşte iddialarımı destekleyen bazı bağlantılar

  1. http://code.google.com/speed/page-speed/docs/rendering.html
  2. https://developer.mozilla.org/en/Writing_Efficient_CSS

Öyle görünüyor ki bir çocuğun tüm ebeveynlerinden ziyade ebeveynin tüm çocuklarına (çok sayıda olabilir) bakmak zorunda kalmamak için bu şekilde yapılır. DOM derin olsa bile, RTL eşleştirmesinde çoklu değil, seviye başına yalnızca bir düğüme bakar. CSS seçicileri LTR veya RTL'yi değerlendirmek daha kolay / hızlı mı?


5
3. Hayır - nasıl okursanız oku, seçici her zaman aynı eleman kümesiyle eşleşir.
Šime Vidas

39
Değeri ne olursa olsun, bir tarayıcı kimliklerinizin benzersiz olduğunu varsayamaz. DOM'nuzun her yerine aynı id = "foo" yapıştırabilirsiniz ve bir #fooseçicinin tüm bu düğümlerle eşleşmesi gerekir. jQuery, $ ("# foo") öğesinin her zaman yalnızca bir öğe döndüreceğini söyleme seçeneğine sahiptir, çünkü kendi API'lerini kendi kuralları ile tanımlarlar. Ancak tarayıcıların CSS uygulaması gerekir ve CSS belgedeki her şeyi verilen kimlikle eşleştirdiğini söyler.
Boris Zbarsky

4
@Quentin Bir "uyumsuz" (HTML'ye) belge kimlikleri benzersiz olmayabilir ve bu belgelerde CSS tüm öğelerin bu kimlikle eşleştirilmesini gerektirir. CSS'nin kendisi kimliklerin benzersiz olmasına ilişkin normatif gereklilikler getirmez; alıntı yaptığınız metin bilgilendiricidir.
Boris Zbarsky

5
@Boris Zbarsky jQuery'nin yaptığı, jQuery içindeki kod yoluna bağlıdır. Bazı durumlarda, jQuery NodeSelector API'sını (yerel querySelectorAll) kullanır . Diğer durumlarda Sizzle kullanılır. Sizzle birden fazla kimlikle eşleşmiyor, ancak QSA eşleşiyor (AYK). İzlenen yol seçiciye, içeriğe, tarayıcıya ve sürümüne bağlıdır. jQuery's Query API, "Önce Yerel, Çift Yaklaşım" olarak adlandırdığım şeyi kullanır. Bununla ilgili bir makale yazdım, ama bitti. Burada bulabilmenize rağmen: fortybelow.ca/hosted/dhtmlkitchen/JavaScript-Query-Engines.html
Garrett

5
Hiç kimsenin emin değilim ama siz ikiniz, bu uzun konuşmada neler olup bittiğini anlayabilirsiniz. Bu genişletilmiş tartışmalar için sohbet ediyoruz. Gerçekten saklamak istediğiniz her şey, özellikle de bilgiyi netleştiriyorsa, soruya veya cevaba konulmalıdır. Yığın Taşması yorumlardaki tartışmayı iyi işlemez.
George Stocker

Yanıtlar:


824

Bir tarayıcı eşleşen bir eşleştirme yaparken, bir öğeye (stili belirlemeye çalıştığı) ve tüm kurallarınıza ve seçicilerine sahip olduğunu ve öğenin hangi kurallarla eşleştiğini bulması gerektiğini unutmayın. Bu, sadece bir seçicinizin olduğu ve bu seçiciyle eşleşen tüm öğeleri bulmanız gereken olağan jQuery şeyinden farklıdır.

Bu seçiciyle karşılaştırmak için yalnızca bir seçiciniz ve yalnızca bir öğeniz varsa, soldan sağa bazı durumlarda daha mantıklıdır. Ama bu kesinlikle var değil tarayıcının durum. Tarayıcı Gmail'i veya her şeyi oluşturmaya <span>çalışıyor ve biçimlendirmeye çalıştığı kurallara sahip ve Gmail'in stil sayfasına koyduğu 10.000'den fazla kural (bu numarayı oluşturmuyorum).

Özellikle, durumda tarayıcı o gözönünde seçicileri en bakıyor yok söz konusu öğeyi eşleşecek. Böylece sorun, bir seçicinin olabildiğince hızlı eşleşmediğine karar vermekten biri oluyor; bu, eşleşen durumlarda biraz ekstra çalışma gerektiriyorsa, eşleşmeyen durumlarda kaydettiğiniz tüm çalışmalar nedeniyle hala kazanırsınız.

Seçicinin en sağ kısmını öğenizle eşleştirerek başlıyorsanız, eşleşmeyeceği ve işiniz bitmiş olabilir. Eşleşirse, daha fazla iş yapmanız gerekir, ancak ağaç derinliğinizle orantılıdır, bu çoğu durumda o kadar büyük değildir.

Öte yandan, seçicinin en sol kısmını eşleştirmeye başlarsanız ... neyle eşleştiriyorsunuz? DOM ile yürümeye başlamalı, onunla eşleşebilecek düğümleri aramalısın. Sadece en soldaki bölümle eşleşen bir şey olmadığını keşfetmek biraz zaman alabilir.

Böylece tarayıcılar sağdan eşleşir; bariz bir başlangıç ​​noktası verir ve aday seçicilerin çoğundan çok hızlı bir şekilde kurtulmanızı sağlar. Bazı verileri http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665 adresinde görebilirsiniz (gösterim kafa karıştırıcı olsa da), özellikle de sonuç, özellikle Gmail içindir. iki yıl önce, (kural, öğe) çiftlerinin% 70'i için, kural için en sağ seçicinin tag / class / id bölümlerini inceledikten sonra kuralın eşleşmediğine karar verebilirsiniz. Mozilla'nın sayfa yükü performans test paketi için karşılık gelen sayı% 72 idi. Bu yüzden, tüm kuralların 2 / 3'ünden olabildiğince hızlı bir şekilde kurtulmaya çalışmak ve daha sonra sadece kalan 1/3'ü eşleştirmekten endişe etmek.

Ayrıca, tarayıcıların kesinlikle eşleşmeyen kuralları eşleştirmeye çalışmaktan kaçınmak için zaten yaptıkları diğer optimizasyonların da olduğunu unutmayın. Örneğin, en sağdaki seçicinin bir kimliği varsa ve bu kimlik öğenin kimliğiyle eşleşmiyorsa, o seçiciyi Gecko'daki bu öğeyle hiç eşleştirmeye çalışmaz: denenen "kimliğe sahip seçiciler" kümesi öğenin kimliğinde karma bir aramadan gelir. Bu yüzden bu eşleme oldukça iyi bir şans var kuralların% 70 olduğu hala en sağdaki seçicinin sadece etiket / sınıf / id değerlendirdikten sonra uyuşmuyor.


5
Küçük bir bonus olarak, İngilizce'de bile LTR'den RTL okumak daha mantıklı. Bir örnek: stackoverflow.com/questions/3851635/css-combinator-precedence/…
BoltClock

6
Not o RTL eşleştirme sadece genelinde geçerlidir , bağdaştırıcılarla . Basit seçici seviyesine inmez. Yani, bir tarayıcı en sağdaki bileşik seçiciyi veya basit seçicilerin sırasını alır ve atomik olarak eşleştirmeye çalışır. Daha sonra, bir eşleşme varsa, birleştiriciyi bir sonraki bileşik seçiciye sola doğru takip eder ve öğeyi bu konumda kontrol eder, vb. Bir tarayıcının bir bileşik seçici RTL'nin her bir parçasını okuduğuna dair bir kanıt yoktur; aslında, son paragraf tam olarak aksini gösterir (kimlik kontrolleri her zaman önce gelir).
BoltClock

5
Aslında, seçicileri eşleştirdiğinizde, en azından Gecko'da, tagname ve ad alanı önce gelir. Kimlik (ayrıca tagname ve sınıf adları), seçicileri gerçekten eşleştirmeye çalışmadan çoğu kuralı ortadan kaldıran bir ön filtreleme adımında dikkate alınır.
Boris Zbarsky

Bu , UA'nın hangi optimizasyonları yaptığına bağlı olarak yardımcı olabilir , ancak yukarıda tarif ettiğim Gecko'daki ön filtreleme adımına yardımcı olmaz. Bununla birlikte, sadece yardımcı olabileceği soyundan gelen birleştiriciler için kullanılan kimlikler ve sınıflar üzerinde çalışan ikinci bir filtreleme adımı var.
Boris Zbarsky

@Benito Ciaro: Spesifiklik problemlerinden de bahsetmiyoruz bile.
BoltClock

33

Sağdan sola ayrıştırma, aşağıdan yukarıya ayrıştırma olarak da adlandırılır tarayıcı için gerçekten etkilidir.

Aşağıdakileri göz önünde bulundur:

#menu ul li a { color: #00f; }

Tarayıcı önce a, sonra li, sonra ulve sonra kontrol eder #menu.

Bunun nedeni, tarayıcı sayfayı tararken, yalnızca geçerli öğeye / düğüme ve taradığı önceki tüm düğümlere / öğelere bakması gerekir.

Dikkat edilmesi gereken şey, tarayıcının tam bir etiket / düğüm aldığı anda işlemeye başlaması ve bir komut dosyası bulması dışında tüm sayfayı beklemesi gerekmemesidir, bu durumda komut dosyasının yürütülmesini geçici olarak duraklatır ve tamamlar ve ardından ileri gider.

Diğer yönde yaparsa, tarayıcı ilk kontrolde taradığı öğeyi bulduğu için verimsiz olacaktır, ancak daha sonra tüm ek seçiciler için belgeye bakmaya devam etmek zorunda kaldı. Bunun için tarayıcının tüm html'ye sahip olması ve css resmine başlamadan önce tüm sayfayı taraması gerekebilir.

Çoğu libs dom nasıl ayrıştırılır aksine. Orada dom inşa edilir ve sadece ilk öğeyi bulmak ve daha sonra içindeki diğer eşleşen devam tüm sayfayı taramak gerekmez.


20

Daha spesifik olandan daha az spesifik olana kadar basamaklandırmaya izin verir. Uygulamada kısa devreye de izin verir. Üst kuralın uygulandığı tüm yönlerde daha belirgin kural geçerliyse, tüm üst kurallar yok sayılır. Üst öğede başka bitler varsa, bunlar uygulanır.

Eğer tersine gittiyseniz, ebeveyne göre biçimlendirir ve daha sonra çocuğun her farklı şeyi olduğunda üzerine yazarsınız. Uzun vadede, bu, zaten halledilmiş olan kurallardaki öğeleri görmezden gelmekten çok daha fazla iştir.


11
Bu ayrı bir konu. Basamakları, kuralları özgüllüğe göre sıralayarak ve daha sonra bunlarla özgünlük sırasına göre eşleştirerek yaparsınız. Ancak buradaki soru, belirli bir kural için seçicilerini neden belirli bir şekilde eşleştirdiğinizdir.
Boris Zbarsky
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.