jQuery / Método / .toggle() - Mostrar u ocultar elementos

En jQuery, .toggle() oculta cada elemento visible y muestra cada uno oculto. .toggle(true) ordena mostrar, .toggle(false) ocultar y .toggle(800) anima el cambio. Distinga invertir el estado actual de establecer uno conocido.

Inversión inmediata, estado y animación

La API de .toggle() cambia display inmediatamente sin argumentos. Si Alpha está visible y Beta oculto, un uso oculta Alpha y muestra Beta. No sincroniza toda la colección al mismo estado.

Llamada Comportamiento Cuándo usarla
.toggle() Invertir cada estado Cambiar al contrario
.toggle(true), .toggle(false) Mostrar u ocultar explícitamente Estado deseado conocido
.toggle(800) Animar durante 800ms Cambiar tamaño y opacidad
.toggle({ duration: 0, complete: fn }) Efecto de duración cero Final inmediato con callback

Los efectos temporizados cambian ancho, alto y opacidad. Al terminar de ocultar, display:none elimina el espacio ocupado. 800ms son 0,8 segundos y un valor mayor es más lento. false booleano y cero numérico son formas distintas. Ocultar no elimina valores ni otros estados del modelo de objetos del documento (DOM).

Ejemplo completo con dos paneles

Guarde todo el código en UTF-8 como toggle-demo.html y ábralo en el navegador. Internet carga el archivo oficial completo de jQuery 4.0.0 desde la red de distribución de contenido (CDN). Los efectos temporizados necesitan effects: no use slim. Las interacciones y el fragmento de consola se ejecutaron con 3.7.1 y 4.0.0.

Alpha usa flex y Beta empieza oculto. Los controles quedan fuera. Elija inmediato, 800ms, 200ms o 0ms. busy ignora peticiones adicionales durante el efecto. La preferencia del sistema de movimiento reducido aplica duración cero.

<!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>

Al principio solo se ve Alpha; ambos paneles siguen en el documento.

visible=alpha
completed=0
busy=false
DOM panels=2
  1. Con No arguments, pulse Toggle each: solo se ve Beta y completed sigue en cero. Otra pulsación vuelve a Alpha.
  2. Edite el campo Alpha, ocúltelo y muéstrelo: conserva valor y vuelve a flex.
  3. Con 800ms, al final visible=beta, completed=2 y busy=false. El callback ejecuta una vez por panel, no una vez por colección.
  4. Los clics durante el efecto se ignoran, sin acumular una cola. Reinicie antes de comparar 200ms bajo las mismas condiciones.
  5. Show both muestra ambos y Hide both oculta ambos. Repetir conserva el estado indicado.
  6. Reset termina efectos y restaura Alpha visible, Beta oculto, campo y modo iniciales. El valor cambia por .val() explícito, no por ocultar.

0ms se parece visualmente a no pasar argumentos, pero ejecuta complete por panel y da completed=2. Movimiento reducido usa esa ruta sin cambiar efectos globales del sitio. :visible durante la animación no garantiza el estado final; compruébelo tras completar.

Booleanos y reinicio durante el efecto

Pase un booleano real para decidir la visibilidad por condición. Dos true no vuelven a ocultar. Ejecute esto en la consola de la misma página; crea dos elementos temporales y después los elimina.

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

Imponer un estado durante la animación requiere gestionar cola y estado interno. settle() usa .stop(true, true) para vaciar la cola y terminar el efecto, y después reinicia busy y completed. El segundo true puede ejecutar callbacks inmediatamente: ponga los contadores a cero después de stop.

Reset aplica luego estados conocidos. Detener a tamaño intermedio difiere de terminar en destino. Se verificó Reset durante la animación seguido de inversión sin argumentos: Alpha cambió correctamente a Beta. Para otra política de clics, decida antes entre ignorar, esperar o terminar el efecto actual.

Investigar visibilidad o efectos distintos

Compruebe selector, .length y carga de jQuery. Un antecesor con display:none puede impedir ver al hijo aunque use .toggle(true). Distinga visibility:hidden y opacity:0. toggle no elimina todas las causas de invisibilidad.

Si termina inmediatamente, revise duración, movimiento reducido y archivo cargado. Elija según necesite solo opacidad, solo altura o cambios combinados. Evite escribir repetidamente tamaños intermedios como estilos permanentes sin una razón concreta.

Al ocultar una zona con foco, diseñe reapertura y movimiento del foco. El ejemplo conserva controles externos, pero no implementa toda la restauración ni los anuncios de expansión. Mostrar y ocultar no completa por sí solo las interacciones.