2012-06-27 11 views
6

Considerati i dettagli di elaborazione CSS, in particolare RTL matching e selector efficiency, in che modo i selettori dovrebbero essere scritti puramente dal punto di vista delle prestazioni del motore di rendering?Scelta di selettori efficienti in base alla complessità computazionale

Questo dovrebbe riguardare aspetti generali e includere l'utilizzo o l'evitamento di pseudo-classi, pseudo-elementi e selettori di relazione.

+1

Buona domanda, ma ricorda sempre: le prestazioni non sono tutto finché non rimane più l'unica cosa di cui preoccuparsi. Inizia a preoccuparti solo delle prestazioni se sei sicuro di aver assolutamente bisogno di salvare il più possibile e il tuo design lo consente. – BoltClock

+2

Il "CSS Selector Profiler" negli Strumenti per sviluppatori di Chrome è utile se si desidera ... profilare i selettori CSS. – thirtydot

risposta

6

In fase di esecuzione, un documento HTML viene analizzato in un albero DOM contenente elementi N con una profondità media D. C'è anche un totale di S regole CSS nei fogli di stile applicati.

  1. stili Elementi sono applicati singolarmente significato v'è una relazione diretta tra N e complessità generale. Degno di nota, questo può essere in qualche modo compensato dalla logica del browser come la cache di riferimento e gli stili di riciclaggio da elementi identici. Ad esempio, le seguenti voci di elenco avranno le stesse CSS applicate (supponendo che non pseudo-classi come :nth-child vengono applicati):

    <ul class="sample"> 
        <li>one</li> 
        <li>two</li> 
        <li>three</li> 
    </ul> 
    
  2. selettori sono abbinati destra a sinistra per singoli norma di ammissibilità - cioè se la chiave più a destra non corrisponde a un particolare elemento, non è necessario elaborare ulteriormente il selettore e viene scartato. Ciò significa che la chiave più adatta dovrebbe corrispondere al minor numero possibile di elementi. Sotto, il descrittore p corrisponderà più elementi compresi i punti fuori del contenitore di destinazione (che, ovviamente, non avrà applica la regola, ma ancora provocherà più iterazioni di ammissibilità controllo per quel particolare selettore):

    .custom-container p {} 
    .container .custom-paragraph {} 
    
  3. Selettori di relazioni: Il selettore di discendenti richiede fino a D elementi da iterare su. Ad esempio, l'abbinamento corretto con .container .content può richiedere solo un passaggio se gli elementi si trovano in una relazione padre-figlio, ma l'albero DOM dovrà essere spostato fino a html prima che un elemento possa essere confermato in una mancata corrispondenza e la regola venga scartata in modo sicuro . Questo vale anche per i selettori discendenti incatenati, con alcune indennità.

    D'altra parte, un selettore > bambino, un + adiacente selettore o :first-child richiedono ancora un ulteriore elemento da valutare ma hanno solo una profondità implicita di uno e non potrà mai richiedere ulteriore attraversamento di alberi.

  4. La behavior definition di pseudo-elementi come :before e :after implica che non fanno parte del paradigma RTL. La logica è che non ci sono pseudo elementi di per sé fino a quando una regola non impone che venga inserita prima o dopo il contenuto di un elemento (che a sua volta richiede una manipolazione DOM extra ma non è necessario alcun calcolo aggiuntivo per corrispondere al selettore stesso).

  5. Non sono riuscito a trovare alcuna informazione su pseudo-classi come :nth-child() o :disabled. La verifica di uno stato di un elemento richiederebbe un calcolo aggiuntivo, ma dal punto di vista dell'analisi delle regole sarebbe opportuno escluderli dall'elaborazione RTL.

Dato queste relazioni, complessità computazionale O(N*D*S) deve essere abbassata principalmente minimizzando la profondità di selettori CSS e indirizzamento punto 2. Ciò si tradurrà in miglioramenti quantificabili più forti rispetto alla riduzione al minimo del numero di regole CSS o di elementi HTML da solo^

I selettori superficiali, preferibilmente su un livello, vengono elaborati più rapidamente. Questo è preso ad un livello completamente nuovo da parte di Google (a livello di codice, non a mano!), Per esempio, raramente v'è un selettore a tre tasti e la maggior parte delle regole nei risultati di ricerca sembrano

#gb {} 
#gbz, #gbg {} 
#gbz {} 
#gbg {} 
#gbs {} 
.gbto #gbs {} 
#gbx3, #gbx4 {} 
#gbx3 {} 
#gbx4 {} 
/*...*/ 

^- mentre questo è vero dal punto di vista delle prestazioni motore di rendering, ci sono sempre altri fattori quali il traffico aereo e DOM analisi ecc

Fonti: 12345

+1

In Selettori, tutti gli pseudo-elementi (non solo ':: before' e' :: after') sono soggetti alla stessa regola che possono essere applicati solo all'oggetto di un selettore e vengono valutati solo dopo aver completato la corrispondenza del selettore - http://www.w3.org/TR/selectors/#pseudo-elements Da CSS1 a CSS3, questo è sempre il selettore di chiave; tuttavia nei CSS4 questo potrebbe cambiare. – BoltClock

+1

L'analisi RTL è un dettaglio di implementazione e può variare da motore a motore, ma il concetto generale di avviare il selettore di chiave e di lavorare all'indietro è concordato tra i fornitori. Quali semplici selettori in ciascun selettore composto vengono valutati per primi sembra essere qualcosa a cui solo il codice sorgente può rispondere ... più su questo [qui] (http://stackoverflow.com/questions/10106345/css-selector-engine-clarification/ 10108700 # 10108700). – BoltClock

+0

@BoltClock: buon punto; Sarei disposto a ipotizzare che il selettore genitore CSS4 sia effettivamente una pseudo-classe con una condizione * ha-figli * - altrimenti potrebbero esserci molti cicli di corrispondenza ridondanti. Per quanto riguarda le implementazioni specifiche del codice, probabilmente è meglio attenersi al comportamento suggerito: un esempio notevole di come fare casino è IE7 'nella cache dei riferimenti ': first-child' –

Problemi correlati