Currently there is no consistent way in Civi to tell which page you are on by querying the DOM. Usually this is done by having a class attached to the <body> tag that identifies the current page. Unfortunately each CMS use different naming conventions, or attaches no class at all.
For example: this is the Contact Summary page's <body> tag on each CMS
It would open new cross-cms customization avenues for devs: styles applied only a specific page, JS plugins that use the body class to bootstrap itself or perform an action only on certain pages, etc.
Of course currently one can already inject a css/js file on specific pages by using hook_civicrm_pageRun(), but this approach lacks the flexibility that the proposed solution would instead provide.
Technical challenges
I figured that there would be at least two:
Find a way in all 3 cms to alter the list of classes attached to <body> that doesn't involve using a theme hook, given that this solution should be both cms and theme agnostic (you don't want those classes to disappear the moment an admin decides to change the administration theme)
Figure out how to programmatically generate the class name for each individual civi page
Before opening the issue I asked in the dev channel if there was already a way to identify a page that I wasn't aware of (https://chat.civicrm.org/civicrm/pl/of6xsr17sidujmm1tuasr8bupy), but apparently there isn't, at least not the in the way I'm proposing here
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items 0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items 0
Link issues together to show that they're related.
Learn more.
I'm not opposed to it but have concerns about implementation. Civi doesn't really integrate with the CMS deeply enough to be able to influence the <body> tag. We could do it with jQuery though. That might suffice.
Unfortunately I think that using jQuery or JS in general wouldn't be a feasible solution: given that we would have to wait for the JS to kick in and apply the class to <body>, we would have css flashes and race conditions for any scripts relying on that class.
I think this must be done on the backend in order for it to work.
On drupal I believe hook_preprocess_page would do the trick (after all there is an entire module dedicated to adding classes to <body>)
On Joomla apparently there is an onAfterRender hook for plugins (saw it mentioned here), and i think i saw that civicrm has some plugins for joomla already?
For Wordpress I couldn't find anything yet, except for reference to body_class() but if i understood correctly this is for themes only
Just to add a bit of context to this. I think this may be a blocker to moving forward with Shoreditch on WordPress and Joomla as currently some of the Shoreditch styles target specific pages in order to achieve the consistent look and feel (as we've avoided changing markup). On Drupal this has been possible but without this improvement for Joomla and WordPress I don't think it will be possible to achieve Shoreditch compatibility.
Would be great to get a 'concept approved' for this so we can start to flesh out the next steps.
I was thinking about that, but in the end it would still be preferable if there was a way to apply those classes to <body>, as extensions (like Shoreditch) might have the need to apply specific styles also to elements outside of the civi boundaries
On drupal I believe hook_preprocess_page would do the trick (after all there is an entire module dedicated to adding classes to <body>)
On Joomla apparently there is an onAfterRender hook for plugins (saw it mentioned here), and i think i saw that civicrm has some plugins for joomla already?
For Wordpress I couldn't find anything yet, except for reference to body_class() but if i understood correctly this is for themes only
thanks @kcristiano! Is this method available only in themes or also in plugins (sorry, not much experienced with WP)? I'm asking because
this solution should be both cms and theme agnostic (you don't want those classes to disappear the moment an admin decides to change the administration theme)
@AkA84 This is available to plugins. I agree we have to stay away from the CMS themes. WP themes (generally) do not affect the admin side. They could, but in general they do not.
@AkA84 In case it's any help I tried putting together a Joomla plugin. Not really sure what the best way of getting the class name from CiviCRM is so am getting it from the URL (&task=civicrm/etc) for now. Have a look at https://github.com/andrewpthompson/joomla-civicrm-css-class-plugin if you're interested. There seem to be some other issues that need to be resolved to get Shoreditch to work on Joomla though; possibly [role='dialog'] is one.
@AkA84 Sorry for the long delay in replying - was on holidays. The third column of the table below shows the additional class that would be added to <body>. In all but the first one (dashboard) it is derived simply from the task URL argument. If we need CiviCRM to inject classes more flexibly than just being URL-derived then obviously a different mechanism would be required to pass that from CiviCRM to Joomla.
CiviCRM page
Class added to body element (current Drupal-style)
Class added to body element (as per this proposal)
I've tried a few variations on the code. The code to get the class name in column 3 above (as per your proposal) is here.
Other variations on the code (not related to your proposal but to try to suit Shoreditch's current design):
The code I used to get the Drupal-style class name in column 2 is here.
Another attempt at mimicking Drupal more closely (multiple classnames e.g. page-civicrm page-civicrm-admin page-civicrm-admin-custom page-civicrm-admin-custom-group, the purpose was to get most of Shoreditch working on Joomla) is here.
Regarding my comment about role='dialog', this is a non-issue. I spent only a short time looking for reasons why Shoreditch still had a few styling issues on Joomla. After seeing that Shoreditch uses the role attribute in many places in the compiled custom-civicrm.css e.g. .crm-container[role='dialog'] I had thought that under Joomla CiviCRM possibly wasn't adding role="dialog" where it should but I checked again and it does. No problem there.
I'm getting back on this issue, and first of all a very overdue thanks for your help! I'm gonna take a look at those 3 branches on my local, i'm not very versed in Joomla (so I can't really properly review them), but I can certainly tell you if they get us closer to what I was proposing, thanks again and sorry for the massive delay of my reply
Does it need to be the <body> tag? What about the <div id="crm-container"> element?
Was thinking if having those classes on #crm-container would make things easier? Given the push recently to fully decouple Shoreditch from the CMS (see here and here) I don't think my initial answer to your question holds much water anymore.
I'm not sure yet if the change of position of those classes from body to #crm-container would be a good thing for Shoreditch (both in terms of how much rewrite would be necessary and also what problems it would create for the styling of certain pages), but it might still be worth taking a look
So I think both proposals (adding classes to the body or the crm-container) are technically possible. I think it's even possible to do it with javascript without any flash - it's just a matter of correct script placement and execution.
But... YAGNI? I still haven't heard any non-theoretical use case for this. If someone has a killer feature they are trying to implement and this is a blocker, I'd love to hear about it so we can talk about this in more concrete terms.
@colemanw I'm not sure if it's been made clear here in the above but I believe the desire for this feature is due to the way that Shoreditch styles target individual pages in order to deal with the inconsistency in CiviCRM markup.
Currently the approach that is used in Shoreditch only supports Drupal, but the proposal above would allow us to make the Shoreditch page specific styles work for Wordpress and Joomla, making Shoreditch cross platform compatible.
. I think it's even possible to do it with javascript without any flash - it's just a matter of correct script placement and execution.
Just to make this concrete, an example implementation: https://gist.github.com/totten/983267cf33edb44aa98f38ccf13d41fb. This could be a fallback - so initially we support the CSS class on every page via JS polyfill. But, incrementally, each CMS-integration can be updated to inject the CSS class server-side (no Javascript; guaranteed flash-free and compatible with all browsers). To signal its support, the CMS-integration sets CIVICRM_UF_PAGE_CSS.
I'm not worred about YAGNI - I mean, it's valid fear that this creates a new foot-gun, but the technique seems common enough in the broader world. I think it's reasonable to support this.
My main question is about the semantics when using dialogs. For example, if you go to "View Contact" and add a new "Phone Call", then you have one DOM, one <BODY>, and two logical pages (parent civicrm/contact/view and dialog civicrm/activity/add).
It feels equally legit to write CSS rules which mean:
Customize the styling of civicrm/activity/add when it's standalone - i.e. body.civi-page-civicrm-activity-add
Customize the styling of civicrm/activity/add whether it's standalone or dialog - i.e. .crm-container.civi-page-civicrm-activity-add
So maybe it makes more sense to support a CSS class at both body and crm-container levels?
So maybe it makes more sense to support a CSS class at both body and crm-container levels?
I'm not sure about crm-container, if you go to the demo site there are 25 instances of .crm-container, ranging from the main content to the little "widgets" on the left hand side column, to some select2 elements
What if instead the body class gets attached to .crm-ajax-container, which is the root of the modal content?
(1) Great point. Agree .crm-ajax-container looks better than .crm-container. @colemanw, does that seem like a reasonable analog to body for embedded AJAX pages?
(2) At the slight risk of sounding bike-sheddy... I'd suggest a couple revisions to the class naming:
The general naming convention of Civi's CSS classes uses the crm-* prefix. I don't think civi-* shows up anywhere else.
(Less important/more bikesheddy comment) When examining path /civicrm/contact/view, the current draft spec strips out civicrm prefix (/civicrm/contact/view => contact-view). That is more concise, but I'd lean toward 1:1 naming (/civicrm/contact/view => civicrm-contact-view) because (a) it makes the mechanism simpler and (b) it will still be well-defined if the routing system changes to support more paths. (This might happen if, eg, we allow admins to configure custom URLs for profiles or reports.)
Thank you for raising an issue to help improve CiviCRM. As you may know, this issue has not had any activity for quite some time, so we have closed it.
We would like you to help us to determine if this issue should be re-opened:
If this issue was reporting a bug, can you attempt to reproduce it on a latest version of CiviCRM?
If this issue was proposing a new feature, can you verify if the feature proposal is still relevant? Did it get the concept-approved label? Have other people also shown interest? Could it be implemented as an extension?
If the answer to either question is yes, please feel free to comment or re-open the issue. Please also consider:
Is it something that you could help implement, either by sending a patch or hiring someone who can?
Thank you for your help and contributions to CiviCRM.
P.S. This is an automated message, see infra/gitlab issue 20. We understand that automatic responses are annoying, but given the number of open issues as the project evolves, we need a bit of help to triage and prioritise the most relevant issues.