Bootstrap3 CSS
Definitions
- Look and Feel: A visual appearance that can be recognized by a user of a page.
- CSS Vocabulary: A list of CSS classes that are agreed upon as a contract between a theme and an app-page. Example: "Bootstrap CSS v3", "Bootstrap CSS v4", "crm-*"
- Application Page: A business application which provides functionality/behavior. It is positioned as consumer of CSS vocabulary(ies). Example: CiviContribute's "Contribution Page", CiviMail's "New Mailing" page, or CiviVolunteer's "Assign Volunteers" page.
- Civi Theme: A CiviCRM package which defines a look-and-feel. It is positioned as a provider of CSS vocabulary(ies). Example: Shoreditch
- CMS Theme: A package for a CMS which defines a look-and-feel. It is positioned as a provider of CSS vocabulary(ies). Example: Drupal Garland, WP Twenty Seventeen
- Civi-Optimized Theme: A package which defines a look-and-feel that is specifically intended to work with CiviCRM. Some CMS themes may be "Civi-optimized" (even if they are not specificallly packaged as a "CiviCRM extension").
- Resource: A resource is some artifact-- CSS file, CSS snippet, JS file, JS snippet, JS setting, et al -- that can be added to a page.
- Resource Bundle: A bundle is a list of related resources that are loaded together.
Expectations
-
I am a novice site-builder who relies on some default/widespread theme. I expect that CiviCRM will look coherent out-of-the-box. If this expectation is unmet, I will assume that CiviCRM is broken.
-
I am a mid-level (or higher) site-builder who researches and configures various addons. I may be using a theme that is neither default/widespread nor specific/optimized to CiviCRM. I also expect that CiviCRM will look coherent. However, I have greater tolerance for challenges: if my expectation cannot be met out-of-the-box, then I may spend some effort to make it work... provided that the configuration game is communicated clearly.
-
I am an application developer with a specialization in CiviCRM. I expect there to be a well-defined CSS vocublary that I can rely upon when writing application pages. I expect the CSS vocabulary to be equally supported in all environs.
-
I am a theme designer/developer with a specialization in CiviCRM. I expect there to be a well-defined CSS vocabulary that I can target when writing CSS rules. I anticipate some interaction between CMS theming and Civi theming, and I expect a clear relation between them.
General Thoughts
- It is possible to implement any "CSS Vocabulary" in any "CMS Theme" or "Civi Theme". Just create another
.css
file. - The CSS vocabulary for "Bootstrap3" is well-defined, well-documented, stable. The CSS vocabulary for "crm-*" is (in relative terms) more fluid and not as well-documented.
- Within any given page-request, there are 0-1 active CMS themes and 0-1 active Civi themes. (Internally, some themes may be built on top of one another. For our purposes, such details are encapsulated witin the theme such that we may set aside those details while considering the protocol.)
- The upshot of a "Civi Theme" is that it can provide additional CSS vocabularies that are not universally available within CMS ecosystems. The flip-side is that the look-and-feel may be mismatched.
- If the concurrent "CMS Theme" and "Civi Theme" both implement support for the same CSS vocabulary, then (logically) this is a conflict. The "CMS Theme" is generally required for other purposes (outside our purview), so it must be left active. The conflict may have a few outcomes:
(Mixed) If we proceed with loading both CMS+Civi theme CSS, and if both use broad selectors, then the look-and-feel will be the arbibtrary combination of both (spread across the page).- (Split) If we proceed with loading both CMS+Civi theme CSS, and if Civi's selectors are carefully tuned, then the look-and-feel have single, distinct split in the look-and-feel (different L&F on "Civi pages" and "CMS pages").
- (Yield) If we omit the the Civi theme CSS for that vocabulary, and if the vocabulary providers really are interchangeable, then we get one L&F across all "Civi pages" and "CMS pages". (At least, for pages based on the duplicate vocabulary. Other Civi pages may use other vocabularies which are not supported by the CMS theme.)
- Note: None of these outcomes is necessarily best or optimal... the "best" will be in a state of flux as support for different vocabularies and different L&Fs change. The choice is subjective.
- In discussing themes, we often distinguish between a frontend and backend policy. If there's a manual on/off switch for "bootstrap3", should it discern between frontend/backend?
- At first, I thought "yes", because that's usually articulate decision-making wrt frontend vs backend.
- On second thought, aren't we using "frontend/backend" as a proxy for identifying the particular theme that is active on the frontend/backend? ie The provisioning of
bootstrap3
is a chacateristic of that theme.
Current behavior
In shoreditch
, one activates the extension and chooses "Shoreditch" as the activ etheme- and then its bundle of bootstrap3
resources is loaded on every page.
New behavior
-
Application Page: An application-page signals the need for Bootstrap3 vocabulary by calling
Civi::resources()->addBundle('bootstrap3');
-
Civi Theme (Basic): A theme may define the content of
bootstrap3
bundle by file-convention, ie- Implement
hook_civicrm_themes
to declare the theme - Create the files
css/bootstrap3.css
andjs/bootstrap3.js
- Implement
-
Civi Theme (Advanced): A theme may define the contenf of
bootstrap3
bundle by hook, ie- Implement
hook_civicrm_themes
to declare the theme - Implement
hook_civicrm_alterBundle
and filter/revise/override/supplement the list of resources inside ofbootstrap3
.Civi::dispatcher()->addListener('hook_civicrm_alterBundle', function($e){ if ($e->bundle->name === 'bootstrap3') { $e->bundle->update('civicrm:css/bootstrap.css', [ 'type' => 'scriptUrl', 'scriptUrl' => Civi::service('asset_builder')->getUrl('...'); ]); } });
- Implement
-
Conflict Resolution: The default policy is to "(Split)" L&F between CMS+Civi, but there are counterplays.
- To wit: if Shoreditch is active on a page, and if the page needs Bootstrap3, then (by deafult) it loads Shoreditch's
bootstrap3
- regardless of whether the CMS providesbootstrap3
by other means. This provides more internal consistency (e.g.bootstra.css
/civicrm.css
) and more cross-site consistency (e.g. different sites with different CMS themes chosen by different people => but shoreditch always behaves the same). - For a Civi-optimized CMS theme, the developer may implement
hook_civicrm_alterBundle
and toggle$bundle->isActive
.Civi::dispatcher()->addListener('hook_civicrm_alterBundle', function($e){ // mycmstheme has built-in, global support for bootstrap3. if ($e->bundle->getName() === 'bootstrap3' && $e->bundle->getActive() === 'auto' && cms_active_theme() === 'mycmstheme') { $bundle->setActive(FALSE); } }, 1000);
- For a local override, the site-builder may configure the setting
array theme_bundles
- ie$themeBundles[$cmsThemeName][$bundleName] === TRUE|FALSE|auto'
.
- To wit: if Shoreditch is active on a page, and if the page needs Bootstrap3, then (by deafult) it loads Shoreditch's