Recently while working on ItWeb module of Imbibe’s flagship ItNet product, I came across an interesting scenario. To display order listing on the back-end, we decided to use the Order Details Bootstrap snippet from Bootdey.

Now customers and users of ItNet would know our back-end is built with ExtJs’ Modern toolkit. And there’s no way ExtJs’ css can co-exist in parallel with Bootstrap’s css. So we had to wrap / sandbox / isolate css from one of the two toolkits, and isolating / sandboxing Bootstrap was the obvious choice for us as ExtJs was our primary UI toolkit.

While researching on ways to isolate / sandbox Bootstrap’s css, I came across this excellent blog post from Chris Youderian which listed precise steps for isolating Bootstrap’s css under a parent class so that Bootstrap’s css does not apply to the whole page but only to elements under a parent element with a specific css class (.bootstrap-wrapper in our case) applied.

So I downloaded latest Bootstrap (5.3.3 at the time of writing this blog post), installed less compiler on my machine:

npm install less

And prepared a less file for isolating / sandboxing Bootstrap 5.3.3’s css:

.bootstrap-wrapper {
  @import (less) '../css/bootstrap.css';
}

The parent class under which the Bootstrap css would reside in our case was .bootstrap-wrapper.

Next it was time to compile the less file for which I invoked the following command:

node node_modules\less\bin\lessc resources\lib\bootstrap\5.3.3\wrapped\bootstrap.wrapped.less resources\lib\bootstrap\5.3.3\wrapped\bootstrap.wrapped.css

And to my surprise, the command failed spectacularly with the following error:

ParseError: Unrecognised input in resources\lib\bootstrap\5.3.3\css\bootstrap.css on line 2978, column 2                              5:
2977   --bs-btn-padding-y: 0.375rem;
2978   --bs-btn-font-family: ;
2979   --bs-btn-font-size: 1rem;

After doing some research, it became clear that starting with Bootstrap 5.3.3, Bootstrap css by default ships with empty values / expressions for a few css variable definitions (e.g. --bs-btn-font-family). While the same constitutes valid CSS, the less compiler does not support it by design and neither are there any plans for supporting it from the less community.

So, there I was… stuck!! I could not use Bootstrap in our ExtJs application unless it got sandboxed / isolated / wrapped up. The less compiler won’t do it, as they won’t support empty expressions for css variable declarations.

At one point, I just thought of removing all empty expression variable declarations from Bootstrap css. But I suspected that might cause issues in generated css as the variable declaration won’t be present. After going back and forth, I came up with a pretty simple way of getting this to work.

I replaced empty expressions with a dummy value for all variable declarations in Bootstrap css, and ran the less compiler. In other words, I replaced all instances of : ; (colon space semi-colon) in Bootstrap css with : dummyvalue; (where dummyvalue was the dummy value I used, I know how ingenuine 😊). Then when I ran the less compiler, it did it’s job pretty well. Afterwards, I again replace the dummy value with empty expression in css outputted by less (i.e. : dummyvalue; was replaced back with : ;). And voila, I had the correctly wrapped / isolated / sandboxed Bootstrap css I could use in my ExtJs project or in parallel with another Bootstrap version or any other front-end toolkit.

For my closing remarks, I would like to point that Chris’s blog post recommends making following replacements in less generated css for it to work correctly:

  1. Replace all instances of .bootstrap-wrapper body with .bootstrap-wrapper.
  2. Replace all instances of .bootstrap-wrapper html with .bootstrap-wrapper.

However I found there was one additional step. We have to remove all occurrences of :root selector too from less generated css (simply find and remove all instances of :root from the generated css).

That was about it. Below you can see Bootstrap’s snippet in a Row Expander inside an ExtJs Modern grid:

Bootstrap 5.3.3 inside a Row Expander of ExtJs 5.3.3 Modern grid

Again remember, you need to have a parent html element for all Bootstrap html / css, e.g.

<div class="bootstrap-wrapper">
    <!-- Your Bootstrap html / css goes here -->
</div>

Happy Hacking!!