Instant show and hide
The simplest effects are instant:
<p id="note">This note can be hidden.</p>
<button id="hide">Hide</button> <button id="show">Show</button>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("#hide").on("click", function () {
$("#note").hide();
console.log("hidden, display =", $("#note").css("display"));
});
$("#show").on("click", function () {
$("#note").show();
console.log("shown, display =", $("#note").css("display"));
});
</script>hidden, display = none
shown, display = block.hide() sets display: none, so the element takes up no space and is not read by screen readers. It remembers the previous display value, so .show() puts back block, flex, inline or whatever the element used before.
Toggle
.toggle() flips the state: visible elements hide and hidden ones show.
<button id="more" aria-expanded="false" aria-controls="details">Show details</button>
<div id="details" hidden>Ships in 2 days. Free returns within 30 days.</div>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("#details").removeAttr("hidden").hide(); // let jQuery manage it from here
$("#more").on("click", function () {
$("#details").toggle();
const open = $("#details").is(":visible");
$(this).text(open ? "Hide details" : "Show details").attr("aria-expanded", open);
console.log("open:", open);
});
</script>open: true
open: false
open: trueThe button's text and its aria-expanded attribute are updated every time, so everyone knows the current state. Notice the first line: the details start with the HTML hidden attribute, so they are hidden even before JavaScript runs, then jQuery takes over.
Pass a boolean to force the state, which is safer when the code may run more than once:
$("#admin-tools").toggle(user.isAdmin);
$("#empty-message").toggle(items.length === 0);Animated show and hide
Give .show(), .hide() or .toggle() a duration, and the element animates its width, height and opacity together:
<button id="box-btn">Toggle with animation</button>
<div id="box" style="width: 160px; height: 80px; background: #a5b4fc; margin-top: 8px"></div>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("#box-btn").on("click", function () {
$("#box").toggle(400, function () {
console.log("finished, visible:", $(this).is(":visible"));
});
});
</script>finished, visible: falseThe duration can be:
- a number of milliseconds, such as
300; "fast"(200ms) or"slow"(600ms);- left out of animated calls such as
.fadeIn(), which use the default 400ms.
Callbacks
The function passed after the duration is a callback: it runs when the animation finishes, once per element. Code after the call runs straight away, before the animation is done:
<button id="go">Hide</button>
<p id="msg">Goodbye</p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("#go").on("click", function () {
$("#msg").hide("fast", function () {
console.log("2. callback: animation finished");
});
console.log("1. this line runs first");
});
</script>1. this line runs first
2. callback: animation finishedThis ordering is the most important thing to understand about jQuery animations. If you want something to happen after an effect, put it in the callback (or use the promise technique in the queue lesson).
Hiding with jQuery or with a class?
There are three common ways to hide something:
| Method | Good for |
|---|---|
.hide() / .show() |
quick scripts, and animated showing and hiding |
.toggleClass("is-hidden") with CSS |
when CSS should decide how hiding looks (for example a CSS transition), or different screen sizes behave differently |
the hidden attribute, .prop("hidden", bool) |
plain markup that is hidden before any script runs |
.show() sets an inline display style, which beats your stylesheet. If you later try to hide the element with a CSS class, the inline style wins. Mixing approaches on the same element causes confusing bugs, so pick one per element.
Respecting reduced motion
Some people get dizzy or distracted from movement on screen and ask their system to reduce motion. You can turn off all jQuery animations for them with one line; effects then jump straight to their end state, and callbacks still run:
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
$.fx.off = true;
}Common mistakes
- Putting follow-up code after an animated call instead of in its callback.
- Forgetting to update
aria-expandedon the button that shows or hides content. - Mixing
.show()with CSS classes that also setdisplay. - Animating many large elements at once, which can make a page stutter; animate the container instead.
Exercise
Make a "Read more" button that toggles a hidden paragraph with the "fast" speed. When the animation finishes, change the button text to "Read less" or "Read more" depending on whether the paragraph is visible.
Show one possible answer
<button id="rm">Read more</button>
<p id="more" style="display: none">The rest of the story...</p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("#rm").on("click", function () {
const $btn = $(this);
$("#more").toggle("fast", function () {
$btn.text($(this).is(":visible") ? "Read less" : "Read more");
console.log($btn.text());
});
});
</script>Read lessKey points
- .hide() sets display: none and remembers the old display value; .show() restores it.
- .toggle() shows hidden elements and hides visible ones; .toggle(condition) forces a state.
- Pass a duration ("fast", "slow" or milliseconds) to animate, and a callback to run code when it finishes.
- Hidden elements are removed from the accessibility tree too; keep aria-expanded in step on the button that controls them.