ASP.NET, Css condizionali e Themes

Si non sono sparito... solo un pò assente. Btw, in questi giorni mi sono dovuto/voluto scontrare di persona con il problema della compatibilità dei broswer e i css... tra IE7 e IE8 le cose cambiano molto e se non si vuole ricorrere al metà tag “X-UA-Compatible = IE=EmulateIE7” un’alternativa potrebbe essere quella di usare i “Microsoft Conditional Comments” e lasciare che la pagina risolva client-side il corretto css da usare. Tutto questo è in contrasto con l’uso dei Themes dove tutti i css presenti nella cartella vengono inseriti nella pagina senza distinzione... ovviamente le buone e pratiche osservazioni, “Themes prevent the use of Microsoft's CSS Conditional Comments”, vengono chiuse e catalogate come come “Won't Fix”.

In rete ho trovato diverse idee... anche sovracomplesse; una soluzione decisamente interessante è questa "How to take control of style sheets in ASP.NET Themes with the StylePlaceholder and Style control". Perchè interessante? Perchè mi ha dato l’idea su come muovermi su qualcosa di più semplice e pratico. In fondo è un problema semplice e mi piacerebbe risolverlo con un metodo semplice. Ecco come mi sono mosso.

Ho stabilito che il nome del mio css deve contenere anche la regola che indica se deve essere incluso o scartato per la richiesta corrente in accordo con le caratteristiche del browser. Ho voluto definire solo due regole semplici:

  • <nome>@<broswertype>.css: il css è da usare esclusimanente per uno specifico browertype
  • <nome>@!<broswertype>.css: il css NON è da usare per uno specifico browertype

Si potrebbero aggiungere regole più complicate ma attualmente queste coprono tutti i casi d’uso a me necessari. Ho quindi definito uno user control che incluso nella pagina va ad escludere i css aggiunti ma che non sono concordi con il browser che sta facendo richiesta. Ecco il codice che ne è uscito.

[ToolboxData("<{0}:ConditionalCssThemeControl runat=\"server\"></{0}:ConditionalCssThemeControl>")]
public class ConditionalCssThemeControl: WebControl
{
    const char CONDITIONAL_CHAR = '@';

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        this.Page.LoadComplete += new EventHandler(Page_LoadComplete);
    }

    void Page_LoadComplete(object sender, EventArgs e)
    {
        string browserType = this.Page.Request.Browser.Type;

        var removeCandidate = Page.Header.Controls.OfType<HtmlLink>()
            .Where(link => !IsValidCss(link.Href, browserType)).ToList();

        removeCandidate.ForEach(Page.Header.Controls.Remove);
    }

    protected override void Render(HtmlTextWriter writer)
    {
        //il controllo agisce solo server side
    }

    private bool IsValidCss(string href, string browserType)
    {
        if (href.Contains(CONDITIONAL_CHAR))
        {
            string[] segments = href.Split(new char[] { CONDITIONAL_CHAR }, 2);
            string condition = segments[1];
            bool matchBrowser = condition.EndsWith(string.Concat(browserType, ".css"),
                    StringComparison.InvariantCultureIgnoreCase);

            if (condition[0] == '!')
            {
                //il css è da escludere per lo specifico browser
                return !matchBrowser;
            }
            else
            {
                //il css è indicato per lo specifico browser
                return matchBrowser;
            }
        }
        else
        {
            //il css non ha condizioni di utilizzo
            return true;
        }
    }
}

Quindi nell’head della Page o della MasterPage aggiungo un’istanza del controllo.

<mb:ConditionalCssThemeControl runat="server" id="condCssTheme" />

La mia cartella del Theme risulta come segue.

image

Quello che mi piace di questa soluzione è che posso indicare le condizioni semplicemente e non ho dovuto mettere riferimenti al path del Themes nel codice... come molti esempi viene fatto.

oO0( ... altre possibilità? )

posted @ giovedì 2 luglio 2009 12.52

Print

Comments on this entry:

# re: ASP.NET, Css condizionali e Themes

Left by Nausicaa at 02/07/2009 13.22
Gravatar
Consiglio: abbandona i Themes, e impara bene come usare i css (studia le guide su Html.it).
Non ha assolutamente senso scrivere codice per fare qualcosa che si può fare senza sforzo con cose che esistono da tempo: XHTML+CSS esistono apposta, e risolvono tante cose che Microsoft ha cercato senza successo di "semplificare" ottenendo invece l'opposto (vedi Themes & Skin, e tutto l'obrobrio di style inline generati dai webcontrols).

# re: ASP.NET, Css condizionali e Themes

Left by markino at 02/07/2009 14.43
Gravatar
CSS e Skin hanno scopi diversi... i temi hanno un altro scopo ancora. Skin e Css sono una parte dei Themes. XHTML+CSS sono solo il risultato dell'uso dei temi e degli skin.... impara bene ad usare i themes e vedrai che potrai avere lo stesso risultato. Sono solo punto di vista e un modo di lavorare diversi. E' ovvio che quanto ho scritto vale per chi fa la scelta di lavorare usando i Themes. Purtroppo le vecchie versione versione di IE... hanno troppa licenza poetica in merito all'interpretazione dei CSS per cui creare in maniera veloce un css valido per ogni browser al momento non è pensabile. (my 2 cents)

# re: ASP.NET, Css condizionali e Themes

Left by Andrea Moro at 11/08/2009 13.29
Gravatar
La cosa è interessante, ma correggimi se sbaglio (perchè in fondo è quello che ho notato io cercando di trovare una soluzione).
Non appena metti un qualsiasi file .css dentro la tua cartella theme, questo viene automaticamente incluso nel tuo html (questo è quello che mi succede a me e non credo vi siano opzioni, o parametri nel web.config o chissà dove che aiutino in tal senso), quindi a meno che tu non metta quei file altrove, il tuo codice non avrà alcun tipo di efficacia (purtroppo).

# re: ASP.NET, Css condizionali e Themes

Left by M.rkino at 23/08/2009 15.47
Gravatar
si andrea, ma come ho scritto lo use control "va ad escludere i css aggiunti ma che non sono concordi con il browser che sta facendo richiesta". Infatti se vedi il codice dello user control nel LoadComplete si legge.

removeCandidate.ForEach(Page.Header.Controls.Remove);

Lascio quindi che i css vengano inclusi ma poi escludo quelli non concordi con le regole... sarebbe bello agire per "regole di inclusione" ma non sembra che la cosa sia possibile.

Your comment:



 (will not be displayed)


 
 
 
Please add 1 and 4 and type the answer here:
 

Live Comment Preview:

 
«marzo»
domlunmarmergiovensab
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910