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
- Con No arguments, pulse Toggle each: solo se ve Beta y completed sigue en cero. Otra pulsación vuelve a Alpha.
- Edite el campo Alpha, ocúltelo y muéstrelo: conserva valor y vuelve a flex.
- Con 800ms, al final visible=beta, completed=2 y busy=false. El callback ejecuta una vez por panel, no una vez por colección.
- Los clics durante el efecto se ignoran, sin acumular una cola. Reinicie antes de comparar 200ms bajo las mismas condiciones.
- Show both muestra ambos y Hide both oculta ambos. Repetir conserva el estado indicado.
- 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.




