# Visual Swap Debugging `HTMX_NAV_DEBUG_SWAPS` highlights DOM elements as they're updated by out-of-band HTMX swaps, useful for seeing at a glance what actually changed. ## Enable ```python # settings.py INSTALLED_APPS = [ ..., "htmx_nav", ..., ] # needed for static files + {% htmx_nav_debug_marker %} ``` ```python # settings.py HTMX_NAV_DEBUG_SWAPS = True ``` Two stylesheets are provided, depending on whether you want a client-side on/off toggle: **Toggleable** — highlighting only shows while `data-hn-debug-swaps` is present on `
`. Useful since `HTMX_NAV_DEBUG_SWAPS` is a server-side setting that needs a reload to flip, but the body attribute can be toggled instantly client-side (e.g. a dev-only button running `document.body.toggleAttribute('data-hn-debug-swaps')`): ```html {% load static %} ``` **Always-on** — highlighting fires any time a swap happens while `HTMX_NAV_DEBUG_SWAPS` is enabled, no body attribute needed: ```html {% load static %} ``` ## How it works With the setting on, any `Swap(target_id=...)` appends a script that toggles a `.hn-swap` class on that element (with a forced reflow, so repeated swaps retrigger it): ```html ``` `debug-swaps.css` flashes the background of any `.hn-swap` element: ```css [data-hn-debug-swaps] .hn-swap { animation: hn-flash-pulse 900ms ease-out; } @keyframes hn-flash-pulse { from { background-color: #fef08a; } to { background-color: transparent; } } ``` ## Two requirements for the flash to actually show up **A stable id on a persistent element.** The script runs `getElementById` *after* the swap lands, so `target_id` must be on a node that already exists in the page and keeps the same id every render. Put it on the wrapper in your base/shell template, not inside the swapped partial: ```html ``` ```python Swap("components/_sidebar_menu.html", context, target_id="sidebar") ``` An id that only exists inside the fragment, or that changes per render (`id="sidebar-{{ project.id }}"`), means `getElementById` finds nothing, or a stale node. **No opaque background covering the target.** The flash paints on the element `target_id` resolves to. If a child fully covers it with its own solid background, the flash renders underneath and is invisible: ```html ``` ## Manual OOB wrapping `target_id` bundles two things: which id the marker flashes, and telling `Swap` to auto-wrap your fragment in `