woocommerce / woocommerce

A customizable, open-source ecommerce platform built on WordPress. Build any commerce solution you can imagine.
https://woocommerce.com
9.39k stars 10.76k forks source link

No way to modify injected wrapper div with class 'woocommerce'. #12191

Closed dsignr closed 7 years ago

dsignr commented 7 years ago

EXPLANATION OF THE ISSUE

Using version 2.3.6, when you visit the cart page, there is a wrapper div with class woocommerce being injected. I would like to remove/customize this wrapper div. However, it seems like there is no easy way to do so and all I'm doing is just fighting the framework to get something as simple as changing the presentational logic (HTML), which for some reason is embedded into the core (woocommerce/includes).

I searched all help docs. I searched for filter action/references, found none. I found just one StackOverflow thread about this with no answer.

There is absolutely no easy way for me to remove this unnecessary div. Using a custom WooCommerce theme, with a popular css framework and this breaks my grid layout.

Any help is much appreciated.

STEPS TO REPRODUCE THE ISSUE

Create a normal page.php either using the normal wordpress loop, or using the help doc listed here.

Visit the cart page. You should notice your content is wrapped around with a <div class="woocommerce></div>.

SYSTEM STATUS REPORT

### WordPress Environment ###

Home URL: http://localhost:8888/XYZ
Site URL: http://localhost:8888/XYZ
WC Version: 2.6.6
Log Directory Writable: ✔
WP Version: 4.6.1
WP Multisite: –
WP Memory Limit: 256 MB
WP Debug Mode: –
WP Cron: ✔
Language: en_US

### Server Environment ###

Server Info: Apache/2.2.29 (Unix) mod_wsgi/3.5 Python/2.7.10 PHP/7.0.0 mod_ssl/2.2.29 OpenSSL/0.9.8zh DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.22.0
PHP Version: 7.0.0
PHP Post Max Size: 32 MB
PHP Time Limit: 30
PHP Max Input Vars: 1000
cURL Version: 7.43.0
OpenSSL/0.9.8zd

SUHOSIN Installed: –
MySQL Version: ❌ 5.5.42 - We recommend a minimum MySQL version of 5.6. See: WordPress Requirements
Max Upload Size: 32 MB
Default Timezone is UTC: ✔
fsockopen/cURL: ✔
SoapClient: ✔
DOMDocument: ✔
GZip: ✔
Multibyte String: ✔
Remote Post: ✔
Remote Get: ✔

### Database ###

WC Database Version: 2.6.6
: 
woocommerce_sessions: ✔
woocommerce_api_keys: ✔
woocommerce_attribute_taxonomies: ✔
woocommerce_downloadable_product_permissions: ✔
woocommerce_order_items: ✔
woocommerce_order_itemmeta: ✔
woocommerce_tax_rates: ✔
woocommerce_tax_rate_locations: ✔
woocommerce_shipping_zones: ✔
woocommerce_shipping_zone_locations: ✔
woocommerce_shipping_zone_methods: ✔
woocommerce_payment_tokens: ✔
woocommerce_payment_tokenmeta: ✔
MaxMind GeoIP Database: ❌ The MaxMind GeoIP Database does not exist - Geolocation will not function. You can download and install it manually from http://dev.maxmind.com/geoip/legacy/geolite/ to the path: . Scroll down to \"Downloads\" and download the \"Binary / gzip\" file next to \"GeoLite Country\"

### Active Plugins (3) ###

Theme Check: by Otto42
pross – 20160523.1

WooCommerce: by WooThemes – 2.6.6
WP Super Cache: by Automattic – 1.4.8

### Settings ###

Force SSL: –
Currency: USD ($)
Currency Position: left
Thousand Separator: ,
Decimal Separator: .
Number of Decimals: 2

### API ###

API Enabled: ✔

### WC Pages ###

Shop Base: #61 - /shop/
Cart: #62 - /cart/
Checkout: #63 - /checkout/
My Account: #64 - /my-account/

### Taxonomies ###

Product Types: external (external)
grouped (grouped)
simple (simple)
variable (variable)

### Theme ###

Name: XYZ
Version: 1.2
Author URL: http://www.example.com/
Child Theme: ❌ – If you're modifying WooCommerce on a parent theme you didn't build personally
then we recommend using a child theme. See: How to create a child theme

WooCommerce Support: ✔

### Templates ###

Overrides: XYZ/.DS_Store
XYZ/woocommerce/archive-product.php
XYZ/woocommerce/cart/.DS_Store
XYZ/woocommerce/cart/cart-empty.php
XYZ/woocommerce/cart/cart-item-data.php
XYZ/woocommerce/cart/cart-shipping.php
XYZ/woocommerce/cart/cart-totals.php
XYZ/woocommerce/cart/cart.php
XYZ/woocommerce/cart/cross-sells.php
XYZ/woocommerce/cart/mini-cart.php
XYZ/woocommerce/cart/proceed-to-checkout-button.php
XYZ/woocommerce/cart/shipping-calculator.php
XYZ/woocommerce/content-product.php
XYZ/woocommerce/content-widget-product.php
XYZ/woocommerce/global/.DS_Store
XYZ/woocommerce/global/breadcrumb.php
XYZ/woocommerce/global/form-login.php
XYZ/woocommerce/global/quantity-input.php
XYZ/woocommerce/global/sidebar.php
XYZ/woocommerce/global/wrapper-end.php
XYZ/woocommerce/global/wrapper-start.php
XYZ/woocommerce/loop/.DS_Store
XYZ/woocommerce/loop/add-to-cart.php
XYZ/woocommerce/loop/loop-end.php
XYZ/woocommerce/loop/loop-start.php
XYZ/woocommerce/loop/no-products-found.php
XYZ/woocommerce/loop/orderby.php
XYZ/woocommerce/loop/pagination.php
XYZ/woocommerce/loop/price.php
XYZ/woocommerce/loop/rating.php
XYZ/woocommerce/loop/result-count.php
XYZ/woocommerce/loop/sale-flash.php
XYZ/woocommerce/notices/.DS_Store
XYZ/woocommerce/notices/error.php
XYZ/woocommerce/notices/notice.php
XYZ/woocommerce/notices/success.php
XYZ/woocommerce/product-searchform.php
mikejolley commented 7 years ago

This isn't something we plan on allowing you to change - we use this for styling, scripts and so on. It's certainly not unnecessary if you want a working store :) I see no reason why it would break a grid layout unless you're not removing existing CSS rules applied to it. Dequeue the CSS.

dsignr commented 7 years ago

My grid structure is currently this way:

<div class="grid">
     <div class="woocommerce">
           ...
     </div>
     <div class="column-3">
           ...
     </div>
</div>

The problem is my CSS framework expects a column or row element to be the first child, but, because WooCommerce injects this div, it breaks my layout. IF I were to fix this, I would need to re-write the same definitions for .column class for .woocommerce, which defeats the purpose of me using a CSS grid system and a framework. In the very least, a hook would be nice.

It's awesome that WooCommerce enables anyone to run a store like Amazon in no time, but the fact that I have to fight the framework just to modify some CSS classes is frankly, appalling. This is just one of several issues I've experienced using WooCommerce where the presentational logic is buried inside some absurd php include/template hook, rather than letting it be where it belongs.

I hope you will take this as constructive criticism in improving the framework. Cheers.

mikejolley commented 7 years ago

The div is the only consistent way for us to have a class we can target with CSS and Javascript. I'm sure there would be more users complaining if we applied our code across all elements on all pages, thats why it's there.

Not sure why it would be nested though, unless you're using shortcodes?

dsignr commented 7 years ago

The div is the only consistent way for us to have a class we can target with CSS and Javascript. I'm sure there would be more users complaining if we applied our code across all elements on all pages, thats why it's there.

Thanks for the reply, I understand that as well.

<div class="grid">
     <?php the_content(); ?>  //I also tried <?php woocommerce_content(); ?>
     <div class="column-3">
           ...
     </div>
</div>

(Note: Code above is simplified) The nesting happens because I use it as in the code above. That's the reason I wanted to check if there's a way to modify the class name (or at atleast add). If I put the template code outside my grid, it would still break my page layout. So, kind of stuck here. Your thoughts?

mikejolley commented 7 years ago

The_content can vary between pages/post types - would it not be best to wrap that in a column- and then if you require subcolumns, make a grid inside of that? It's not clear what you're trying to control here - product grid, cart page, regular page?

dsignr commented 7 years ago

Thanks for your quick replies!

then if you require subcolumns, make a grid inside of that

I wanted to avoid nested grids as they will add more code (another wrapper, row, column, etc), but I guess this is the only solution for now.

I need more coffee. Thanks for your help so far 👍

SoLoGHoST commented 5 years ago

Is it atleast possible to add additional classes to the div element? For example, if I wanted to add "row" class for bootstrap capabilities. How to add an additional class to the<div class="woocommerce"> div element?

Can you folks atleast provide the ability for this?

monecchi commented 5 years ago

There should be at least a method to add additional css classes to <div class="woocommerce"> without relying on jQuery or waiting for the DOM to load in order to apply a js hack. Perhaps a simple filter function which would prevent the .woocommerce css class from being stripped out but would let additional classes to be passed along with it.

anunay commented 5 years ago

I am having the same issue, and I think we can have some filter we can apply so we can still have WooCommerce class and then append additional classes as needed. Just no need to remove WooCommerce but to append some additional classes all we want. thank you

lennyanders commented 4 years ago

I just wrote a little filter to do this. I think it is likely to break the default WooCommerce Styles and Scripts, but I don't use any of them, so it doesn't matter to me, and to you probably too.

function lenny_remove_div_class_woocommerce($content) {
  libxml_use_internal_errors(true);

  $html = new DOMDocument();
  $html->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  $container = (new DOMXpath($html))->query("//div[contains(@class,'woocommerce')]")[0];
  if ($container) {
    foreach ($container->childNodes as $child) {
      $container->parentNode->insertBefore($child->cloneNode(true), $container);
    }
    $container->parentNode->removeChild($container);
  }
  return $html->saveHTML();
}
add_filter('the_content', 'lenny_remove_div_class_woocommerce', 100);
sanjeevbeekeeper commented 5 months ago

Don't do this ❌

page-my-account.php

<div class="row">
  <?php the_content(); ?>
</div>

navigation.php

<div class="col-6">
  <nav>
    ...
  </nav>
</div>

my-account.php

<div class="col-6">
  <div class="woocommerce-MyAccount-content">
    <?php do_action( 'woocommerce_account_content' ); ?>
  </div>
</div>

DOM

<div class="row">
  <div class="woocommerce">
    <div class="col-6"></div>
    <div class="col-6"></div>
  </div>
</div>

Do this ✔️

You could include everything in your woocommerce / myaccount / my-account.php page

my-account.php

<div class="row">
  <div class="col-6">
    <?php do_action( 'woocommerce_account_navigation' ); ?>
  </div>
  <div class="col-6">
    <div class="woocommerce-MyAccount-content">
      <?php do_action( 'woocommerce_account_content' ); ?>
    </div>
  </div>
</div>

DOM

<div class="woocommerce">
  <div class="row">
    <div class="col-6"></div>
    <div class="col-6"></div>
  </div>
</div>