WooCommerce can’t charge shipping by cart weight out of the box. Its Flat rate method only knows the number of items ([qty]), a percentage of the cart ([fee]) and one extra cost per shipping class, so for “0–5 kg costs 6, 5–20 kg costs 12” you need a table rate plugin. When shipping classes or postcodes “don’t work”, the cause is almost always in the settings: the zone order, the calculation type, a product without a class or a price typed with the wrong separator.

Why it happens

  • Flat rate has no weight field. You can enter a formula like 10 + ( 2 * [qty] ), but there is no placeholder for the cart weight. Product weights are stored, but no core method uses them to price shipping.
  • The customer lands in another zone. WooCommerce checks zones from the top of the list and uses the first one that matches. In a 2026 support thread on WordPress.org, a Europe zone sat above the UK zone, so UK customers never reached the UK prices.
  • The calculation type. With Per order, Flat rate charges only the most expensive class in the cart. With Per class, it adds every class. Many “my classes are ignored” questions come from this setting.
  • Products without a class, or classes without a price. A product with no class uses No shipping class cost. In the same thread, most products used classes that had no price in the international zone, so overseas orders paid only the base cost.
  • Variations. A variation can have its own shipping class. If you set the class only on the parent and a variation has another one, that variation is priced differently.
  • Prices typed with commas or dots. In a WordPress.org thread with 15 replies, class prices worked in one zone and not in three others. The prices in the broken zones had commas and dots; retyping them as plain numbers fixed it.
  • Products with no weight. In a weight table, a product with an empty weight counts as 0 kg and lands in the cheapest row.
  • Cached rates. WooCommerce keeps the shipping rates in the shopper’s session. After you change a setting, an old cart can still show the old price.

How to check it yourself

  1. List your zones. Go to WooCommerce > Settings > Shipping > Shipping zones. Zones are read from top to bottom. A zone that contains another (Europe contains the UK, “United States” contains one state) must go below it.
  2. Check the postcodes. Open the zone and look at Limit to specific zip/postcodes. One code per line; ranges are written 90210...99000 and wildcards 902*. Wildcards inside ranges (902*...990*) are not supported.
  3. Turn on debug mode. Go to WooCommerce > Settings > Shipping > Shipping settings, tick Enable debug mode and save. Add a product to the cart and open the classic Cart page with a test address: a notice tells you which zone matched. It only shows on the classic Cart page, not in the Cart or Checkout blocks. Turn it off when you finish, because customers see it too.
  4. Open each Flat rate. Check the Cost, the cost of every class your products use, No shipping class cost and Calculation type.
  5. Check the products. In Products > All Products, open a product that gets the wrong price. Look at Weight and Shipping class in the Shipping tab and, for variable products, in each variation.

How to fix it

If classes or postcodes give the wrong price:

  1. Put the smallest zones first. Drag the zones in the list so that a city or a postcode zone is above its state, and a country is above its continent.
  2. In every zone, open Flat rate and enter a cost for every class your products use. A class you leave out is not charged in that zone.
  3. Type prices as plain numbers, with the same decimal separator your store uses (WooCommerce > Settings > General) and no thousands separator. If a zone still fails, do what fixed the 15-reply thread: delete it, create it again and retype the prices.
  4. Choose the Calculation type: Per class if every class must be charged, Per order if you only want the most expensive one.
  5. Give every product a class. With bulk edit (Products > All Products, tick the products, Bulk actions > Edit) you can set the Shipping class of many at once. Check the variations one by one.
  6. Empty the cart or use a private window and test again.

If you need prices by weight:

Core WooCommerce can only fake it: create classes like “Up to 2 kg” or “2–10 kg”, put each product in one and give each class a cost. That prices each item by its own weight, not the cart total, so three 1 kg items cost three times the “Up to 2 kg” price. For real weight ranges you need a plugin:

  • Flexible Shipping (Octolize) is free on WordPress.org and covers rules by cart weight and cart total. Rules by shipping class or number of items are in its paid PRO version.
  • Table Rate Shipping is WooCommerce’s official paid extension, with rules by weight, items, items per class and price.
  • Any of them: set a row per weight range, add a row for “no limit” at the top end, and fill in the weight of every product first.

How to stop it from happening again

Shipping breaks again when you add a zone, a class or a product and forget one place. Our plugin ShipCraft adds a table rate method to your zones: rows with ranges of weight, items, subtotal, volume or longest side, and lists of shipping classes, categories, customer roles and postcodes (28*, 1000...1999, SW1A*). Rows can charge a fixed cost, per item, per kg, a percentage or “1.00 every 5 kg over 20”, and a row can be “not available” (for example over 30 kg). The part that prevents these mistakes is the simulator: you build a test cart with a country, postcode and products, and it shows the price of each rate, highlights the rows it used and explains every step, also with unsaved changes. It works with the block and classic checkout and HPOS, needs WooCommerce 8.9 or newer, and costs 35 USD a year for one site or 69 USD for life. You can try it in the demo. If you only need weight ranges, the free Flexible Shipping may be enough.

FAQ

Can WooCommerce calculate shipping by weight without a plugin? No. Flat rate uses items, a percentage and shipping classes. You can use classes as weight bands, but the price is per item, not per cart weight.

Why are my shipping class costs ignored? Usually the customer matches another zone, the class has no cost in that zone, or Calculation type is set to Per order, which charges only the most expensive class.

Why does a customer get the wrong zone? WooCommerce uses the first zone that matches, from the top of the list. Move the more specific zone above the broader one.

How do I charge by postcode? Create a zone and fill in Limit to specific zip/postcodes with codes, ranges (90210...99000) or wildcards (902*). Put that zone above the country zone.

What happens to products with no weight? They count as 0 kg, so a weight table puts them in the lowest row. Fill in the weight of every product before you switch to weight rates.