Q Card Docs
Modules

Comparison

Comparison table modules including sticky headers and ways-to-pay layouts.

Comparison

Description

Comparison modules show product or payment options side by side in a table layout. Some variants use a sticky header on desktop and expandable columns on mobile.

How to edit

  1. Go to Elementor → Editor → Templates.
  2. Search for Comparison (or a word from the specific template name below).
  3. Open the template and edit the column headings and cell content directly.
  4. Save, then check a page that uses the template.

Edit the copy inside the existing columns rather than adding or removing structure, so the table stays aligned and the sticky and expand behaviour keeps working.

Variants

TemplateWhat it is
CK – Comparison – HomepageThe homepage comparison module.
CK – Comparison – Ways to PayWays to pay, with sticky headings on desktop (uses ck-ways-to-pay)
CK – Comparison – Whats the DifferenceSide-by-side product comparison

How it behaves

  • Any column with the ck-highlighted class is expanded by default.
  • On tablet and mobile (under 1024px), tapping a column heading expands or collapses that column.
  • On desktop, a copy of the column headings stays fixed to the top of the screen while you scroll through the Ways to Pay table, so you can always see which column you are reading.

Classes

Primary classes used by the comparison component:

ClassWhat it's for
ck-comparisonMain wrapper
ck-ways-to-payWays-to-pay variant, used alongside ck-comparison
ck-comparison__columnA single column
ck-comparison__column-headerColumn heading
ck-highlightedMarks a column that starts expanded
ck-activeApplied to an expanded column
ck-sticky-activeApplied while the sticky heading is showing

Styling is done through a combination of the built-in page builder options as well as custom CSS where needed.

Script

This script is added using the HTML editor template. It handles the expandable columns on mobile and the sticky headings on desktop.

<script>
    (() => {
        document.addEventListener("DOMContentLoaded", () => {
            const highlightedColumns = document.querySelectorAll(
                ".ck-comparison__column.ck-highlighted",
            );

            highlightedColumns.forEach((column) => {
                column.classList.add("ck-active");
            });

            const columnHeaders = document.querySelectorAll(
                ".ck-comparison__column-header",
            );

            columnHeaders.forEach((header) => {
                header.addEventListener("click", () => {
                    if (window.innerWidth > 1023) return;

                    const column = header.closest(".ck-comparison__column");
                    if (column) {
                        column.classList.toggle("ck-active");
                    }
                });

                const stickyHeader = header.cloneNode(true);
                stickyHeader.classList.add(
                    "ck-comparison__column-header--sticky",
                );
                header.after(stickyHeader);
            });

            const comparison = document.querySelector(
                ".ck-comparison.ck-ways-to-pay",
            );
            if (!comparison) return;

            // Matches .ck-comparison__column-header--sticky { top: 239px }
            const STICKY_HEADER_TOP = 239;
            const STICKY_BOTTOM_OFFSET = 400;
            let ticking = false;
            let headerDocTop = 0;
            let comparisonDocBottom = 0;

            const originalHeader = comparison.querySelector(
                ".ck-comparison__column-header:not(.ck-comparison__column-header--sticky)",
            );
            if (!originalHeader) return;

            const getDocTop = (el) =>
                el.getBoundingClientRect().top + window.scrollY;

            // Measure document positions with sticky off so thresholds stay stable.
            const measure = () => {
                const wasSticky =
                    comparison.classList.contains("ck-sticky-active");
                if (wasSticky) comparison.classList.remove("ck-sticky-active");

                headerDocTop = getDocTop(originalHeader);
                comparisonDocBottom =
                    getDocTop(comparison) + comparison.offsetHeight;

                if (wasSticky) comparison.classList.add("ck-sticky-active");
            };

            const updateStickyState = () => {
                ticking = false;

                if (window.innerWidth < 1024) {
                    comparison.classList.remove("ck-sticky-active");
                    return;
                }

                const y = window.scrollY;
                const shouldStick =
                    y >= headerDocTop - STICKY_HEADER_TOP &&
                    y < comparisonDocBottom - STICKY_BOTTOM_OFFSET;

                comparison.classList.toggle("ck-sticky-active", shouldStick);
            };

            const onScroll = () => {
                if (!ticking) {
                    ticking = true;
                    requestAnimationFrame(updateStickyState);
                }
            };

            const onResize = () => {
                measure();
                updateStickyState();
            };

            window.addEventListener("scroll", onScroll, { passive: true });
            window.addEventListener("resize", onResize);
            measure();
            updateStickyState();
        });
    })();
</script>

On this page