> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# ws-filter

> ws-filter renders an individual filter (checkbox, range, slider, image, label) for properties such as color, price, or availability and controls its values.

The `<ws-filter>` WebComponent enables filtering of the search results or categories based on various product properties. It supports different filter types such as checkboxes, value ranges (range), sliders, image-based selection (image), and clickable labels (label).

Both dynamically generated filters (e.g. colors) and individually defined custom filters (e.g. top sellers, availability) are supported.

***

## Requirement

* The component must be embedded inside `<ws-filters>`.
* For the filter component to work correctly, the `name=""` attribute must contain the technical column name from the data feed. This name must be strictly lowercase. This column name specifies which product data field the filter refers to. Examples of possible column names are:
  * `price`: For price filters.
  * `color`: For color-selection filters.
  * `brand`: For brand filters.
* The column names in the data feed are defined through the data fields that are activated in the configuration of the [search module](/en/ws-search/konfiguration-des-such-moduls) and used for filtering, sorting, or search.

***

## Dynamic and custom filters

The `<ws-filter>` component supports two types of filters: **dynamic filters** and **custom filters**. Both filter types can look the same in the frontend (e.g. as a checkbox).

### Dynamic filters

Dynamic filters are based directly on the product data — that is, on information available in the data feed for each individual product. Typical examples are color, size, or brand.

Typical use cases for dynamic filters:

* Color (`color`)
* Size (`size`)
* Brand (`brand`)
* Price (`price`)
* Ingredients (`ingredients`)

### Custom filters

Custom filters are not based on the individual values in the feed but on technically defined filter conditions (e.g. "stock ≥ 1"). Custom filters are therefore predefined filters where you decide exactly what should be filtered.

Typical use cases:

* Only available products (e.g. stock > 0)
* "New arrivals" based on the creation date
* Sale products (e.g. `is_reduced = true`)
* Rating (e.g. `rating >= 4`)

***

## Component for filters

The individual `<ws-filter>` elements for the filter items must always be placed inside `<ws-filters>`.

If `<ws-filters>` is already present, additional filters can simply be added there.

### Component for dynamic filters

The component can be embedded as follows on the category and search result page:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...

  <ws-filter type="checkbox" multiple="true" name="color"></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="size"></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="brand"></ws-filter>
  ...

  <ws-filter type="range" display-type="slider-fields" name="price"></ws-filter>
  ...

  <ws-filter type="checkbox" multiple="true" name="ingredients" negate></ws-filter>
  ...

  <ws-filter type="checkbox" multiple="true" name="ingredients" negate></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="neq_ingredients" negate></ws-filter>
  ...
</ws-filters>
```

* **Attributes**
  * `type`: Specifies the filter type.
    * `checkbox`: Selection via checkboxes (e.g. categories or colors).
      * `negate`: Enables the exclusion filter. Products that contain the selected filter values are not displayed. Only available with `type="checkbox"`.
    * `range`: Slider for value ranges (e.g. price).
      * `display-type`: Presentation type of the range filter.
        * `slider`: Renders the range filter only as a slider.
        * `fields`: Renders the range filter only as number input fields (2 input fields).
        * `slider-fields`: Renders the range filter as a slider and number input fields.
    * `image`: Image-based selection via clickable images (e.g. colors, materials, patterns). See [Image-based filters](#image-based-filters-type-image) for details.
    * `label`: Clickable label options with hidden checkbox input (e.g. sizes). See [Label filters](#label-filters-type-label) for details.
  * `multiple="true"`: Allows multi-selection (for `type="checkbox"`, `type="image"`, and `type="label"`; default for `image` and `label`: `false`).
  * `use-numeric-sort`: Sort numerically. Possible values: `true`.
  * `name`: Defines the product data field the filter is applied to, e.g.
    * `catids` for categories
    * `price` for price

<Info>
  Product data fields used as filters are evaluated positively by default; if a field should filter alternatively or exclusively negatively, the negative variant must be activated in the configuration. The logic is controlled by the `negate` attribute inside `<ws-filters>`. If both variants should be available in parallel, use the technical field name with the prefix `neq_` (e.g. `neq_field_name`) for the negative presentation; for exclusively negative use, no separate `neq_` field is required. Important: For the `neq_` field to exist at all, the `negate` attribute must additionally be set in the [import module](/en/ws-search/konfiguration-des-such-moduls).

  If the user should be able to switch between include and exclude themselves, the [ws-filter-toggle](/en/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filter-toggle) component is available for this.
</Info>

### Component for custom filters

The individual `<ws-filter>` elements for the filter items must always be placed inside `<ws-filters>`.

The component can be embedded as follows on the category and search result page:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
    <ws-filter type="checkbox" display-style="hide" name="salesrank" static-label="Top sellers only"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="rating" static-label="Top-rated products only"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="new_field" static-label="Newest products only"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="inventory" static-label="Available products only"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="reduced_field" static-label="Discounted products only"></ws-filter>
  ...
</ws-filters>
```

* **Attributes**
  * `type`: Specifies the filter type.
    * `checkbox`: Selection via checkboxes (e.g. categories or colors).
      * `negate`: Enables the exclusion filter. Products that contain the selected filter values are not displayed. Only available with `type="checkbox"`.
  * `name`: Defines the product data field the filter is applied to, e.g.
    * `catids` for categories
    * `price` for price
  * `disable-style`: Specifies how the filter should behave when it contains no values:
    * `hide`: The filter disappears graphically.
    * `inactive`: The filter is simply inactive → does not react.
    * `gray-out`: The filter is grayed out and inactive.
    * `line-through`: The filter is struck through and inactive.
    * `blur`: The filter is blurred (2px) and inactive.
    * `disable-style="disable-style"`: In addition to the predefined styles, you can also create a `disable-style` class and give it instructions in your own CSS file.
  * `static-label`: Optional label text for displaying a custom text for a custom filter.

<Info>
  `<ws-filter>` instances must always be placed inside `<ws-filters>`. If `<ws-filters>` is already present, the custom filters can be added there.
</Info>

### Image-based filters (`type="image"`)

With `type="image"`, filter options are rendered as clickable images — e.g. for colors, materials, or patterns.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter
  type="image"
  name="color"
  image-path="/images/colorpick/"
  image-format="jpg"
  label-class="color-swatch"
  multiple="true">
</ws-filter>
```

* **Attributes**
  * `image-path`: **Required.** Path to the directory containing the images of the filter options.
  * `image-format`: File extension of the images. Default: `jpg`
  * `image-map`: JSON mapping from filter value to file name — for image names that deviate from the automatic name normalization.
  * `label-class`: CSS class for the label element.
  * `multiple`: Allows multi-selection. Default: `false`

**Image name convention**

File names are derived automatically from the filter values. The values are normalized:

* Lowercase
* Spaces become underscores

Example: The value `Dark Blue` becomes the file `dark_blue.jpg`. If an image name deviates from this convention, the mapping can be defined via `image-map`.

**Behavior**

* The label of the filter option shows the image as a background image (`background-image`).
* A tooltip shows the original value of the option.
* Selected options receive the CSS class `.checked` on the label.
* If an image is missing, the text of the option is displayed as a fallback.

### Label filters (`type="label"`)

With `type="label"`, filter options are rendered as clickable labels with a hidden checkbox input — e.g. for sizes that should be offered as buttons instead of a checkbox list.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter
  type="label"
  name="size"
  label-class="size-class"
  data-template="{% value %} ({% count %})"
  multiple="true">
</ws-filter>
```

* **Attributes**
  * `label-map`: JSON mapping from filter value to display label (e.g. `{"xl": "Extra Large"}`) — for display texts that deviate from the technical value.
  * `data-template`: Mustache template for the label content (e.g. `{% value %} ({% count %})` for the value with hit count).
  * `label-class`: CSS class for the label element.
  * `multiple`: Allows multi-selection. Default: `false`

**Behavior**

* The checkbox input is rendered hidden; selection is done via the clickable label.
* Selected options receive the CSS class `.active` on the label.

### Sorting the filter values within a filter (custom order)

By default, filter values are sorted alphabetically (e.g. "Adult, Junior, Senior"), which is unsuitable for domain-specific orders (e.g. "Junior, Adult, Senior" or sizes S, M, L, XL, XXL).

For this you can, for example, provide a sort list per filter that is stored via JavaScript in the template.

#### Static sort list (manually maintained)

The "Life stage" filter contains the values Adult, Junior, and Senior but should be sorted in the following order: Junior - Adult - Senior.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
  <ws-filter type="checkbox" multiple="true" name="lebensphase"></ws-filter>
  ...
</ws-filters>
```

The sorting is implemented via the script:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script type="text/plain" id="sort-list-lebensphase">
  ['Junior','Adult','Senior']
</script>
```

* **Attributes**
  * `sort-list-` = technical name of the product data field/filter, always lowercase (e.g. `lebensphase`).
  * If new values are added, the list must be extended manually.

#### Sort list from the import (Wawi/ERP)

The "Life stage" filter contains the values Adult, Junior, and Senior but should be sorted in the following order: Junior - Adult - Senior.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
  <ws-filter type="checkbox" multiple="true" name="lebensphase"></ws-filter>
  ...
</ws-filters>
```

The sorting is implemented via a JavaScript that accesses a sort list provided by the import via the `WS-FilterSortList()` tag:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script type="text/plain" id="sort-list-lebensphase">
  ['Junior','Adult','Senior']
</script>
```

* **Attributes**
  * `WS-FilterSortList(FieldName)` is case-sensitive → the field name must be used exactly as in the original (e.g. `Lebensphase`).
  * In the script ID, `sort-list-` remains **lowercase** (`sort-list-lebensphase`).
  * Providing this import list must be coordinated with Wawi/ERP.

### Visibility of dynamic and custom filters (hiding)

Whether a filter is visible is controlled via the `filter-container` attribute, which must be assigned to HTML elements.

For more information see [ws-filters](/en/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filters).

***

## HTML & CSS

### CSS & styling for checkboxes

The component with the attribute `type="checkbox"` does not generate any specific CSS classes.

No additional CSS instructions or HTML elements can be added inside the component.

However, HTML elements and additional CSS styles can be added around the component to flexibly adjust the layout.

For example, for `type="checkbox"` the component generates the following source code:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<input type="checkbox" value="blau" id="farbgrp-blau" name="farbgrp">
<label for="farbgrp-blau">blau</label>

<input type="checkbox" value="rot" id="farbgrp-rot" name="farbgrp">
<label for="farbgrp-rot">rot</label>
```

### CSS & styling for image filters

With the `image` filter type, the image is set as a `background-image` on the label; the label itself can be styled with its own CSS class via the `label-class` attribute (e.g. for size and cropping of the image). Selected options additionally carry the class `.checked` and can be marked accordingly (e.g. with a border or a check-mark overlay).

### CSS & styling for label filters

With the `label` filter type, the checkbox input is hidden; only the label is visible and can be styled with its own CSS class via the `label-class` attribute (e.g. as a button). Selected options additionally carry the class `.active` and can be highlighted accordingly.

### CSS & styling for range sliders

[noUiSlider](https://refreshless.com/nouislider/) is used for the range sliders — a JavaScript library that provides user-friendly sliders:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.0/nouislider.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.0/nouislider.min.js"></script>
```

For `type="range"`, for example, the following source code is generated:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter type="range" display-type="slider-fields" name="price">

  2.00

  4000.00

  <style class="slider-tooltip-style">
    .noUi-tooltip {
      display: none;
    }
  </style>
  <input type="number" name="price-min" class="range-field" min="2" max="3999" step="1"
      value="2"><input type="number" name="price-max" class="range-field" min="3" max="4000" step="1" value="4000">

</ws-filter>
```

Features of `noUiSlider`:

* Dynamic range selection with two handles (e.g. price filter from 0 to 259 €)
* Tooltips showing the current values
* Customizable styling via CSS

The following classes are generated in the output and can be used for individual styling:

* `noUi-base`: Base container of the slider.
* `noUi-connect`: Area between the two slider handles (shows the selected range).
* `noUi-origin`: Position of the respective slider handle.
* `noUi-tooltip`: Tooltip that shows the current value of the handle.
* `noUi-handle`: The actual handle that can be moved.

The [noUiSlider library](https://refreshless.com/nouislider/) should be downloaded and can then be included directly or via the [WEBSALE PageSpeed tool](https://doku.websale.net/guide_jsjq.html#1einbindenneuerjavascript-dateienundnutzungdesminify-tools).

### JavaScript workaround for displaying the currency symbol in a price range

The function must of course be executed when the filter is selected and, for example, also when items are loaded.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script>
...
function wsPriceFilterCurrency() {
  var currencySymbol = document.createElement("span");
      currencySymbol.innerHTML = "~WS-CurrencySymbol~";
      currencySymbol = currencySymbol.innerText;
      var priceInputs = document.querySelectorAll("ws-filter[name='price'] input[type='number']");
      priceInputs.forEach(function(input) {
        var wrapper = input.closest(".range-field-wrapper");
        if (!wrapper) return;
        // Build new structure
        var inputGroup = document.createElement("div");
        inputGroup.className = "wsPriceFilterGroup";
        var prepend = document.createElement("div");
        prepend.className = "wsPriceFilterCurrency";
        prepend.textContent = currencySymbol;
        // Remove input from DOM and insert into new structure
        input.parentNode.removeChild(input);
        inputGroup.appendChild(prepend);
        inputGroup.appendChild(input);
        // Insert new structure in place of the original input
        wrapper.appendChild(inputGroup);
      });
    }
 ...
 </script>
```

***

## URL filter parameters

Filters can be passed directly to the search module via the URL – e.g. for campaigns, preselections, or direct links with active filters.

More about this in the documentation on [URL filter parameters](/en/ws-search/integration-in-die-templates-storefront/webcomponents/url-filterparameter-query-parameter).
