jQuery / Method / .toggle() - Show or Hide Elements

jQuery’s .toggle() hides each displayed element and shows each hidden one. .toggle(true) specifies showing, .toggle(false) specifies hiding, and a duration such as .toggle(800) animates the change. Choose between inverting the current state and specifying a known state.

Immediate inversion, explicit state and animation

The .toggle() API changes display immediately when called without arguments. If Alpha is visible and Beta hidden, one call hides Alpha and shows Beta. It does not synchronize the whole collection to one state.

Call Behavior Use when
.toggle() Invert each display state Current state should reverse
.toggle(true), .toggle(false) Specify show or hide Desired state is known
.toggle(800) Animate over 800ms Size and opacity should change
.toggle({ duration: 0, complete: fn }) Zero-duration effects path Finish immediately with completion handling

Timed effects animate width, height and opacity together. After hiding, display:none removes the layout space. 800 milliseconds is 0.8 seconds; larger values are slower. Boolean false and numeric zero are different argument forms. Hiding alone does not delete input values or other Document Object Model (DOM) state.

Complete two-panel example

Save all code as UTF-8 in toggle-demo.html and open it in a browser. Internet loads the official full jQuery file 4.0.0 from its content delivery network (CDN). Timed effects need the effects module; do not substitute the slim build. These interactions and the Console snippet were executed with 3.7.1 and 4.0.0.

Alpha uses flex display and Beta starts hidden. Controls stay outside the panels. Choose immediate, 800ms, 200ms or 0ms. A busy guard ignores additional toggle requests during an effect. With the system’s reduced-motion preference, the selected effect uses duration zero.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Toggle each panel visibility</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button, select, input { font: inherit; margin: 4px; max-width: 100%; box-sizing: border-box; }
    .panel { padding: 12px; margin: 10px 0; border: 1px solid teal; background: #edf9f6; }
    #alpha { display: flex; flex-wrap: wrap; align-items: center; }
    #beta { display: none; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>Toggle independently or set a known state</h1>
  <label for="mode">Mode:</label>
  <select id="mode"><option value="instant">No arguments</option><option value="800">800ms</option><option value="200">200ms</option><option value="0">0ms</option></select>
  <button type="button" id="toggle">Toggle each</button>
  <button type="button" id="show">Show both</button>
  <button type="button" id="hide">Hide both</button>
  <button type="button" id="reset">Reset</button>
  <div id="panels">
    <div class="panel" id="alpha">Alpha <input aria-label="Alpha note" value="Keep this note"></div>
    <div class="panel" id="beta">Beta panel</div>
  </div>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      const $panels = $("#panels > .panel");
      let busy = false, completed = 0;
      function report() {
        const visible = $panels.filter(":visible").map(function () { return this.id; }).get();
        $("#result").text(`visible=${visible.join(",") || "(none)"}\ncompleted=${completed}\nbusy=${busy}\nDOM panels=${$panels.length}`);
      }
      function settle() { $panels.stop(true, true); busy = false; completed = 0; }
      $("#toggle").on("click", function () {
        if (busy) return;
        completed = 0;
        const mode = $("#mode").val();
        if (mode === "instant") { $panels.toggle(); report(); return; }
        if (!$panels.length) { report(); return; }
        busy = true; report();
        const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
        $panels.toggle({ duration: reduced ? 0 : Number(mode), complete: function () {
          completed++;
          if (completed === $panels.length) busy = false;
          report();
        } });
      });
      $("#show").on("click", function () { settle(); $panels.toggle(true); report(); });
      $("#hide").on("click", function () { settle(); $panels.toggle(false); report(); });
      $("#reset").on("click", function () {
        settle(); $("#alpha").toggle(true); $("#beta").toggle(false);
        $("#alpha input").val("Keep this note"); $("#mode").val("instant"); report();
      });
      report();
    });
  </script>
</body>
</html>

Initially only Alpha is visible; both panels remain in the document.

visible=alpha
completed=0
busy=false
DOM panels=2
  1. With No arguments, press Toggle each: only Beta is visible and completed stays zero. Press again to return to Alpha.
  2. Edit Alpha’s input, hide it and show it again. The edited value remains; check that flex display returns too.
  3. Choose 800ms: afterward visible=beta, completed=2 and busy=false. Completion runs once per panel, not once for the whole collection.
  4. Repeated clicks during an effect are ignored here, preventing a growing queue. Reset before comparing 200ms from the same initial state.
  5. Show both reveals both and Hide both hides both. Repeated presses keep the same specified state.
  6. Reset settles running effects and restores Alpha shown, Beta hidden, the default field value and mode. The field changes because Reset explicitly calls .val(), not because it was hidden.

0ms looks similar to no arguments but runs complete per panel, giving completed=2. Reduced motion uses that same path without changing global site effects settings. Do not assume :visible during animation describes the final state; inspect final results after completion.

Booleans and resetting during an effect

Pass an actual Boolean when a condition determines display. true twice does not hide again. Run the following in the same page’s developer tools Console. It creates two independent temporary elements, checks the behavior and removes them.

const $holder = $('<div><p>A</p><p>B</p></div>').appendTo("body");
const $items = $holder.find("p");
$items.toggle(false);
$items.toggle(false);
console.log(`hide twice visible=${$items.filter(":visible").length}`);
$items.toggle(true);
$items.toggle(true);
console.log(`show twice visible=${$items.filter(":visible").length}`);
console.log(`DOM count=${$items.length}`);
$holder.remove();
hide twice visible=0
show twice visible=2
DOM count=2

Forcing a known state during animation requires handling the queue and internal effects state. settle() uses .stop(true, true) to clear queued work and finish the current effect, then resets busy and completed. The second true can run completion callbacks immediately, so reset counters after stop.

Reset then applies known display states. Stopping at an intermediate size differs from finishing at the destination. Testing also covered Reset during animation followed immediately by an argument-free toggle: Alpha correctly changed to Beta. For another rapid-click policy, decide whether to ignore, queue or finish the current effect first.

Troubleshoot visibility and different effects

Check selectors, .length and jQuery loading first. If an ancestor has display:none, .toggle(true) on its child may still not make it visible. Distinguish visibility:hidden and opacity:0 from display:none. toggle does not automatically remove every cause of invisibility.

If an effect ends immediately, inspect duration, reduced-motion settings and the loaded build. Choose an effect according to whether you need opacity alone or height alone rather than simultaneous size changes. Avoid repeatedly reading intermediate dimensions and writing them as permanent styles without a specific reason.

When hiding an area that holds focus, plan a control to reopen it and appropriate focus movement. This example keeps controls outside but does not implement a complete focus-restoration or expansion-announcement component. Display toggling alone does not complete all interface interactions.