Yes, they provide some limited advice which you've probably seen :-)
No, there are no guarantees they won't turn on a better UI.
But the portal does look like dogs' balls, so here are some tips:
utilize the JavaScript UserContext.siteUrlPrefix
in the header document to resolve the correct relative path to the CSS resource like this:
<script type="text/javascript">
document.write(
"<link " +
"href='" + UserContext.siteUrlPrefix + "/resource/portalCss'" +
"rel='stylesheet' " +
"type='text/css' " +
"/>"
);
</script>
if significant changes are needed, there are a couple of ways to get a clean canvas. A very high specificity CSS reset can be used, or it is possible to dynamically remove the existing stylesheets with JavaScript.
[I can email you a portal-specific example of a high specificity reset.]
study the underlying markup to reverse engineer which structures belong to which components (you'll be able to grok pageBlockSections, pageBlockButtons, etc)
table#bodyTable td#sidebarCell {
/* the left bit */
}
table#bodyTable td#bodyCell {
/* the right bit */
}
table#bodyTable td#sidebarCell div.sidebarModule {
/* narrow home page components */
}
table#bodyTable td#bodyCell div.bPageBlock {
/* wide home page components and page blocks */
}
because the customization mechanism is the insertion of a Document (!) in the header, one may prefer using @import
in the CSS rather than the standard <link />
s in the Document; this offers future developers 'principle of least astonishment' so they need only modify the CSS resources, not the injected Document
like any CSS files, the URLs of the javascript will also differ depending on whether the Portal is bound to a Site or not (and again if one uses [Login As Portal User] from the CRM). Using a script loader will prevent having to change the Document, and from clobbering all paths with UserContext.siteUrlPrefix
. Here's an example:
var
scripts = document.getElementsByTagName('script'),
source = scripts[scripts.length-1].src.split('?')[0],
url = source.split('/').slice(0, -1).join('/')+'/',
load = function(file) {document.write(
"<script type='text/javascript' src='" + url + file + "'></script>"
);}
;
load('jquery.js');
load('jquery.cookie.js');
load('tab_home.js');
load('tab_solutions.js');
load('tab_cases.js');
load('tab_ideas.js');
LaceySnr is right about it being risky if they roll out a new theme.
One runs the same risk when styling any Visualforce. Just consider a fallback strategy in the face of changes to the underlying markup. If the new theme is an improvement, that strategy might be to simply turn off any customizations.
But there are two extremes. At one end, foist the out of the box implementation on customers at the expense of their experience. At the other, attempt to reinvent it all at the expense of not leveraging the platform offering.
It depends on the situation. "I need a visually acceptable customer portal solution in the next couple days" versus "the wireframe says it has to look exactly like this, be 100% future proof and my budget is unlimited". There's a Pareto principle middle ground.
Portal is pretty yukky for the guy doing the CSS, but it can be a quick win if you know the gotchas.