Search This Blog

Saturday, April 4, 2009

Rounded Corner Web Part headers in SharePoint

I was figuring out whether there is a way to make the SharePoint Web Parts with rounded corner on all the four sides. I was in fix because our graphic's team created number of designs with rounded corners and non rounded corners. May be client wanted us to wear our thinking cap. He selected the rounded ones. And to my horror there is no straight way to control how SharePoint renders HTML for web part headers and footers. But I had to do it at any cost.

I have come across number of blogs having some solutions. But most talked about the rounded corner web part header i.e. top portion of the web part. I haven't got any solution that suggest to make both header and footer with rounded corners. It may be because SharePoint does not render the web part footer. After number of trials and errors I was successful in accomplishing the task which I would like to share with you all in this blog.

Below is the final result after applying the changes.


Applying Rounded style to Header

Lets analyze the HTML generated by SharePoint for web part header which looks something like this.

<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr class="ms-WPHeader">
<td id="WebPartTitleWPQ2" title="Summary Link Web Part - Use to display links on your web page that can be grouped and styled and can be organized by dragging and dropping">
<h3 class="ms-standardheader ms-WPTitle">
<nobr><span>Summary Link Web Part</span><span id="WebPartCaptionWPQ2"/></nobr>
</h3>
</td>
<td valign="middle" style="width: 10px; padding-right: 2px;">
<a id="WebPartWPQ2_MenuLink" onclick="javascript:MSOTlPn_ShowToolPane2('DownLevelWebPartMenu','g_762397ad_aac2_42c5_b241_7c05c0e6680c');"
href="#" title="Summary Link Web Part Web Part Menu">
<img border="0" align="absmiddle" alt="Summary Link Web Part Web Part Menu" src="/_layouts/images/Menu1.gif"
onmouseover="this.className='ms-HoverCellActiveDark'" onmouseout="this.className='ms-HoverCellInActive'"
class="ms-HoverCellInActive" />
</a>
</td>
</tr>
</tbody>
</table>

Since we cannot modify the way the HTML is generated by SharePoint we need to make changes to the CSS which SharePoint uses. In this case I have created a CSS from SharePoint core.css by copying all the content from the core.css to my own custom css. The changes we will be doing will be done in this CSS. I will store this in StyleLibrary of the root site as this will help us to refer it from any site. Mention this CSS as the alternate CSS. This can be done from Master Page link under Look and Feel on Site Settings page.

Lets analyze the above generated HTML. We have a table with one TR and two TDs within it. TR is applied a class "ms-WPHeader". There is also a "h3" tag having "ms-WPTitle" class inside first TD.We will modify these class to get the required output.

Before we apply modification we basically need two images similar to images shown below:-





The bigger image will be for left corner and the smaller one for right. The width of the bigger image will be respective to your user's maximum display resolution. Suppose your content area have the width as 1000px and have fixed width then take the width of image as 1000px to be on safer side. The width of right cornered image I have taken is 65px. Yes you may be thinking why so much? Originally even I had smaller width image and it worked perfectly as required. But when I opened the page in edit mode there was gap visible between the two images. So I had to increase the width to hide those white gap. You may resize it accordingly.

Working with CSS

Lets go back to the HTML above and the CSS we have copied from the core.css. As we saw earlier we have two TDs. First TD have
<H3> tag. We will target this tag first and set the image i.e. left cornered image as the background of "H3". As we are setting the image as background the extra part will get cut off and only part visible will be the part equal to the size of "H3". If we analyze the parent tag of TD i.e. TR it has a class "MS-WPHeader " applied to it. We will modify the class in such a way that H3 will have a background we wanted. So the structure is as follows :
<TR> -> <TD> -> <H3>

Create a class as shown below

.ms-WPHeader TD h3
{
background: url(' Your left image URL ') no-repeat top left;
margin: 0;
height:17px;
padding:6px 0 0 12px;
color: #FFFFFF;
font-family:verdana,arial,helvetica,sans-serif;
font-size:8pt;
}

Here the first line is the most important line which mentions your background image URL. Other properties are optional which depends on your requirements. Now we have successfully set the left corner.

For right corner we will target TD which is child of TR. We will modify the class ".ms-WPHeader TD". We will add following lines to it.

background-image:url('Your right corner image URL');
background-position:right top;
background-repeat:no-repeat;
height:23px;


The class will look like this

.ms-WPHeader TD{
border-bottom:1px solid #4e7cb7;
border-collapse:collapse;
background-image:url('
Your right corner image URL');
background-position:right top;
background-repeat:no-repeat;
height:23px;
}

Here also background property is most important. Height is as per your requirement or as per image height.

Apart from above mentioned changes you may require to adjust padding or margin as per the requirements. This tweak will make your web part header rounded.

To change the image for arrow you will have to modify the CSS and target DIV inside second TD as follows:

.ms-WPHeader TD div{
vertical-align:top;
background-color:transparent;
background-image:url('Your dropdown image URL');
background-repeat:no-repeat;
background-position:left;
padding-top:3px;
}

Again over here apart from background properties other properties are optional. Default drop arrow image may still be visible along with the new image. Because we have set the image as background of DIV. And the drop arrow image is anchor image. To hide the anchor image add the following class to the CSS.

.ms-WPHeader TD div img{
visibility:hidden;
margin-right:12px;
}

Check your browser you will see all your webpart with the rounded headers.

Problem lying ahead

At this point I was very happy with the results and even deployed the same to production.

To test this functionality I used my default account which was admin account and had all the admin rights and was ignorant about the problem lying ahead.

When normal users with read access logged in to the portal the web parts looked different than what it should look! The right corner did not show at all. On analyzing the HTML what I found was that for visitors or non admin users the second TD does not render.

To overcome this issue I created a JavaScript which searches for element with "ms-wpheader" class and count the number of child TD element. Based on the count I have decided whether the user is admin or non admin. If the count is 1 then he is non admin and if the count is 2 then he is an admin.

I also added two new class to the CSS which will replace the TR's current "ms-
WPHeader" class to new "ms-WPHeader-new" class which handles the adjustment. Below are those classes :

.ms-WPHeader-new TD{
border-bottom:1px solid #4e7cb7;
border-collapse:collapse;
background-image:url('Your right corner image ');
background-position:right top;
background-repeat:no-repeat;
height:23px;
}

.ms-WPHeader-new TD h3.ms-WPTitle {
background-image:url('.Your long image');
background-position:left top;
background-repeat:no-repeat;
text-align:left;
padding:6px 25px 0 12px;
margin-right:20px;
height:18px;
color: #FFFFFF;
font-family:verdana,arial,helvetica,sans-serif;
font-size:8pt;
}

Here the TD with right corner image is the parent of H3 element. So even if you apply right corner background image to the TD, H3 tag will hide that image with it's own background image. We need to give necessary right padding to h3 as shown in the CSS above so that the right corner background image of TD hidden behind it be visible.

Coming to javascript, I never thought it was feasible to add it to each page. Since we have our own customized master page applied to the site, changing the master page was the best way to centralized the javascript. I added the following javascript to the body's onload event.

function cssHeader()
{
var trElement = document.getElementsByTagName("tr");
for(i = 0; i < trElement.length; i++)
{
if(trElement[i].className == "ms-WPHeader")
{
var arr = trElement[i].getElementsByTagName("td");
if(arr.length == 1)
{
trElement[i].className = "ms-WPHeader-new";
}}}}

This post is getting longer than I expected . In this post I have talked about making the Web Part header rounded. In the next post I will talk about making the footer of a Web Part rounded.

Do check out!