Jak se v Tracy čaruje se specificitou selektorů
- David Grudl
- Nette Core | 8218
Tracy se odjakživa potýká s velkým problémem: její CSS styly kolidují se styly stránky, ve které se zobrazuje.
Obrazovka Bluescreen fungovala tak, že při zobrazení vypnula všechny styly krom svých, takže tam ke kolizi nedocházelo (od verze 2.9 to zkušebně nedělá). Ale Debug bar a Dumper tuhle možnost nemají, musí fungovat současně s jinými styly a nějak kolize řešit.
Zkoušel jsem všechny možné techniky a najít spolehlivé řešení, jak se odstínit od ostatních stylů, jsem nenašel. Tak jsem se je snažil přebíjet resetem s vysokou specificitou a samotné styly pro Debug bar ještě přebíjely reset.
Vedle toho se objevil návrh, aby naopak Tracy styly nepotlačovala a bylo tak cíleně možné je využívat v panelech…
Odbočka: A selector's specificity is calculated as follows: (calculator)
- count the number of ID selectors in the selector (= a)
- count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b)
- count the number of type selectors and pseudo-elements in the selector (= c)
- ignore the universal selector
Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.
Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.
* /* a=0 b=0 c=0 -> specificity = 0 */
LI /* a=0 b=0 c=1 -> specificity = 1 */
UL LI /* a=0 b=0 c=2 -> specificity = 2 */
UL OL+LI /* a=0 b=0 c=3 -> specificity = 3 */
H1 + *[REL=up] /* a=0 b=1 c=1 -> specificity = 11 */
UL OL LI.red /* a=0 b=1 c=3 -> specificity = 13 */
LI.red.level /* a=0 b=2 c=1 -> specificity = 21 */
#x34y /* a=1 b=0 c=0 -> specificity = 100 */
#s12:not(FOO) /* a=1 b=0 c=1 -> specificity = 101 */
Konec odbočky.
Přemýšlel jsem, jak zkombinovat CSS reset s možností, aby jakýkoliv
užitečný styl probublal do Tracy. Vypadá to jako protimluv. Ale napadlo mě
tohle: nechám, ať každé CSS pravidlo obsahující v selektoru
#id
nebo .class
probublá do Debug baru. Aby se
v něm projevilo, musela by třída nebo ID být v něm použitá taky, jinak
prostě pravidlo nebude mířit na něj.
Ačkoliv, není to úplně pravda – Debug bar je přímým potomkem
<body>
, takže toto řešení nebude immuní vůči třídám
nastaveným přímo na <body>
nebo <html>
,
což nevím, jak obejít. A zasáhnou jej taky negativní selektory jako
div:not(.class)
.
Co je ale potřeba uvnitř Debug baru vyresetovat, tak jsou CSS pravidla
mající v selektoru jen HTML elementy, ty by totiž Tracy ovlivňovaly. Podle
tabulky výše potřebuju mít co nejvyšší c
, abych přebil
jakékoliv c
z jiného stylu, ale zároveň držet a
a b
na nule.
Jak zaměřit Debug bar bez použítí ID nebo třídy? Vytvořil jsem pro
něj novou značku <tracy-div>
. Takže původní reset
s vysokou specificitou #tracy-debug, #tracy-debug * { ... }
jsem
nahradil za tracy-div, tracy-div * { ... }
.
Ale tohle pravidlo má zase moc nízkou specificitu (specificity = 1), takže
třeba pre code {...}
jej přebije (specificity = 2). Napadl mě
trik, jak ji zvýšit, a to zdánlivě nesmyslným zápisem
tracy-div:not(a b)
(specificity = 3). Tak funguje současný reset.css.
A ono zdá se, že to funguje (po nějakém ladění v setinkových verzích).
- evromalarkey
- Nette Blogger | 20
Co zkusit shadow dom? Styly v shadowdomu v custom elementu jsou komplet odstíněný od ostatních stylů na stránce.
- Marek Bartoš
- Nette Blogger | 1260
@DavidGrudl Teoreticky bys mohl vytvořit v <body> nějaký prázdný custom element a zjistit které styly podědil z html/body přes getComputedStyle a ty pak v Tracy vyrušit. I když spíš čekám, že se tím něco jiného šeredně rozbije.
- David Grudl
- Nette Core | 8218
@evromalarkey tyjo, na shadow dom jsem si vůbec nevzpomněl, to je super nápad na odstínění!
Umístit Tracy do shadow dom a přidat API, pomocí kterého by se daly dovnitř posílat styly, mi připadá jako nejlepší cesta, protože je to hlavně bez hacků.