Integrating a web theme with Plone (& plone.app.theming)

I'm looking at theming in Plone 5 and trying to determine the best way forward for ensuring Plone's HTML output matches that of my custom theme. In this instance, the theme is based on Bootstrap v4 and features all of the framework's components.

In the past, I've tried theming by creating a theme for Diazo/plone.app.theming and creating XSLT rules for Plone's various aspects of HTML output into my theme's framework classes, but this ended up being brittle and hard to handle all aspects of Plone's HTML output. In my past situation, I was applying Bootstrap v2 to Plone 4.x and (eg see example, but it could have been any given framework. The result was a lot of XSLT, much of which ended up being tied directly to the underlying templates, and thus liable to break if (when) HTML output or structure changed. Given nuances in Plone's output HTML between templates, this approach needed in-depth testing and tweaking to handle all edge cases; and for some HTML (eg part of JS or ajax requests and JSON), theming wasn't possible at all without overriding the underlying templates or classes.

Looking at this issue in more depth in Plone 5, the same issue seems to be present; Plone's templates & UI directly depend on the classes/styles provided by plonetheme.barceloneta, and the my theme's framework is opt-in, requiring CSS classes to be applied. To use my theme/framework (uses Bootstrap v4, as mentioned) with Plone, I'd need way of integrating Barceloneta's styles into my theme (or vice versa), but this doesn't appear directly possible because the two themes share conflicting core styles. For instance, having Plone's default CSS present breaks my theme's styles, but removing Plone's CSS breaks Plone's page templates, editor UI, toolbar, etc. Attempting to cut down Barceloneta's LESS (eg remove the generic parts) isn't an option without rewriting it as the Plone UI elements depend on core LESS mixins and styles being present, or else use conflicting class names or style definitions.

So back to my current theming situation -- what's the best solution for getting my Plone site themed using my existing theme, whilst keeping the default Plone templates/UI usable?

Seemingly, the options are either to:

  1. Change Plone's output to match my theme (eg templates / Diazo and XSLT)
  2. Change my theme to feature CSS for all of Plone's classes (eg rebuild Barceloneta), and use Diazo/XSLT to translate any conflicting classes

Both options are going to be brittle for any HTML/CSS changes anywhere in Plone and complicated to get right across all aspects of Plone.

Are there any other suggestions or options available? I thought at one point iframes were being considered for the toolbar, which would keep that aspect separate from the rest of the site's theme.

Thanks in advance.

1 Like

First step would be determine if you really need to theme your backend. By using a technique like this http://docs.plone.org/adapt-and-extend/theming/barceloneta.html#using-the-barceloneta-theme-only-for-the-backend you make your life 10 times easier. Then your only concern is to make the toolbar look ok in your themed version which is vastly simpler task.

btw, for historical context.

  • yes iframes were considered. But the idea proved too ambitious since what rok was trying to do was squeeze all possible plone UI via ajax which is just too big a change.
  • also there wasn't a lot of understanding and support for the idea of making theming easier by not theming the backend.
  • instead I managed to get that backend.cfg solution in. It's not perfect. It would still be better if the toolbar css and js was way less and used no framework (including require js). That would have given us the easiest theming experience. But it was the best that I could get through in the timeframe given no one else seemed to care.
  • Please make suggestions on how this process could be improved.

I do not think there is any problem to use any layout/grid on top of Plone using Diazo.
So I imagine the main problems you have regarding Plone dependency to Barceloneta are about widgets.

A quite simple way to manage that is to use a front-office/back-office approach:

  • display your Bootstrap based theme for anonymous users (or for view pages),
  • display a Barceloneta based theme for mangers (or for edit/management pages).

For instance:

<rules css:if-not-content=".userrole-manager">
    <theme href="front/index.html" />
    ... your rules
</rules>
<rules css:if-content=".userrole-manager">
    <xi:include href="/++theme++barceloneta/rules.xml" />
</rules>

css:if-content=".userrole-manager" is just an example, you can use also: css:if-content="body.viewpermission-view, body.viewpermission-none", or anything relevant to your case.

I suggest using Diazo just for the bigger imports, for instance, replace the entire #content block at once, avoiding manipulating components individually. That way you'll have less cryptic rules to understand six months later.

To implement BS4 I'd try using LESS (or SASS) Extend feature to make the bulk of work and then p.a.themingplugins (z3c.jbot) for changing templates when the former won't suffice (e.g. adding DOM hooks). Finally I also usually update the Diazo template to better fit its DOM and classes to my need - or just to make rules easier to read by using the same classes/ids/structure from Plone's output. For instance, in one project I only "import" attributes from Plone's searchbox FORM tag; the rest is of the structure is already in the theme template.

1 Like

You can also use the ploneintranet themeswitcher to run the Barceloneta interface on a different hostname than your public-facing site.

https://docs.ploneintranet.org/development/frontend/themeswitcher.html

Ignore the warning, all core changes to enable this have been merged, I need to update the docs. You can load ploneintranet.themeswitcher separately from the rest, no need to install ploneintranet as a whole (beyond having the egg available).

1 Like

first, I want to be clear on something: I don't want to start another round of ranting… I just want to understand the problem and help finding a solution for it:

let me see if I'm understanding, because font end development is the one thing I don't do at all: it is now more complicated for integrators to create a theme for Plone 5 than it was before? if that is the case, this is a huge problem that most be solved ASAP.

the original goal of plone.app.toolbar was to provide an even easier way to theme Plone by creating managing toolbar inside iframe.

@djay is telling us that approach was abandoned because it was too complex and now we have, at least, 4 different workarounds but no real solution… so, our current implementation seems to be not very well designed.

may I ask why the widgets are bundled into Barceloneta? could it be possible to take them out of there? can we somehow split the JS/CSS stuff into Plone back end and Plone front end?

for us, having different themes for users and content editors is not an option at all.

1 Like

The widgets are not bundled into Barceloneta (they are defined in Mockup, and the resulting bundle is in Products.CMFPlone). But, to me, if there are problem to run Plone 5 without Barceloneta there are more chances that's because the widgets are not rendered properly rather than anything else. For instance, I guess (but I am not sure) the folder contents page is quite broken if we remove the Barceloneta CSS.

Nevertheless it is absolutely possible to package a specific bundle able to render the widgets properly without Barceloneta (that's something we did for plone.app.widgets in Plone 4: we used mockup to generate the widgets bundle).

So in the present case, I guess we could do the same.

I agree the documentation is mainly about use cases where we use direcly or inherit from Barceloneta. I will make few tests, see what can be done and document it.

1 Like

The toolbar using iframes only made theming easier by allowing you to have two themes. A front end one and everything else in popups using a standard backend theme. That is also the same idea behind using the body.frontend tag talked about in http://docs.plone.org/adapt-and-extend/theming/barceloneta.html#using-the-barceloneta-theme-only-for-the-backend. Or another way to put it, you only have to theme the frontend not the backend.

Sorry, I think I haven't been very clear in my explanations. Let's try to be clearer:

  • Barceloneta is just a theme, we can easily build an entire theme without Barceloneta (and @djay explained how to insert the Plone toolbar in a non-Barceloneta theme using backend.xml). So if you want to use another theme, based on Bootstrap or anything else, you can, and I don't think the problem described by @davidjb here is related to Barceloneta.

  • Plone core (and more specifically Products.CMFPlone) provides some CSS (and also JS) which are important for different Plone features, if we do not include them in our pages, Plone will be broken (because Plone is not a pure backend app, it also involves some frontend parts which are mandatory, maybe some day we will able to run a headless Plone based on plone.restapi, but it will imply to re-write the frontend feature by ourselves anyway).

I guess the problem @davidjb describes is more about those core CSS, which are probably conflicting with Bootstrap 4.
I do not have any easy solution about that.
Could we have build a conflict-free core CSS? I don't think it is possible (as soon we need CSS, our CSS rules/classes might conflict with some existing/future frameworks, and there is not way we can avoid that).
I clearly do not recommend to manage it with a bunch of XSLT hacks in rules.xml (I have been there on Plone 4 projects and it is quite painful).

Compare to Plone 4, to answer your question @hvelarde, the situation is better, because we can use LESS to mix Plone CSS and theme CSS.
For instance we could imagine things like:

.plone-stuff {
    @import "++plone++static/plone.less";
}
.theme-stuff {
    @import "bower_components/bootstrap4/bootstrap4.less";
}

It will not be as simple as that of course, but might be an idea.

I suspect @davidjb issue was just around theming all the plone backend UI.

For the general issue of how to simplify the effort plone puts of a themer to theme just the frontend. ie such as including the toolbar. There is an old issue I raised which is a good place to put ideas or extra scenarios. - https://github.com/plone/Products.CMFPlone/issues/984

Thanks for the discussion; apologies for this lengthy post. The tl;dr is that:

  • I want (need) to use one theme for front and backend for better usability and UX
  • Attempting to do this at present is very hard & brittle (lot of XSLT or template overrides required)
  • It's difficult to apply a class-over-structure theming approach to all of Plone (what BS4 requires)
  • Parts of my theme's CSS conflict with the Plone toolbar and other widgets.
  • Pulling out part of Barceloneta's CSS for use in my theme isn't straight forward (conflicts, dependencies, LESS vs SASS)
  • There isn't a clear way forward.

@djay & @ebrehault, the reason I'm keen to theme my backend is for consistency and having as much of an overall WYSIWYG experience for pages as possible. In the past, I've attempted a Diazo-themed frontend with a Sunburst-themed backend and users had real trouble understanding changes in fonts/colours/page layout in each area. Having to edit and save in one UI and test in another to make sure it looked okay makes for bad UX (eg changing URLs, logging out, different browser sessions, etc), and even the technical users struggled.

@hvelarde, I'm curious as to whether your rationale for consistent themes is the same.

I agree split frontend/backend themes would be the simplest way to get things done and may indeed be my only option. After all, it is how the other CMS platforms I know of approach this issue -- but my observations are as above with it presenting UX issues. On the other project I mentioned, theming all parts of Plone with Diazo/XSLT resulted in consistency throughout and good feedback from users (plus no more than the standard confusion [eg default pages]). That said, the number of XSLT rules and kludges required to theme pages & AJAX content make this untenable, especially with a view to upgrades both to Plone or the theme framework. That project has remained on the same version of Plone (save for minor patches) for this reason.

In this situation, there doesn't appear to be a clean or clear way forward. In short, there are suggestions of separate frontend/backend themes; using Diazo/XSLT; replicating Barceloneta; or overriding templates. Given how BS4 works, it looks as though I'd need to implement a combination of the latter 3 if I were to aim for a single theme site-wide. Theming the frontend is easy with Diazo, but only up until the point where the theme (framework) requires DOM classes/structure that aren't present. In the case of BS4, the opt-in, class-based approach means theming becomes a either case of XSLT manipulation, template overrides, or @extend'ing CSS to somehow match that of the Barceloneta.

The consequence of using any approach aside from separate front/backends is the limiting of upgrades of the system, because your overall design is now tied to HTML output from templates or data structures in page templates. In fact, we already have this with plonetheme.barceloneta -- one example is whereby its Diazo rules feature column logic tied to Plone's output (see rules.xml). I don't believe you could ever escape this sort of thing because all themes will require some degree of DOM manipulation, but because of the scale of changes required to make Plone work with a framework, page template overrides feel a saner place to control HTML output.

@davilima6's suggestion of plone.app.themingplugins and template overrides is a good start in solving my theme's conflicting CSS issue in the toolbar & elsewhere in Plone, but doesn't help with ensuring patterned widgets are rendered properly because widgets' HTML (as best I could tell) directly related to Barceloneta and vice versa. @ebrehault's suggestion of greater specificity CSS (eg .plone-stuff vs .theme-stuff) feels reasonable, but then that raises the issue of LESS vs SASS. BS4, like Foundation and others, is now based on SASS; whilst kludging LESS/SASS together could work, that's going to be awful. I know little of it, but perhaps <template> and shadow DOM (example) will provide a better solution for patterned aspects, once implemented.

Overall, there doesn't seem to be a clear best practice on this at present. This issue isn't uncommon across CMS platforms, but others like Wordpress or Joomla (at last usage) take the frontend/backend approach OOTB so it's what people expect of them.

I don't have any concrete suggestions aside from having Plone adopt a 'best practice' of either split frontend / backend themes OOTB or otherwise documenting exactly which templates to override and how to override/reimplement templates, mockup patterns, etc to achieve a unified theme site wide. In either case, a supported path that provides for this customisation and system upgrades would be helpful. Eventually, the shadow DOM might be the answer, but not for some time.

1 Like

yes, our rationale is the same, but I can't explain it in depth; maybe @agnogueira can find some time to write about it.

1 Like