Pixy by rád parametry v CSS. Já taky. Ale (zatím) nejsou. Takže je potřeba jejich neexistenci řešit trikem. Jeden z nich nabízím...
Triky na zavedení "parametrizovatelných hodnot" v CSS jsou různé. Od všelijakých důmyslností čistě kaskádových přes brutalforce postupy až k jemným javascriptovým technikám. Já jsem před měsícem řešil tento (podobný) problém: Mám redakční systém pro různé uživatele a chci jim dát možnost změnit např. barvu pozadí a písma bez toho, abych jim dovolil chmatat do CSS stylopisu. Systém běží na serveru s PHP.
Řešení bylo nasnadě – využít PHP a pasírovat CSS soubor přes nějaký filtr. Otázka byla jen zvolit správný postup. Chtěl jsem, aby CSS zůstalo použitelné i "přímo", nefiltrované. Nakonec jsem postupoval takto:
V defaultním stylopisu jsem místo
background-color:#ffffff;
napsal
background-color:#ffffff/*#pozadi#*/;
Tedy za šestimístné RRGGBB vyjádření jsem dopsal komentář, a aby bylo (pro systém) snazší ho rozpoznat, napsal jsem ho ve tvaru /*#jmeno-parametru#*/.
Na CSS pak neodkazuji přímo, ale přes php wrapper (tedy ve skutečnosti o něco složitěji, ale to nebudu rozmazávat, pro jednoduchost stačí představit si, že odkazuji na "/css.php"). V tomto skriptu si zkontroluju, jestli má daný uživatel nadefinovány "replaces", neboli náhrady hodnot. Pokud ne, pošlu CSS tak jak je na výstup (se správným MIME typem, samosebou). Komentáře ničemu nevadí a CSS procesor je ignoruje.
Pokud má nadefinovány náhrady, jsou v poli $cssreplaces. Např. $cssreplaces=array('pozadi'=>'FF00c0','pismo'=>'002040');
Další postup je jednoduchý:
$data=file_get_contents($fn);(samosebou správný MIME typ mám nastaven předem).
Ti co si před spaním čtou regulární výrazy vědí o co jde. Pokud mezi ně nepatříte, tak vězte, že tento regulární výraz odpovídá případu, kdy je šest znaků následováno znaky /*#, pak libovolným řetězcem a znaky #*/. Výraz neošetřuje případy "neuzavřených" komentářů či podobných nestandardností, protože jsem pečlivý a uzavírám si je. :)
Funkce preg_replace_callback takový řetězec vezme, pošle ho funkci css_callback a nahradí ho tím, co jí callback vrátí. Tedy:
function css_callback($txt){
global $cssreplaces;
$key=$txt[1];
$default=substr($txt[0],0,6);
if (!isset($cssreplaces[$key])) return $default;
return $cssreplaces[$key];
}
Callback funkce tedy nejdřív zjistí jméno "parametru" a hledá ho v poli cssreplaces. Pokud ho nenajde, vrátí to, co je před komentářem, tedy těch šest znaků RRGGBB. Pokud je tento parametr v cssreplaces nalezen, je vrácena hodnota z tohoto pole.
Prosté. Není to přesně to, co chce Pixy (chce zapisovat hodnoty do CSS pomocí pojmenovaného parametru), ale řeší to podobný problém... Řešení je jednoduché, quick-and-dirty, dalo by se napsat mnohem robustněji (teď je vázáno na šestiznakový zápis barvy), na druhou stranu je z rodu "minimal intrusive". Možno se inspirovat.
Dne 18.01.2008
Přidej do:
Stumble It!
[1] (ASH721 - WWW) 18.01.2008, 15:53:45 [X] [D]
V Pixyho případě jde o to, že se mu nechce vypisovat mnohokrát například stejnou definici barvy. To lze už dnes řešit (možná o něco složitějším) zápisem pro více selektorů, např.
#head, #content p, #sidebar div.box { color: blue }
Je to sice o něco krkolomnější postup než mít proměnnou @barva, ale lze si na to zvyknout a jakýs takýs "workeraund" to je. Osobně mi tedy v css chybí jiné, skutečně neřešitelné věci, i když netvrdím, že tahle by se nešikla, protože tohle řešení vyžaduje často velmi dlouhý seznam selektorů v jednom řádku.
V tvém případě - pokud jde jen o několik parametrů, bych to asi řešil jinak. Implicitní styly bych nechal normálním csskem, a pokud by si někdo nějaký parametr změnil, připojil bych pod něj další css, které by těch pár hodnot "přebíjelo".
P.S. Mimochodem zápisník už je zase plísněn za problémy s pozadím a čitelností, večer bych poslal nějaké řešení, ok?
[2] (Arthur Dent [openID] - Mail - WWW) 18.01.2008, 15:57:31 [X] [D]
[1] ... a právě "přebíjení" jsem se chtěl vyhnout.
[3] (rony [openID] - Mail - WWW) 18.01.2008, 16:06:01 [X] [D]
[2] ano, no prave to "prebijanie" je sucastou "charakteru" CSS :-)
obecnejsie a opakovane hodnoty vymenujes kdesi na zaciatku.
Takze prvky, ktore maju mat "jednotnu vlastnost" pekne vymenujes oddelene ciarkami a pridas im danu vlastnost.
Jasneze TO NEZODPOVEDA paradigmatu programatora, ktory ma radsej "variables" a PLNE to chapem :-)
ja by som napr. mal uz konecne v CSS BOX kruhoveho tvaru :)))))))))
[4] (Ondra - WWW) 18.01.2008, 16:08:05 [X] [D]
[2] a můžu se zeptat proč jste se chtěl právě přebíjení vyhnout?
[5] (Arthur Dent [openID] - Mail - WWW) 18.01.2008, 16:28:19 [X] [D]
[4] Můžete... :) Chtěl jsem se mu vyhnout proto, že:
- nemám rád příliš mnoho !important, protože v tom aby se prase vyznalo
- kdybych "přebíjel" novým souborem, tak je to jeden HTTP požadavek navíc
- tak jako tak bych vytvářel onen "přebíjející" CSS předpis skriptem a tak jako tak bych v něm potřeboval zapsat konkrétní hodnoty na určité místo.
Řešil jsem nikoli "stejný parametr pro mnoho selektorů", ale problém, jak v CSS nahradit několik konkrétních hodnot dle libosti.
Samosebou že jsem si barvu společnou pro různé prvky dal na jedno místo, pokud si myslíte, že neznám ani
h1, h2, h3, p: {color:black;}
tak je diskuse marná, problém byl v tom, jak tu hodnotu COLOR nastavit tak, aby byla a) "přizpůsobitelná", b) bez přizpůsobení čitelná.
Proto jsem místo "přebíjení" nějakým "extra" souborem (kde bych stejně musel nějak skriptem doplnit konkrétní hodnoty) zvolil substituci do originálního CSS.
[6] (ASH721 - WWW) 18.01.2008, 16:43:52 [X] [D]
[5] Udělat to jak píšeš rozhodně má své opodstatnění. Proto jsem možné řešení podmínil situací, kdy jde jen o několik parametrů. Pokud bys například volil mezi třemi šířkami webu, stačilo by prostě připojit styl$sirka.css, který by měl třeba jen dva řádky a data bys do něj dynamicky vkládat nemusel.
Pokud si ale uživatel nevybírá, ale definuje sám konkrétní hodnoty, pak je to bez dynamických hodnot samozřejmě nesmysl. Chtěl jsem na tu možnost jen poukázat, mě by ani nenapadlo, že bys neznal h1, h2, h3... ;)
[7] (pixy - Mail - WWW) 18.01.2008, 16:52:37 [X] [D]
Další nevýhoda "přebíjení" je v tom, že tu barvu pokaždé potřebuju pro jiný účel - používám ji v color, backgroud-color, background, tuctu border-vlastností atd.
Podobných "workaroundů" se dá vymyslet spousta, třeba se to taky dá udělat definicí palety v komentáři v úvodu CSS a následným processingem, podobným, jako ukazuje Arthur - např.:
/*
Text color: #000000 -> #003366
Background: #ffffff -> #f0f0f0
Links: #000099
...
*/
A snadno napíšu parser, který mi najde v komentáři string #(\d+) -> #(\d+) a následně udělá všude mimo komentáře replace za . A mnoho dalších způsobů...
Ale pořád jsou to jen "workaroundy", obezličky, obcházení nedostatku. Kdyby to bylo přímo v CSS, bylo by to imho o moc lepší.
[8] (pixy - Mail - WWW) 18.01.2008, 17:00:01 [X] [D]
[3] Rony, nejde o programátora/neprogramátora. Chtěl bych tě vidět, jak tímhle způsobem styluješ obrovský web či aplikaci s mnoha podsekcemi a mnoha desítkami či stovkami selektorů. Já opravdu nemluvím o jednostránkovém CSS pro jednu stránku - tam předdefinované hodnoty nemají valného smyslu. Ale máš-li každou barvu použitou v řádově desítkách selektorů, je každá změna metodou find/replace (nebo preprocessingem) na zabití. A ladit takhle web, to je úplně na mozek...
[9] (syntax ) 18.01.2008, 17:05:05 [X] [D]
Workaroundy mají něco do sebe, zejména pokud je tam ještě něco navíc. Z vlastní zkušenosti můžu doporučit Inmanův CSS Server-side Pre-processor - obsahuje konstanty, proměnné, server-side import, vnořování atakdále.
Viz http://www.shauninman.com...ocessor
[10] (karel dytrych - Mail - WWW) 18.01.2008, 20:59:48 [X] [D]
Kdyz to mas takto jako funkci v CMS prijde mi docela zbytecne generovat a replacovat to CSS s kazdym jeho pozadavkem... Spis bych dal na to misto funkci, ktera vygeneruje novy staticky CSS soubor z neceho jako je sablona, v ktere jsou tyto komentare...
[11] (veena ) 18.01.2008, 21:45:07 [X] [D]
Mě napadlo, jestli by na ten pixyho problém vyřešit třeba v pspadu napsáním skriptu, který by vždy při uložení souboru přepsal ty "konstanty" v souboru podle toho, jak by byly na začátku definované v komentářích.
[12] (Arthur Dent [openID] - Mail - WWW) 18.01.2008, 21:50:41 [X] [D]
[10] Stačí vám prostá odpověď, že to tak, jak píšete, udělat NEŠLO? Nebo se budete (bez znalosti konkrétního problému) dohadovat? :)
[11] Hezké, ale trochu úplně jinde :)
[13] (mka ) 18.01.2008, 22:10:02 [X] [D]
Možná jsem něco nepochopil, ale pokud už se ten styl generuje PHPčkem, proč rovnou nevyužít samotné PHP, stejně jako když generujeme HTML? Nějak takhle:
-----------
backgroud-color:
.error {
font-color: ;
font-weight: bold;
}
//atakdale
-----------
samozrejmě, šlo by omezit počet globálních proměnných např. využitím objektů.
[14] (mka ) 18.01.2008, 22:12:20 [X] [D]
sorry, php kod to nejak sezralo, takze ten priklad ponekud nedava smysl...
[15] (otaznik [openID] - WWW) 18.01.2008, 22:20:37 [X] [D]
[11] tak zas tak vtipné mi to nepřišlo.
Proměnné v CSS by určitě našly své využití, ale nevím aby se z toho nakonec nestal další skriptovací jazyk. Navíc práce s proměnnými, nápad je to pěkný, dokonce logické mi to přijde, ale...vím na to o CSS a jeho cílech příliš málo, možná to není z nějakého mě neznámého důvodu přijatelné.
[16] (Arthur Dent [openID] - Mail - WWW) 18.01.2008, 22:24:03 [X] [D]
[13] Á, další takový chytrý jako [10]. Neočekáváte, doufám, že vám budu vysvětlovat, proč to TAKTO dělat bylo v mém případě nesmysl, že ne?
On něco naznačil Pixy v [8]... Když CSS dělá člověk, co dělá grafiku, tak by mu CSS s nějakými embedded PHP opičárnami bylo na dvě věci. Zkuste prosím uvažovat chvíli mimo meze zaběhané praxe, že si PHP, CSS i HTML bastlí jeden člověk na jednom PC.
Jak pak bude člověk, co dělá CSS, takový pasqil testovat? A není jednodušší mu říct: "Označ mi důležité barvy tímhle způsobem..."?
[17] (Lubomír Hauerland - WWW) 18.01.2008, 23:29:27 [X] [D]
Připadne mi to jako hodně silný kanon :-) Co takhle parametry nahradit vícenásobnými třídami.
class="parametr2 parametr1"
.parametr1 {background-color: #fff}
.parametr2 {color: blue}
[18] (Tomas - Mail - WWW) 19.01.2008, 00:09:18 [X] [D]
Já na to šel podobně, jako autor článku (tedy background-color:#ffffff/*#pozadi#*/),jen s tím rozdílem, že náhrady hodnot nedělám online na serverové straně, ale napsal jsem si na to offline program.
Spustím si page, u které mám okomentované css a současně si to css otevřu v tom programu. Ten mi pak každou proměnou, kterou v tom scriptu nalezne, zobrazí jako tlačítko odpovídající barvy. Samozřejmě že těmi tlačítky mohu ty barvy měnit a kdykoliv mohu uložit aktuální podobu css a reloadnout page. Navíc to umí uložit do extra souboru sadu hodnot těch proměnných.
Ještě uvažuji o dvojúrovňovém mapování. V css bych si pojmenoval proměnné typu LeftColBorder, LeftColText, LeftColBack,.... Těch je několik desítek. Pak bych si udělal jednu nebo více variant mapování, kde bych tyto proměnné namapoval na cca 5-10 proměnych typu HlavniBarva,KonrastniBarva,DoplnkovaBarva, ... Tím by bylo řečeno, jaké prvky jsou stejné, jaké musí být v kontrastu a podobně. No a nakonec by se jen hledaly optimální hodnoty těchto barev, třeba tím mixérem, co má na svých stránkách Pixy. Bylo by super jen tahat a posuvníčky a naživo vidět, jak se web přebarvuje :)
Ale živí mě winform aplikace, weby dělám jen občas, tak jsem k tomu zatím nedostal.
Pokud by to někoho zajímalo, ozvěte se.
[19] (Tomik - Mail - WWW) 19.01.2008, 00:19:03 [X] [D]
[18] Nechci nic slibovat, ale ta idea se mi tak zalíbila, že na to možná něco napíšu. :)
[20] (Lubomír Hauerland - WWW) 19.01.2008, 00:49:56 [X] [D]
[18] Něco podobného je na těchto stránkách:
http://www.hypergurl.com...atch.php
[21] (Arthur Dent [openID] - Mail - WWW) 19.01.2008, 11:23:59 [X] [D]
[17] viz [7]
© Martin Malý (aka Arthur Dent) | Design by © 2007 ASH721 | HOSTING 3000GB+unlimited domains za 6 dolarů