Wednesday, 15 June 2011

There are often times when it's useful to draw attention to particular items in a SharePoint list or library. For example, you might want to highlight overdue tasks, colour-code items according to priority, or draw attention to undesirable information. In other words, you want to apply conditional formatting based on field values. Now, as you probably know, SharePoint 2010 uses XSLT-based list views by default. By editing the XSLT for a list view you can apply all manner of rules and conditional formatting. Even better, SharePoint Designer 2010 includes some built-in tools that will figure out the XSLT for you. In the List View Tools tab group, on the Options tab, there's a handy dropdown menu:

In most cases, you're probably going to want to apply conditional formatting by row. First you set your conditions:

Then you choose the styles you want to apply when the conditions are met.

When you've set your style, SharePoint Designer modifies the XSLT so that your formatting is rendered as an inline style on the row (<tr>) element when your conditions are met. I've stripped out some of the less relevant attributes to improve readability.

So far so good. Everything looks correct in SharePoint Designer. However, if you've tried this, you might have found that when you load the list view in the browser you get mixed results – in particular:

Changing background colours and text decorations (such as bolding or italics) works fine.

Changing fonts or font colours works in SharePoint Designer but doesn't work in the browser.

As a result, you'll end up with something like this when you view the list through the browser:

A quick web search revealed that I'm not the first person to encounter this, and I've yet to see a definitive answer, so here goes.

Short version – the problem is down to the way the default styles are structured in corev4.css. Row styles do not cascade down to individual cells (regardless of whether you append an !important flag). If you want to change the background colour, apply conditional formatting at the row level. If you want to change the font colour, and you don't fancy messing around with CSS, apply conditional formatting at the column level.

Long version – read on for a more detailed explanation…

Using IE Developer Tools, you can take a look at how styles are applied to individual HTML elements on the page. The XSLT rule created by SharePoint Designer applies an inline style to a row (tr) element. If we use IE Developer Tools to look at how the row is styled, we can see that everything looks correct – the inline style takes precedence:

However, if we look at how the text within one of the individual cells is styled, you can see that our inline style at the tr level is getting overridden by a more specific style, defined by the ms-vb2 class, at the td level.

Unfortunately there's not much we can do about this. If you want to modify any of the styles defined by the ms-vb2 class, such as font, font size and font colour, you need to create a column-level rule rather than a row-level rule. The two types of rules work in exactly the same way in SharePoint Designer—when you create a column-level rule, you can still set conditions based on any field value, not just the column to which you are applying the conditional formatting. If you want to conditionally change the font colour of an entire row, you simply create a column-level rule on every column. This time, SharePoint Designer modifies the XSLT so that your formatting is rendered as an inline style on the column (<td>) element when your conditions are met:

<td>
<xsl:attribute name="style">
<xsl:if test="ddwrt:DateTimeTick(ddwrt:GenDisplayName( string($thisNode/@Target_x0020_Pub_x0020_Date1)))
&lt;= ddwrt:DateTimeTick( ddwrt:GenDisplayName(string($Today)))">color: #FF0000; </xsl:if> </xsl:attribute> ...This time the browser will render the view as expected. The following image shows the results of a column-level rule on the Target Pub Date column, in addition to the row-level rule described earlier.

If we take a look at the CSS, we can see that our inline column style is overriding the styles provided by ms-vb2.

In summary, there's no real difference between row-level conditional formatting and column-level conditional formatting, other than the scope at which your inline styles are applied. In practice you may often need to use a combination of the two in order to realise a particular style or effect.

13 comments:

I'm not sure why you'd want to do it without using SPD... you could create an XSL file manually and link to it from a List View Web Part (see for example http://tomvangaever.be/blogv2/2011/07/custom-sharepoint-xsl-webpart/). But I'd let SPD do the work for you wherever possible.

Hi Jason,Have you ever had concerns with US date format and UK date format. I have been reading forums, blogs and anything I can to get a solution for this. I have been trying different combinations for 3 days and still have no luck. I am at my wits end.English Australia - LCID = 3081 This is my current version of the code applied at the row level:(number(ddwrt:FormatDateTime(ddwrt:FormatDate(string(@EndDateActual),3081,1),3081,’yyyyMMdd’))) >number(ddwrt:FormatDateTime(ddwrt:FormatDate(string(@EndDatePlanned),3081,1),3081,'yyyyMMdd')))and then apply the formatting.My dates are as followsin dd/mm/yy @EndDatePlanned = 9/11/12 (9 Nov 12) Actual = 19/10/12 (19 OCT 12) That is, the job got completed about 3 weeks earlier than planned so should not trigger the formatting.yet SP is interpreting the 9 Nov 12 date in US format, such that it is 11 Sep 12, and therefore the statement is true and the formatting is triggering (19 Oct > 11 Sep).I have tried (number(ddwrt:FormatDateTime(ddwrt:FormatDate(string(@EndDateActual),1033,1),1033,’yyyyMMdd’))) >number(ddwrt:FormatDateTime(ddwrt:FormatDate(string(@EndDatePlanned),1033,1),1033,'yyyyMMdd')))and many many MANY other combinations. I cannot seem to get SP to do accurate date calculations when there is a possibility of interpreting the date in US format. If it can, it does. Which makes for erroneous results.

I have tried so many sources, and am at my wits end. I am in Australia, and would love someone who has implemented conditional formatting using non US formats to give me some assistance.

And while I am here, I am having trouble rendering an image using the same logic, or using % completed or any date fields. I want to set up a traffic light system based on conditions, using hidden and visible. Text fields seem to work fine. Have you set up traffic light systems using date comparison?

Hi John,It's been a while since I've done any work with conditional formatting, and I don't think I've done anything based on dates - I don't know what to suggest! Next time I get some downtime I'll try to take a look and put up a blog post if I get anywhere with it.CheersJason

I have a list of about 15,000 records. I would like to use conditional formatting to highlight rows that have a duplicate in one column in the list. (Example: all of the rows have a phone number field. Sometimes duplicates are necessary so I can't set the field to not allow duplicates, but I need to validate the duplicates in the phone number field.)

Hi Crystal - sorry, I missed this at the time due to our Christmas break. It's not something I've tried myself, but this looks like a neat approach: http://community.obilogic.co.uk/blogs/teamblog/archive/2012/10/22/detecting-duplicate-list-items-using-xslt.aspx

Thanks Jason.It wasnt very clear that font changes dont apply when applying conditional formatting on row, and needs to be explicitly applied on column.Your article solves exactly what I was looking for - Sangeet Ahuja (www.sangeetahuja.com)

Hi Jason,Any idea why i can see the background color on sharepoint designer but when i refresh my webpart on the browser to show the row color. It does not show the changes. I have delted and inserted the color

Hi Sakshi - one way to troubleshoot it would be to use a web debugger (e.g. F12 Developer Tools in IE as shown in the post) to inspect the CSS that gets applied to the row, and possibly to individual columns. It should show you whether the background colour you specify is getting overridden by another style.

I am new to the Sharepoint scene and found this article extremely helpful. One issue I have is changing the font colour for user or a column linked to the edit menu. Is there an easy way to achieve this?