Roots Discourse

Sage + Woocommerce - how to handle stylesheets?

I’m building an ecommerce site running on Trellis/Bedrock/Sage with WooCommerce and Sage’s default Bootstrap component.

I have read this article at least a dozen times over the course of the past few months, for this and other projects: https://roots.io/using-woocommerce-with-sage/. I’ve also read multiple topics around here saying that “this link contains literally everything you need to know to work with WooCommerce”. It’s a great resource, but it is lacking specifics at least with regard to the asset pipeline. In fact, the answer to this or a similar question would probably make a useful addition to that article.

What’s the best way to get the WooCommerce styles into my Sage theme’s build process? I installed WooCommerce as a standard WP plugin (it isn’t on Composer and I didn’t want to mess with a custom repo or using it as a git submodule or subtree.

I could just let WooCommerce run it’s own CSS within it’s plugin directory and overwrite stuff, but I’d really rather avoid that. I want to try to keep the CSS as lean as possible. So, I copied WooCommerce’s SCSS files into my Sage assets/styles directory in a woocommerce subdirectory.

I figured at this point I can either do something with manifest.json, bower.json, or maybe even NPM’s package.json5, but I just don’t know how I should be doing so. What I’ve ended up doing is just including the various WooCommerce SCSS files within my main.scss file in my assets directory. This seems to work, but also feels clumsy.

Has anyone done a project with Sage and WooCommerce and found a good way to streamline the asset pipeline between the two?

Take WooCommerce out of the picture — you want plugin assets to be compiled into your theme assets. This is covered in multiple places:

It’s also been discussed on the forum a few times if you look around

I installed WooCommerce as a standard WP plugin (it isn’t on Composer and I didn’t want to mess with a custom repo or using it as a git submodule or subtree.

FYI — every plugin in the WordPress plugin directory is available via WPackagist. See https://roots.io/wordpress-plugins-with-composer/.

manifest.json is where you’ll need to make the changes

3 Likes

Thanks. That clears it up for me somewhat, though I’m still not sure what will amount to being the “ideal way” to accomplish this.

When I decide on something and implement it, I’ll update here for any potential future users with the same goal.

The ideal way is what I already mentioned — using manifest.json to include assets from the plugin in the theme. I provided you with links to multiple resources that show you how to do this.

1 Like

Here’s an approach I use for times when I want to write my own rules for WC without having to override tons of classes in my SCSS files, so I can have a customised WC appearance within Sage. I presume that’s what you’re trying to do here?

For my WC+Sage projects, I use a WC function to deactivate WC’s ‘gloss’ elements and keep just the basic responsive grid structure. Reason being, I was always annoyed by the fact that I had to override a lot of the basic WC styles all the time in my custom theme (eg the purple “Add to cart” button styling or the green circular “Sale!” sticker). I wanted to also use Bootstrap styles for these sorts of things. Rather than trying to figure out how to pull in WC’s styles into the pipeline and then write overrides on top, I wanted to just switch off all the WC styling fluff, except for the basic responsive grid layout (which I personally find handy).

I Improvised this solution, based on a function that disables various components of the WC stylesheet so I could then just use my own rules where I wanted to:

// functions.php

$sage_includes = [
  'lib/assets.php',    // Scripts and stylesheets
  'lib/extras.php',    // Custom functions
  'lib/setup.php',     // Theme setup
  'lib/titles.php',    // Page titles
  'lib/wrapper.php',   // Theme wrapper class
  'lib/customizer.php', // Theme customizer
  'lib/woocommerce-functions.php'  // <----- Add in my external WooCommerce functions
];

// lib/woocommerce-functions.php

//Remove default woocommerce stylesheets
add_filter( 'woocommerce_enqueue_styles', 'jk_dequeue_styles' );
function jk_dequeue_styles( $enqueue_styles ) {
	unset( $enqueue_styles['woocommerce-general'] ); // Remove the gloss
	// unset( $enqueue_styles['woocommerce-layout'] ); // Remove the layout
	// unset( $enqueue_styles['woocommerce-smallscreen'] ); // Remove the smallscreen optimisation
	return $enqueue_styles;
}

So in the custom WC functions file I created, I uncommented the first “unset” statement so it would strip out the irrelevant styling that I didn’t want to keep. But I kept next two lines commented out so I could retain the basic structure. But you can uncomment all three lines and have a completely blank slate to work with.

Now if I wanted to apply my own basic theming across the board (eg if I wanted Bootstrap button styles on all WC button elements, and apply Bootstrap table styles) I would do something like:

// assets/styles/common/_pages.scss

.woocommerce-page {
  .button {
    @extend .btn;
    @extend .btn-primary;
    @extend .btn-lg;
  }
  table {
   @extend .table;
  }
}


4 Likes

I am very, sincerely sorry for wasting your time here. Thank you so much for taking the time to assist. I appreciate everything you do for the community, and you all at Roots have created a wonderful product with Trellis, Bedrock, and Sage. When I say that I did extensive searching prior to asking this question, I was not exaggerating.

The point I’m trying to make here isn’t that I think you’re implying I didn’t search long enough, but just to convey that I honestly, sincerely did spend a reasonable amount of time into this before posting a thread.

Maybe I didn’t search long enough, maybe I was unlucky and didn’t happen to see the right resources, or maybe I’m just too stupid and I needed a more precise explanation. Whatever the case, I am sorry, and again I am truly appreciative of the time you’ve taken out of your day to help me directly.

I’m also glad that the heightened exposure most likely created by your reply has attracted another user, and it looks like he’s contributed some additional information which builds upon the great solutions you’ve already provided me. Man, I’ve edited this like 5 times now in the hope of expressing how grateful, appreciative, and remorseful I am, so please excuse the slight rambling.

Thank you again @benword, sincerely.

Please don’t hate me :disappointed:

2 Likes

Thanks, this helps. The main thing I wanted to do was make sure I don’t have extra stylesheets being loaded just for WooCommerce, which @benword explained perfectly for me. What you’ve said in your post here pretty much covers the rest of what I was wondering about.

1 Like

lol no worries :blue_heart:

Thanks man, I appreciate it. Really trying hard to learn all of this shit, because it’s about the most enjoyable programming I’ve done in years. It all really elevates WordPress to another level entirely.

@benword Can you please be more specific? This doesn’t help AT ALL.

Take WooCommerce out of the picture

What do you even mean by that?? Delete woocommerce? Use another ecommerce plugin?? wtf you mean, man???

manifest.json is where you’ll need to make the changes

Great! Now what do I do in manifest.json to make this work???

You didn’t offer any solutions you simply just posted links. What do I add to manifest.json to make this work? You guys assume we understand what you understand. Can you please be more specific and detailed???

Woah, man.

“Take Woocommerce out of the picture” as in “don’t treat Woocommerce special when trying to tackle this problem”.

The Sage ebook is a good place to look for the details you’re searching for. The support provided on this forum is provided for free and at-will by the Roots team. What you’re looking to do is relatively complicated and is going to require that you learn the things you don’t understand to achieve it.

EDIT: the answer is right here (line 55) in the documentation that Ben linked.

1 Like

I figured out a solution for Sage 8.4.2.

1. Remove the default woocommerce css
Taken from @drawcardau solution above; Add an external WooCommerce functions file to your functions.php

// functions.php

$sage_includes = [
  'lib/assets.php',    // Scripts and stylesheets
  'lib/extras.php',    // Custom functions
  'lib/setup.php',     // Theme setup
  'lib/titles.php',    // Page titles
  'lib/wrapper.php',   // Theme wrapper class
  'lib/customizer.php', // Theme customizer
  'lib/woocommerce-functions.php'  // <----- Add in my external WooCommerce functions
];

Create a woocommerce-functions.php file

// lib/woocommerce-functions.php

//Remove default woocommerce stylesheets
add_filter( 'woocommerce_enqueue_styles', 'jk_dequeue_styles' );
function jk_dequeue_styles( $enqueue_styles ) {
	unset( $enqueue_styles['woocommerce-general'] ); // Remove the gloss
	// unset( $enqueue_styles['woocommerce-layout'] ); // Remove the layout
	// unset( $enqueue_styles['woocommerce-smallscreen'] ); // Remove the smallscreen optimisation
	return $enqueue_styles;
}

Uncomment the woocommerce stylesheets you want to change. I want to keep the layout and smallcreen optimizations and only change the colors of the woocommerce buttons and make the input fields like .form-control. So I’m only dequeuing woocommerce-general.

2. Copy the woocommerce Sass files
Grab a copy of the woocommerce source .scss files from wp-content/plugins/woocommerce/assets/css and place them into your themes assets folder under assets/styles/woocommerce

3. Install bourbon
Woocommerce uses the bourbon mixing library so you must include it. Install it via bower by opening a console on your sage folder and running

bower install bourbon --save

4. Make edits to main.scss and woocommerce.scss
I didn’t include the woocommerce.scss file into the manifest.json. Instead I added it to the bottom of the main.scss file in assets/styles. If you’re overriding the layout or smallcreen files as well then include them here too. I’m only overriding the general woocommerce css so my import looks like so:

@import "woocommerce/woocommerce";

open up woocommerce.scss in the woocommerce folder you copied the files to and replace @import “bourbon with:

@import "../../../bower_components/bourbon/app/assets/stylesheets/bourbon";

You can now use the variables from bootstrap in your woo commerce sass. If anyone has a better solution please feel free to modify this.

3 Likes

Correct me please if I’m wrong but maybe this is not necessary as bower injects automatically bourbon:

// Automatically injected Bower dependencies via wiredep (never manually edit this block)
// bower:scss
@import "../../bower_components/bootstrap/scss/bootstrap.scss";
@import "../../bower_components/font-awesome/scss/font-awesome.scss";
@import "../../bower_components/slick-carousel/slick/slick.scss";
@import "../../bower_components/slick-carousel/slick/slick-theme.scss";
@import "../../bower_components/bourbon/app/assets/stylesheets/_bourbon.scss";
// endbower

I suppose that bourbon @include from _woocommerce.scss should be deleted, shouldn’t it?

I’ve just been going through this today. Here is a Sage 9 solution that should require minimal maintenance as the WooCommerce plugin gets updated:

  1. Create a custom woocommerce.php functions file in /theme-folder/app/

  2. In your new file, add a filter to remove default woocommerce stylesheets and scripts:

add_action('wp_enqueue_scripts', function () {

    if (function_exists('is_woocommerce')) {

        // Part 1: Dequeue styles on all pages (These will be added to the main.scss build)
        wp_deregister_style('woocommerce-general');
        wp_deregister_style('woocommerce-layout');
        wp_deregister_style('wc-block-style');

        // Part 2: Dequeue scripts on non-WC pages (I haven't figured out how to include these in main.js yet)
        if (!is_woocommerce() && !is_cart() && !is_checkout()) {

            # Styles not covered by part 1 (this one is trickier to remove because it contains an inline media query)
            wp_dequeue_style('woocommerce-smallscreen');

            # WooCommerce Scripts
            wp_dequeue_script('wc_price_slider');
            wp_dequeue_script('wc-single-product');
            wp_dequeue_script('wc-add-to-cart');
            wp_dequeue_script('wc-cart-fragments');
            wp_dequeue_script('wc-checkout');
            wp_dequeue_script('wc-add-to-cart-variation');
            wp_dequeue_script('wc-single-product');
            wp_dequeue_script('wc-cart');
            wp_dequeue_script('wc-chosen');
            wp_dequeue_script('woocommerce');
            wp_dequeue_script('prettyPhoto');
            wp_dequeue_script('prettyPhoto-init');
            wp_dequeue_script('jquery-blockui');
            wp_dequeue_script('jquery-placeholder');
            wp_dequeue_script('fancybox');
            wp_dequeue_script('jqueryui');

            # WooCommerce Multilingal scripts
            wp_dequeue_script('wcml-front-scripts');
            wp_dequeue_script('cart-widget');
        }
    }
}, 99);
  1. Initialise the new file in /theme-folder/resouces/functions.php, like so:
['helpers', 'setup', 'filters', 'admin', 'woocommerce']
  1. Add the plugins folder to webpack’s paths in theme-folder/resources/build/config.js, like so:
paths: {
  root: rootPath,
  assets: path.join(rootPath, 'resources/assets'),
  plugins: path.join(rootPath, '../../plugins'),
   ...
  1. Modify webpack.config.js so that it applies the url loader to the plugins folder, like so:
test: /\.(ttf|otf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
include: [
  config.paths.assets,
  config.paths.plugins
], 
...
  1. Add WooCommerce styles to main.scss
    Be careful not to use WooCommerce’s SASS files as its variables conflict with Bootstrap’s. Use the pre-compiled CSS files.
/** Import woocoomerce styles */
@import "./../../../../../plugins/woocommerce/packages/woocommerce-blocks/build/style.css";
@import "./../../../../../plugins/woocommerce/assets/css/woocommerce-layout.css";
// @import "./../../../../../plugins/woocommerce/assets/css/woocommerce-smallscreen.css";
@import "./../../../../../plugins/woocommerce/assets/css/woocommerce.css";

Then you can just yarn build as usual. Webpack will know the location of all the WooCommerce assets thanks to the webpack config modifications.

I’m a little concerned that the distribution file paths will cause problems, e.g.:
dist/_/_/_/_/plugins/woocommerce/assets/fonts/WooCommerce.woff
Notice the series of folders named with an underscore. This hasn’t caused any problems yet, but just a heads up!

Thank you to all the previous commenters on this post, and also this post:
https://discourse.roots.io/t/any-working-example-of-sage-9-latest-sage-9-0-0-beta-4-with-woocommerce-3-1-1/10099/20

3 Likes