Some structural scss/js requests :)

Created on 2 April 2024, 3 months ago
Updated 12 June 2024, 15 days ago

This is taken from my thoughts installing and poking around 3.0.11. I like the simplicity vs some of the (arguably) more over-engineered options available. That said as someone who is comfortable in SCSS it'd be nice to have more control. :)

Problem/Motivation

1. Be able to selectively load bootstrap components

IMO it's not ideal to just have a single @import from the child theme that loads all of bootstrap, in terms of page load time etc.

I've edited my subtheme's style.scss to the following, which seems to be working correctly.

// Sub theme styling variables.
@import 'variables_drupal';

// Bootstrap overriden variables.
// @see https://getbootstrap.com/docs/5.3/customize/sass/#variable-defaults.
@import 'variables_bootstrap';

//////////////////////////////
// Start bootstrap import. //
////////////////////////////

@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/mixins/banner";
@include bsBanner("");

// Required Configuration, do not comment out
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/functions";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/variables";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/variables-dark";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/maps";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/mixins";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/utilities";

// Layout & components, can comment out if not used
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/root";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/reboot";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/type";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/images";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/containers";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/grid";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tables";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/forms";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/buttons";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/transitions";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/dropdown";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/button-group";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/nav";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/navbar"; // Requires nav
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/card";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/accordion";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/breadcrumb";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/pagination";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/badge";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/alert";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/progress";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/list-group";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/close";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/toasts";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/modal"; // Requires transitions
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tooltip";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/popover";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/carousel";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/spinners";
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/offcanvas"; // Requires transitions
// @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/placeholders"; // Causes conflicts with Drupal?

// Helpers
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/helpers";

// Utilities
@import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/utilities/api";

////////////////////////////
// End bootstrap import. //
//////////////////////////

// Import styles from base theme
@import '../../../../themes/contrib/bootstrap5/scss/style';
@import '../../../../themes/contrib/bootstrap5/scss/mixins';
@import '../../../../themes/contrib/bootstrap5/scss/drupal';
@import '../../../../themes/contrib/bootstrap5/scss/bootstrap_fix';

// Include bootswatch
@import 'bootswatch';

// Custom SCSS
@import 'SUBTHEME'

It's not clear how I'd do the same for the js files - I could add a scripts.js to the theme library, but I imagine those files are already being loaded at the parent theme level.

2. Be able to break out theme styles meant for the admin theme

I imagine most people use a separate theme for /admin/, while it's nice to support that, it'd be good if it was clear what partials could be excluded if that wasn't a concern. Not a deal breaker, but it'd make chasing down what the parent theme does and doesn't do simpler.

3. More bs non-semantic class overrides from the theme interface

I wanted to change navbar behaviour, so had to fork page.html.twig to change .justify-content-md-end to .justify-content-md-between. This is pretty normal, but it also makes updates more fragile if I'm pulling a bunch of templates out to change a class here or there.

I'm still on the fence about non-semantic class names outside of SDC etc, so maybe this is just me being a blue beanie curmudgeon. :)

4. Have bootstrap be loaded via Drupal Libraries vs saved in the parent theme.

Less important, this just feels a bit cleaner to me. I appreciate not having to deal with an npm workflow (aside from error messages being a bit tucked away). I'm playing around with CodeKit and PrePros now after being CLI centric for a long time to get the browsersync functionality, but keeping Bootstrap in Libraries vs the base theme feels more appropriate. There could also be an option in the theme file to grab either 5.3 or 5.2 instead of just downloading both.

Ending note

These are obviously just my takes. If there's a hard yes/no/maybe on each I'll understand - I can also try to contribute some MRs to some of the suggestions if they seem like they'd be a philosophical fit.

✨ Feature request
Status

Active

Version

4.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States erutan

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @erutan
  • πŸ‡ΊπŸ‡ΈUnited States erutan
  • πŸ‡¨πŸ‡¦Canada robbdavis

    I love the option of breaking out the bootstrap components. I think I'll borrow that.

    As for bootstrap, an option in config to use a cdn or /libraries version (installed via composer?) would be awesome.

  • πŸ‡ΊπŸ‡ΈUnited States erutan

    I love the option of breaking out the bootstrap components. I think I'll borrow that.

    Glad you find it useful. :)

    Let me if there's anything weird, I'm still sort of porting over the the theme and haven't fully kicked the tires.

    As for bootstrap, an option in config to use a cdn or /libraries version (installed via composer?) would be awesome.

    Libraries + composer seems better, as it'd include all the uncompiled SCSS to reference. afaik the CDN is just pre-compiled CSS/JS that people can style on top of (probably using a lot of !important).

    Bootstrap is in composer, so it can loaded a lot more easily than say highcharts (which is or at least was a bunch of manual links in composer.json).

    https://packagist.org/packages/twbs/bootstrap

  • πŸ‡ΊπŸ‡ΈUnited States erutan

    Updated my scss structure (borrowed heavily from Radix, even though I ended up moving away from it). :)

    Have an _init.scss with the following:

    // Sub theme styling variables.
    @import 'variables_drupal';
    
    // Bootstrap overriden variables.
    // @see https://getbootstrap.com/docs/5.3/customize/sass/#variable-defaults.
    @import 'variables_bootstrap';
    
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/mixins/banner";
    @include bsBanner("");
    
    // Required Configuration, do not comment out
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/functions";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/variables";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/variables-dark";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/maps";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/mixins";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/utilities";

    Then have style.scss be the following (obviously the bottom is up to personal preference):

    //////////////////////////////
    // Start bootstrap import. //
    ////////////////////////////
    
    // Load custom variables and bootstrap dependencies
    // Note you should import this into the top any other directly rendered scss files (ones loaded by a library etc)
    @import "init";
    
    // Layout & components, can comment out if not used
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/root";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/reboot";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/type";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/images";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/containers";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/grid";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tables";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/forms";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/buttons";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/transitions";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/dropdown";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/button-group";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/nav";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/navbar"; // Requires nav
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/card";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/accordion";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/breadcrumb";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/pagination";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/badge";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/alert";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/progress";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/list-group";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/close";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/toasts";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/modal"; // Requires transitions
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tooltip";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/popover";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/carousel";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/spinners";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/offcanvas"; // Requires transitions
    // @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/placeholders"; // Causes conflicts with Drupal?
    
    // Helpers
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/helpers";
    
    // Utilities
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/utilities/api";
    
    ////////////////////////////
    // End bootstrap import. //
    //////////////////////////
    
    // Import styles from base theme
    @import '../../../../themes/contrib/bootstrap5/scss/style';
    @import '../../../../themes/contrib/bootstrap5/scss/mixins';
    @import '../../../../themes/contrib/bootstrap5/scss/drupal';
    @import '../../../../themes/contrib/bootstrap5/scss/bootstrap_fix';
    
    // Include bootswatch
    @import 'bootswatch';
    
    // Custom SCSS
    @import 'SUBTHEME'

    Importing init into my tooltips.scss loaded by a library works well.

  • πŸ‡ΊπŸ‡ΈUnited States erutan

    @import '../../../../themes/contrib/bootstrap5/scss/style'; doesn't need to be loaded since we're already pulling stuff out of it. the init file is still good to go, updated the main style.scss as below.

    Note that you can go to '../../../../themes/contrib/bootstrap5/scss/drupal' and copy out those imports if you really want granular control. I kept it as is in for simplicities sake. Works on both 3.0.13 and 4.0.2, just did the upgrade. :)

    You'll have to do a find/replace when bootstrap updates, but that's not a huge deal IMO. Note that all the bootstrap js is being loaded in the bundle in the base theme even if you comment out SCSS.

    I find the _init is nice - I only use tooltips on a few views, so I can just use hook_views_pre_render in my .theme file to load a tooltips.css and tooltips.js (the two lines of init code from the official site) that I registered in .libraries.yml. There's not a ton of styling I'm doing on the tooltips, but I can include color and spacing variables etc to keep things consistent - if you had more extreme use cases (styling different sections of the site very differently) this would be even more useful.

    //////////////////////////////
    // Start bootstrap import. //
    ////////////////////////////
    
    // Load custom variables and bootstrap dependencies
    // Note you should import this "init" into the top any other directly rendered scss files (ones loaded by a library etc)
    @import "init";
    
    // Layout & components, can comment out if not used
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/root";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/reboot";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/type";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/images";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/containers";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/grid";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tables";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/forms";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/buttons";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/transitions";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/dropdown";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/button-group";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/nav";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/navbar"; // Requires nav
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/card";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/accordion";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/breadcrumb";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/pagination";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/badge";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/alert";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/progress";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/list-group";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/close";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/toasts";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/modal"; // Requires transitions
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/tooltip";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/popover";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/carousel";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/spinners";
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/offcanvas"; // Requires transitions
    // @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/placeholders"; // Causes namespacing conflicts with Drupal?
    
    // Helpers
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/helpers";
    
    // Utilities
    @import "../../../../themes/contrib/bootstrap5/dist/bootstrap/5.3.3/scss/utilities/api";
    
    ////////////////////////////
    // End bootstrap import. //
    //////////////////////////
    
    // Import style overrides from base theme
    @import '../../../../themes/contrib/bootstrap5/scss/mixins';
    @import '../../../../themes/contrib/bootstrap5/scss/drupal'; // if using as an admin theme? can unpack this and load invidually
    @import '../../../../themes/contrib/bootstrap5/scss/bootstrap_fix';
    
    // Include bootswatch
    @import 'bootswatch';
    
    // Custom SCSS
    @import 'SUBTHEME'
Production build 0.69.0 2024