Friday, 26 August 2016

CSS switching in Asp.Net

Websites are legally obligated in the UK to provide accessible versions of the site for the benefit of users with visual disabilities. This is often achieved by switching the site styling on demand, such that the full-colour graphics-heavy design is replaced by one or more text-based high contrast versions.

This in turn is usually achieved by switching the site CSS according to user selection; and in the wild the switching can often be driven by a complex set of scripting commands cobbled together from chunks found on Stack Overflow, some local customisation, and a liberal application of the old maxim that if the javascript isn’t working, add a bit more javascript.

However faced with implementing this wobbly heap recently, I found that actually the same thing can be achieved with pure asp.net with very few lines of code. As per usual error trapping and so forth has been removed for ease of showing the central concept.

Scenario 

A web site. Old-school fully-templated aspx, master/child, MVC, it doesn’t matter. There are two CSS files defined, standard.css which is the full graphic experience, and hiviz.css which renders the site as black text on a yellow background. The site developers have been very extremely well behaved and have put all of their stylings into the css. The following example calls two methods in a Tools class, GetCookie and SetCookie, which do exactly what you’d expect.

Public Shared Sub SetCookie(ByVal CookieName As String, ByVal CookieValue As String)
    With HttpContext.Current.Response
        .Cookies(CookieName).Expires = Now.AddMonths(6)
        .Cookies(CookieName).Value = CookieValue
    End With

End Sub

Public Shared Function GetCookie(ByVal CookieName As String) As String

   Dim strValue As String = ""
   For i As Integer = 0 To HttpContext.Current.Request.Cookies.Count - 1
       If HttpContext.Current.Request.Cookies.Item(i).Name = CookieName Then
            strValue = HttpContext.Current.Request.Cookies.Item(i).Value
            Exit For
       End If
       Next
       Return strValue
   End Function

Step 1: page header 

The key to this is in the declaration of the css in the page header.

<head runat="server">

    <link id="lkStandardSwitch" href="CSS/standard.css" rel="stylesheet" /></head>

The css declaration is given an id so that it is addressable in code, and the default set as standard.css. That default behaviour is also set in code, but declaring it here keeps the Visual Studio IDE happy.

Step 2: Master page Page_Load event 

In the master page’s Page Load event (or an embedded ascx if you prefer) …

Dim lk As HtmlLink = CType(Page.FindControl("lkStandardSwitch"), HtmlLink)
Dim strCookie As String = Tools.GetCookie("WhichCss")
strCookie = If(strCookie = "", "standard", strCookie)
lk.Attributes("href") = "CSS/" & strCookie & ".css"

If the user has selected one of the accessible css options, that is retrieved from a cookie and the HtmlLink is amended to use that css; otherwise the standard.css is used.

Step 3: CSS selection by the user

To capture the user requirement to display an accessible css, simply write the name of the selected css into the cookie from a button press …

Tools.SetCookie("WhichCss", “hiviz”)

And to update the current page to the new css

Response.Redirect(Request.RawUrl)

And you’re done. Apply to all pages and relax.

In real life of course you may need to switch several CSSs, but this is easily extensible; just remember to use a separate cookie for each css, and then only call the Response.Redirect once when all the updates have been applied. Your visually impaired users will thank you, your accessibility QA team will thank you, and a future you or you-replacement will thank you when they don't have to unpick 40 lines of spaghetti javascript.

1 comment: