Rounded Corners on Portlets using only CSS
Put the "Rounded Corners" look on your portlets using only custom CSS and three images.
Introduction
Why would you want to make the corners look round?
Plone's standard skin is a little bit... "boxy", with "pointy" corners.
This is so because it is a minimal skin designed to be fast and easily customizable.
But... how do we get rid of some of this "boxyness"?
Why don't we put round corners on the portlets? That's a good place to start, it's an approach that has been taken by many people to make the look of their website easier on the eyes and more original.
Traditionally this has been implemented in Plone by making skins that change the templates that generate the portlets, so that additional HTML elements can be positioned at the corners of portlets, so that these corners look rounded thanks to images of rounded corners, as you would imagine.
This method works well, sites do gain more personality and become less "Plone-like", but...
It has one drawback: When it's time for you to upgrade your website to a new Plone version, you must go through the templates of the new version, manually compare them to those of the previous version, and make sure that the customized templates that you are using to make the round corners do not need to be customized again.
Not very easy to maintain.
The solution to this sort of problem is to do the entire skin only on web standard Cascading Style Sheets (CSS) and without changing any base Plone template or any other element that might be modified from one version of Plone to the next.
The purpose of this Tutorial is to show you how you can round the corners of your portlets using only CSS. This tutorial is meant for Plone 2.1.x, even though it should work just as well in Plone 2.0.x.
In order to implement this method we must make 1 (one) compromise:
- Portlets must become fixed width. If they were allowed to change width the right hand corners would move away from the corner, using this method. To prevent this from happening we would need to manually modify every portlet template in order to add one more corner HTML component for the right bottom corner of every portlet, which goes against our purpose. We want to do the whole thing without modifying templates. For that to work our portlets must become fixed width.
If you feel that this is a compromise that you are willing to make, this is what your portlets will look like at the end of this tutorial:

Now, let's see on the following pages how we can accomplish this.
Ensuring that the portlets' width remains constant
For this method to work we need to ensure that the portlets' width does not change as the user manipulates the page. Here's how.
The standard Plone skin is not very good at ensuring that portlet width is always the same because it uses the HTML <table> element to divide the page in the 3 columns that have the portlets on the left, the main content, and the portlets on the right.
That's why we are going to switch to the "Tableless" Plone skin that is CSS based. To switch to tableless, you need to install this product:
http://plone.org/products/plone-tableless/
You may need to refresh your browser to see the product take effect and / or reload your portal_css by hitting the "Save" button.
Using this "Tableless" skin does help ensure that the portlet's width remains constant but it alone is not enough. We don't want the width to change even if the user changes the page font size on his or her web browser.
To deal with that possibility we must go to Zope Management Interface (ZMI)--the engine behind Plone. That's where we change things that can't be configured yet using Plone's Control Panel, and it is where we will do must of our work during this tutorial.
Access to the ZMI is available on Plone's Control Panel.
On ZMI's main management page you see a list of the many components that make up Plone, some of which are folders with sub-components.
We want to customize the current skin. The component folder that we must select is the "portal_skins".
As we do so we enter another list of components that have to do with what Plone looks like.
We are going to work with CSS. The CSS files are under the "plone_styles" sub-folder, and so is the "base_properties" file where we are going to specify the exact width for our portlets. If you are working on the filesystem, this file should be automatically generated for you by the plone3_theme paster recipe. You can find this file in the "styles" folder inside skins/. (Although the steps below cover how to do this through-the-web, you should really be doing this on the filesystem.)
At this time you must click on the "base_properties" file. It shows you a list of preferences. In order to be able to change these preferences you must click on the "Customize" button up at the top of the page.

This file has now been automaticaly moved to the "/portal_skins/custom" folder in the ZMI.
We can now modify it. As you scroll down to the bottom of the customized "base_properties" page you'll find the "columnOneWidth" and "columnTwoWidth" fields.
You must change both to 176px, and then click on "Save Changes".
There is one more thing to change: It is the padding that exists beside each portal column. But default it is configured to change if the font size happens to be changed by the user. That would affect the portlet's width as well--if the padding becomes wider because the user enlarges the browser's font size then the portlets become narrower.
To make this padding constant we must make the first customization to the CSS rules by hand:
To do that you must go back to the "/portal_skins/plone_styles" directory in ZMI and customize the "ploneCustom.css" file. This file is meant precisely for such customizations, unless you have a filesystem theme product where you can make your CSS changes. So let's click on ploneCustom.css.
You see a text file that is all greyed out.
In order to be able to change it we need to press the "Customize" button as we had done before for the "base_properties" file. This will automatically place a copy of it in the "/portal_skins/custom" folder as well, where we can edit it manually.
This file is made up of comments, two of them have special meaning to Plone so we won't touch those two comments. There is another comment line that says /* DELETE THIS LINE AND PUT YOUR CUSTOM STUFF HERE */. It marks the place in the file where we are supposed to put our customized CSS rules.
So, at this point you are going to remove that comment line and you are going to type in its place the following CSS rules that will make the padding beside the portlets become constant:
body #portal-column-one .visualPadding {
padding-left: 22px;
}
body #portal-column-two .visualPadding {
padding-right: 22px;
}
After you type this in (replacing the comment line mentioned above) you can now click on the "Save Changes" button.
There should be no visual difference in Plone, but we have ensured that the portlets' width remains constant at... let's make some calculations... 176 pixels column width... minus 22 pixels side padding... which results in a portlet fixed width of 154 pixels.
If you'd rather use a different width for your pottlets make your decisions at this point and put the appropriate values in the "base_properties" and "ploneCustom.css" files as described above, so that the resulting portlet width is the one you want.
Now, let's move on to the next step: rounding the corners of our portlet.
Rounding the corners of the portlets' headers
The corners of portlets' headers are made round with the help of a few images.
To round off the corners of the portlets' headers we are going to create 2 images. (If you are concerned about HTTP requests, you could easily create a sprite image that combines the images into one.) One is to be used as the background for the headers of regular portlets, and the other one is to be used for the header of the Calendar portlet (it is slightly different).
You could start by making a mockup of the kind of round corners you want to have, using a graphics application as I did:

These are the mockups I've made. Note that both images on the right side are the ones to be used with the headers of the portlets. Their width must be precise, in our example the images must be 154 pixels wide, as calculated on the previous page. Their height must be as high as your portlets' titles may need to be (within reason,) imagining the possibility of multi-line titles on aomw portlet's headers. These images are:
- Header.png
- HeaderCalendar.png
Note that for the Calendar we need to put those side triangular arrows that allow the user to scroll through months. I also wanted the calendar portlet to look more like a regular portlet, so I made the header line a little thinner and I put the background of the weekdays line to transparent.
In order to implement this, assuming that you've created similar images for the headers, you must go back to the /portal_skins/custom/ directory in ZMI and you must upload both of these images to it.

At this point your "custom" directory should look like this:

Now to make Plone use these images you must click on "ploneCustom.css" and you must add the following rules below the rules you have entered before:
.portletHeader {
background: url(Header.png) top left no-repeat;
border-width: 0 0 1px 0;
}
.ploneCalendar #calendar-previous {
background: url(HeaderCalendar.png) top left no-repeat;
width: 22px;
}
.ploneCalendar th {
background: url(HeaderCalendar.png) top center no-repeat;
padding: 0;
width: 154px;
}
.ploneCalendar #calendar-next {
background: url(HeaderCalendar.png) top right no-repeat;
width: 22px;
}
.ploneCalendar .weekdays td {
background-color: transparent;
}
The Calendar portlet is the one that requires the most amount of CSS rules because it is basically a table.
Go check it out. Your site should now look more or less like this:
The portlets' headers have now round corners, and it wasn't too dificult.
Note that the bottom corners are still not round and also that the Calendar seems to still have a square border over the round corners.
We're going to fix all this on the next page.
Rounding the bottom corners
We finish by rounding the bottom corners. This is the tough part... but it looks so easy when you look at it.
Let's go back to our graphics application to create just one more image. This image is to be used as the bottom part of all portlets, even the Calendar. It should be high enough to "dress" up the Calendar even when it spans 6 weeks, as some months do.
This is the image that I've created for this purpose:
- Bottom.png

Yes, it is really there. It's a simple image, 154 pixels wide, it looks empty but it contains only the bottom contour of the portlets (notice the round bottom corners).
Regular portlets will only use the bottom 6 pixel rows, but the Calendar will use most of it.
You must now upload this "Bottom.png" image to your "custom" folder using the same method as before.
And then you can open the "ploneCustom.css" file again (the one in the "custom" folder in ZMI) and finally add the following CSS rules:
dl.portlet {
background: url(Bottom.png) bottom right no-repeat;
padding: 0 0 6px 0px;
border: none;
}
.ploneCalendar {
border: none;
background: url(Bottom.png) bottom right no-repeat;
}
"dl" stands for "Definition List" and it's the little known HTML component used by all portlets except Calendar. It's the enabler for this CSS only solution.
Notice also the "border: none" rules on both HTML components, because the "Bottom.png" image is providing its own borders and this way we also fix the problem in Calendar's header.
That's all it takes!
Save these changes... and... voilà:

All the portlets are now perfectly rounded, no changes have been made to files that might get changed during the next Plone upgrade.
Well... actually it is possible that "base_properties" will go away in a future Plone release--there is talk about turning Plone's CSS files into static files in order to improve performance. Depending on how it's implemented, it might take away their ability to read parameters from preference files such as "base_properties".
If that happens or if you want to be more future proof right now, just add the following CSS rules to "ploneCustom.css" instead of customizing the "base_properties" file:
body #visual-column-wrapper {
margin-right: -176px;
}
body #portal-column-content {
margin-left: -176px;
}
body #portal-column-content #content {
margin: 0 176px 0 176px;
}
body #portal-column-one {
width: 176px;
}
body #portal-column-two {
width: 176px;
}
These rules do the same thing that you had done in "base_properties" at the beginning of this tutorial, and now we've only customized one single file: "ploneCustom.css".
I know, I know... the site still looks a lot like Plone, which is not a bad thing mind you, but... for example: the tabs are still very "pointy"... somebody might get hurt!
In other words, it looks good but being a CSS based site it could look even better, much-much better!
This is where you come in! There are lots of resources on the Internet showing you how to make good looking tabs using CSS, or showing you how to make translucent panels even on older versions of IE using CSS, and there is a lot of inspiration and good CSS techniques available on sites such as CSS Zen Garden (http://www.csszengarden.com/)
You can make your Plone-based website look as good as you want it to look, just by using CSS and a few additional images, all the while keeping your site readable on every browser ever made, and you can now use the method described in this tutorial when you feel it can help you get the look you want.
Good luck!
Rounding Corners on Fluid-Width Portlets
This technique can be used as a substitute for the previously mentioned solution, or it can be used to round corners on portlets which are not fixed width.
The previous instructions assume that you are working with portlets that are fixed width. If you are not (or even if you are), you can use another method for rounding corners. Assuming you want to round all four corners, you would create four small images (probably best to make them all the same height and width and make sure they will line up exactly with each other) that show the rounded corner. These images will be named something like "topright.gif", "topleft.gif", "bottomright.gif", and "bottomleft.gif". Inside of your code, you would add the following:
<span class="topleft"> <span class="topright"> </span></span> [the rest of your page template] <span class="bottomleft"> <span class="bottomright"></span></span>
Notice the nesting, as this is very important. In this case, your images will hang off of each of the span tags.
Your CSS would then look like this:
.topleft {
background-image:url(&dtml-portal_url;/topleft.gif);
background-position:top left;
background-repeat:no-repeat;
display:block;
}
.topright {
background-image:url(&dtml-portal_url;/topright.gif);
background-position:top right;
background-repeat:no-repeat;
display:block;
}
.bottomleft {
background-image:url(&dtml-portal_url;/bottomleft.gif);
background-position:top right;
background-repeat:no-repeat;
display:block;
}
.bottomright {
background-image:url(&dtml-portal_url;/bottomright.gif);
background-position:top right;
background-repeat:no-repeat;
display:block;
}
Now, on to the rounding of the bottom corners on fixed width portlets.
Rounding Corners Using JQuery
This jQuery plugin will easily create beautifully rounded corners. No images or obtrusive markup necessary.
It's now possible to quickly and easily add rounded corners to your site. In the past, tricks like curvycorners were used, but the effect was global. Now we can control when and where the rounding effect occurs. For the purposes of this section, we are going to refer to the following JQuery solution:
http://www.atblabs.com/jquery.corners.html
It's worth stating that it has the following features:
- Less than 8000 bytes after yui compression.
- Beautiful and fast anti-aliasing for older or stubborn browsers.
- Degrades well for browsers with javascript turned off.
- Native browser corners used on Safari, iPhone, and Firefox 3.
- Form and anchor buttons are easily styled and rounded.
- Documentation and test coverage (this file).
And, it works with:
- iPhone
- Chrome
- Firefox
- Safari 2+
- Opera 9.0+
- Internet Explorer 6+
- and probably more...
Get Started
First, you need a theme product.
Then, you need to download the code from here: http://plugins.jquery.com/project/corners.
(This tutorial was written using the 1.2 version.)
In your theme product, you want to drop the jquery.corners.js file in your skins/templates folder or similar. You also want to take this code and create a new javascript file which we'll call rounded.js and place in our skins/templates folder:
jq(document).ready(function(){ jq('.rounded').corners(); jq('.rounded').corners(); /* test for double rounding */ jq('table', jq('#featureTabsContainer .tab')[0]).each(function(){jq('.native').hide();}); jq('#featureTabsContainer').show(); tab(0); }); function tab(n) { jq('#featureTabsContainer .tab').removeClass('tab_selected'); jq(jq('#featureTabsContainer .tab')[n]).addClass('tab_selected'); jq('#featureElementsContainer .feature').hide(); jq(jq('#featureElementsContainer .feature')[n]).show(); }
You may notice that it is similar to the code at the top of the jQuery.corners.html file, but it has been modified slightly, as Plone 3.1.x and above know about jQuery from the "jq" designation, not from the $ designation. (You can use this technique in older Plone sites, but you'll have to add jQuery support.)
Then, we need to create a portlet (or other page template that knows about main_template). In this case, we will create a portlet called test.pt and we will insert the following code:
<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" i18n:domain="onenorthwest"> <body> <div metal:define-macro="portlet"> <dl class="portlet" id="portlet-rounded-corners"> <dt class="portletHeader"> </dt> <dd> <div style="background-color:#acc; padding:10px" class="rounded"> Example with different x and y sizes. </div> <script>jq(document).ready( function(){ jq('.rounded').corners("30px 10px"); });</script> </dd> </dl> </div> </body> </html>
Then, we modify our theme product's javascript registry file, jsregistry.xml file. This file is located in your theme's profiles/default directory. Add the following code:
<?xml version="1.0"?> <object name="portal_javascripts"> <javascript cacheable="True" compression="safe" cookable="True" enabled="True" expression="" id="jquery.corners.js" inline="True"/> <javascript cacheable="True" compression="safe" cookable="True" enabled="True" expression="" id="rounded.js" inline="True"/> </object>
At this point, you can either install your theme product if you have not already done so, or you can import the javascript GenericSetup step through the ZMI in portal_setup. Make sure you choose your theme product's profile before you import that step.
Next, put your site's javascripts into debug mode via portal_javascripts.
Finally, we need to install the portlet. This particular portlet was created as a Classic portlet, so if you go to http://www.mysite.com/@@manage-portlets (where mysite is the name of your Plone site), and add a Classic portlet named "test", you will instantly see the results.
Additional Customization
There are a number of options that can be applied to your portlet, and these are all documented here: http://www.atblabs.com/jquery.corners.html

Author: