HUSKY - WooCommerce Product Filter Professional

WooCommerce Filter Color Swatches Showing Black: Setup and Fixes

WooCommerce filter color swatches showing black are almost never a broken plugin. In WooCommerce a color attribute is a list of words: the term Red is only text, and WooCommerce stores nothing that says which color it means. The product filter therefore keeps its own color or image for every term, and a term without one is painted with the fallback #000000. Below is how the Color and Image filter types work, why swatches turn black, and how to set up colors, images, tooltips and the selected state so the filter looks the way you planned.

Why WooCommerce filter color swatches show black

When a taxonomy is shown with the Color type, the plugin looks up, for each term, a value saved in its own settings under the taxonomy and the term slug. An image wins over a color; a color is used when there is no image; with neither, the swatch is drawn #000000. So every black swatch is a term the filter has no value for. The usual reasons:

  • The colors were never entered in the filter. Colors stored by the theme, by a variation swatches plugin or in the term description are not read: every plugin keeps them in its own format. The filter needs its own values, or the snippet further below that copies them.
  • A term was added later. New terms get no color. In the term list on the settings page their field shows #000000, and saving the page stores that black.
  • A term slug was changed. Colors are saved by slug, so after editing a slug the old value no longer matches. Enter it again.
  • The term is a subcategory. The settings page offers color and image fields only for top-level terms, and the Color and Image types draw one level of the hierarchy. On a category archive the plugin narrows the category filter to the children of the current category (see why the filter shows only subcategories); those children have no color, so they come out black.
  • The block is a Smart Designer element. Types in the Smart designer group of the type drop-down keep their own colors and images, set with the Set terms color/image button of the Smart Designer. Colors entered for the Color type do not apply to them, and the reverse.

Two pieces of old advice no longer apply in version 3.4.6: Color and Image are built-in and always active, so there is nothing to switch on in the Extensions tab, and changing a block to another type and back no longer wipes its colors. On a WPML or Polylang shop, a translated term without its own color or image takes those of the same term in the default language, so set the colors once there.

Set up a color filter for a WooCommerce attribute

The Color type works with any product taxonomy: a global attribute such as pa_color, categories, tags or brands. Values typed straight into a single product as a custom attribute are not a taxonomy, so they cannot be shown as swatches; create the attribute under Products > Attributes instead.

  1. Open WooCommerce > Settings > Products Filter, tab Structure.
  2. Find the attribute row (for example Product Color), tick it, and in its type drop-down choose Color from the Advanced types group.
  3. Save the settings. The term list belongs to the saved type, so it appears only after the page has reloaded.
  4. Click toggle color terms under the row. Every term has a color picker and an image field with a Select Image button. Enter a HEX value such as #c62828, or choose an image for patterns, textures and multicolor terms.
  5. Save again and check the shop page in a private window. If a page cache is active, clear it: the colors are written into the page HTML.

The cog button next to the row (additional options) holds the settings of the block: Tooltip text (Yes/No: a tooltip with the term name over each swatch, off by default), Show in one column (prints the term name next to its swatch) and Behavior as radio button (one color at a time). The Tooltip field in the same popup is something else: a text shown next to the block title. All options are listed on the Color extension page.

Reuse the colors of a swatch plugin

If a variation swatches plugin already holds a HEX value for every term, you can hand those values to the filter instead of typing them twice. The snippet reads them from the term meta each time the filter is drawn. Replace the meta key with the one your swatch plugin uses; its documentation names it, or look at the rows of one color term in the wp_termmeta table.

/*
 * Product filter: take swatch colors from the term meta of a swatch plugin.
 * Child theme functions.php or a code snippets plugin.
 */
add_filter('woof_modify_settings_before_action', function ($settings) {
    $taxonomy = 'pa_color';      // the attribute shown with the Color type
    $meta_key = 'your_meta_key'; // the term meta key in which the swatch plugin saves the HEX value

    $terms = get_terms(array('taxonomy' => $taxonomy, 'hide_empty' => false));
    if (is_wp_error($terms)) {
        return $settings;
    }

    foreach ($terms as $term) {
        $hex = get_term_meta($term->term_id, $meta_key, true);
        if (is_string($hex) && preg_match('/^#[0-9a-fA-F]{3,8}$/', $hex)) {
            $settings['color'][$taxonomy][urldecode($term->slug)] = $hex;
        }
    }

    return $settings;
});

Terms without a value in the swatch plugin keep the color set in the filter. An image set in the filter still wins over both.

Image swatches in the product filter: patterns, logos and categories

The Image type shows each term as a picture. The setup is the same (type Image, save, toggle image terms, set an image per term), with two differences that explain most surprises:

  • A term without an image is not shown at all. If an image filter shows only some brands, or an empty block, the missing terms have no image.
  • Size and look come from the term's Image styles (the button next to the image field). The default is a 100 × 50 px box with the picture stretched to fill it (background-size: 100% 100%), which distorts any logo that is not 2:1.

Use the URL of the image file itself, which is what Select Image inserts, not the address of its attachment page. To show whole logos on every term at once, override the inline styles in Advanced > Code > Custom CSS code:

/* Image filter: whole logos, no stretching */
.woof .woof_list_image .woof_image_term {
    width: 90px !important;
    height: 60px !important;
    background-size: contain !important;
    background-repeat: no-repeat !important;
    background-position: center !important;
    background-color: #fff;
}

To print the term name under each picture, set Show image title to Yes in the block's additional options. More options: Image extension.

Category thumbnails and brand logos without uploading them again

WooCommerce already stores a thumbnail for each product category and a logo for each brand of its Brands taxonomy, both in the term meta thumbnail_id. The filter hook woof_taxonomy_image lets the Image type use them. It also fixes subcategories: the settings page has image fields only for top-level terms, but the hook supplies a picture for every term, so on a category archive the subcategories appear with their own thumbnails instead of being skipped.

/*
 * Image filter: use the WooCommerce category thumbnail or brand logo.
 * Child theme functions.php or a code snippets plugin.
 */
add_filter('woof_taxonomy_image', function ($image, $term) {
    if (!empty($image) || !in_array($term['taxonomy'], array('product_cat', 'product_brand'), true)) {
        return $image;
    }

    $thumbnail_id = (int) get_term_meta($term['term_id'], 'thumbnail_id', true);
    if ($thumbnail_id) {
        $url = wp_get_attachment_image_url($thumbnail_id, 'thumbnail');
        if ($url) {
            return $url;
        }
    }

    return $image;
}, 10, 2);

A term with a thumbnail shows it, even if another image is set in the filter; a term without one falls back to the filter's image, and stays hidden if there is none. The $term passed to the hook is an array (term_id, slug, taxonomy, name), not a WP_Term object.

Multicolor products and too many shades

A color filter can offer only the terms of the attribute, and it lists a product under every term assigned to it. That gives three patterns:

  • A product in several colors. Assign all its colors in the product's attribute. It is found under each of them.
  • A multicolor or patterned product. Add a term such as Multicolor, Striped or Floral, assign it, and give it an image in the color term list instead of a HEX value. The image covers the swatch (it is drawn with background-size: cover), so a small square of the pattern is enough.
  • Hundreds of shades. The filter cannot merge terms into groups. Create a second global attribute, for example Color family, with ten or twelve main colors, assign it to the products next to the exact shade, and put the family attribute into the filter with the Color type. Untick Visible on the product page for it if customers should see only the exact shade. For many products, the WooCommerce product CSV exporter and importer can fill the new attribute in bulk.

Tooltips: remove the description, stop clipping, move it off the image

The Color type shows a tooltip only when Tooltip text is Yes. The Image type always prints one, with the term name and, when counts are enabled, the count. Both can add the term description, but in 3.4.6 it is looked up by slug where WordPress expects a term ID: for an ordinary slug such as nike nothing is found, while a slug starting with a digit (32gb, 4k) is read as an ID and can bring in the description of an unrelated term. To keep descriptions out of image tooltips, use woof_image_allow_term_desc:

/*
 * Image filter: no term descriptions in tooltips.
 * Child theme functions.php or a code snippets plugin.
 */
add_filter('woof_image_allow_term_desc', function ($show, $tax_slug) {
    return false; // or only for one taxonomy: return $tax_slug === 'product_brand' ? false : $show;
}, 10, 2);

Keep the 10, 2 at the end. The callback declares two parameters; without the accepted-arguments value WordPress passes only one and PHP stops with a Too few arguments fatal error. A callback that takes only $show needs no extra values.

The other tooltip problems are CSS, added in Advanced > Code > Custom CSS code:

/* Color tooltips cut off at the top or left: the color list hides overflow */
.woof ul.woof_list.woof_list_color {
    overflow: visible;
}

/* Tooltip sticking out of a narrow sidebar: open it to the right */
.woof p:hover.woof_tooltip span.woof_tooltip_data {
    left: 0;
    margin-left: 0;
}

/* Image tooltip covering the picture: show it above */
.woof_container_image p:hover.woof_tooltip span.woof_tooltip_data {
    bottom: 100%;
}

/* No tooltip on image swatches at all */
.woof_container_image p.woof_tooltip span.woof_tooltip_data {
    display: none;
}

If a tooltip is still clipped after the first rule, a container of the theme around the sidebar hides overflow. Find it with the browser's developer tools (the element whose styles contain overflow: hidden) and set it to visible.

Layout and the selected state

Color swatches are 50 × 50 px and flow in rows. The rules below cover the usual layout requests; they go into the same Custom CSS code field.

/* Smaller color swatches */
.woof .woof_color_term {
    width: 32px;
    height: 32px;
}

/* "Show in one column" still puts several items in a row */
.woof ul.woof_list_color.woof_color_title_col li {
    display: block !important;
}

/* "Not toggled terms count" shows the button but hides no colors */
.woof ul.woof_list_color li.woof_hidden_term {
    display: none !important;
}

/* Theme styles stack the image swatches in one column */
.woof ul.woof_list_image li {
    display: inline-block;
}

The two !important rules are needed because the Color stylesheet forces display: inline-block !important on every list item, which outranks both the one-column layout and the hidden state used by Not toggled terms count.

The selected state is the other common complaint. A selected color gets a dark border; a selected image gets exactly the same border as a hovered one. On a phone the hover state sticks after a tap, so when a customer taps an image again to deselect it, it still looks selected and the filter seems stuck. Give the two states different looks:

/* Image filter: selected differs from hover */
.woof .woof_image_term.checked {
    border-color: #289e80 !important;
    box-shadow: 0 0 0 2px #289e80;
}
.woof .woof_image_term:not(.checked):hover {
    border-color: #c6c6c6 !important;
}

/* Color filter: a clearer ring around the selected swatch */
.woof .woof_color_term.checked {
    border-color: #111;
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px #111;
}

/* Bold name of the selected color ("Show in one column" = Yes) */
.woof .woof_color_title.woof_checkbox_label_selected {
    font-weight: 700;
}

For round swatches see circular color swatches. Counts appear only where there is text: in the tooltip, next to the name with Show in one column, and under the picture with Show image title.

If the swatches still look wrong

  • Black swatch: open toggle color terms and check that the term has a real value, not #000000. New terms start black, and a term whose slug was edited needs its color again.
  • Empty swatch with only a border: the image URL does not load. Open it in a new tab; it must be the file itself.
  • Terms missing in an image filter: they have no image, or they are subcategories (use the thumbnail snippet).
  • Colors entered but still black on the shop: the block may be a Smart Designer element with its own colors, or a page cache serves the old HTML.
  • Styling ignored: the theme's CSS is more specific. Inspect the swatch in the browser, see which rule wins, and make yours more specific.

If a swatch still shows the wrong color, ask on the HUSKY support forum with a link to the filter page and the attribute it uses.