Lit has no special 'if' template syntax — conditional rendering is just JavaScript. This lesson covers the idiomatic patterns for showing or hiding content based on state.
Conditional Rendering Is Plain JavaScript
Because template expressions accept any JavaScript value, the most common conditional patterns from everyday JavaScript work directly inside html`...` templates: the ternary operator for either/or branches, and the && operator for 'render this or nothing'.
For more complex branching, extracting a helper method (or using the when() directive, covered in a dedicated lesson) keeps templates readable as the number of conditions grows.
The ternary picks one of two templates; && renders the error template only when errorMessage is truthy, otherwise renders false (which Lit treats as nothing).
Prefer nothing over '' for the 'render nothing' branch — it's more explicit about intent.
&& works because Lit treats false the same as null/undefined: nothing is rendered.
Avoid || for this purpose — 0 or '' as a falsy first operand can produce confusing output.
The when() directive (from lit/directives/when.js) is a slightly more declarative alternative to a ternary for either/or branches.
Conditional Rendering Cheat Sheet
Pick the right pattern for the situation.
Situation
Recommended Pattern
Either A or B
Ternary: `cond ? html`A` : html`B`
A or nothing
cond && html`A` or cond ? html`A` : nothing`
Many branches
Extracted helper method with if/switch
Declarative either/or
when(cond, trueCase, falseCase)
Toggle visibility, keep in DOM
?hidden=${!cond} boolean attribute binding
Hiding an Element vs. Removing It Entirely
There's an important distinction between conditionally *rendering* a template (adding/removing DOM nodes entirely) and conditionally *hiding* an already-rendered element with CSS. Removing and re-adding nodes is more expensive and resets any internal state (like scroll position or focus) inside that subtree; hiding with ?hidden keeps the DOM alive.
<!-- Removes/re-adds the whole panel -->
${this.open ? html`<div class="panel">...</div>` : nothing}
<!-- Keeps the panel in the DOM, toggles visibility with CSS -->
<div class="panel" ?hidden=${!this.open}>...</div>
Prefer ?hidden for frequently toggled UI (accordions, tabs) and template removal for rarely-shown, heavy content.
Extracting Multi-Branch Logic
Once you have three or more mutually exclusive states, a chain of ternaries becomes hard to read. Extract the logic into a small helper method with an early-return if/switch structure instead.
Using || instead of && for 'show or nothing' logic and getting tripped up by falsy-but-valid values like 0.
Nesting several ternaries directly inside a template instead of extracting a readable helper method.
Removing and re-adding heavy DOM subtrees on every toggle when a CSS-based ?hidden binding would be cheaper and preserve state.
Forgetting that nothing needs to be imported from lit — using the string 'nothing' by mistake does not have the same effect.
Key Takeaways
Conditional rendering in Lit is plain JavaScript — ternaries and && cover most cases.
Use nothing (imported from lit) for explicit 'render nothing' branches.
Prefer ?hidden CSS-based toggling over full template removal for frequently toggled UI.
Extract multi-branch conditional logic into a helper method once it grows past two options.
Pro Tip
If a piece of UI toggles on and off frequently (like a dropdown or tooltip), default to ?hidden/?disabled bindings first, and only reach for full template removal when the hidden content is expensive enough that you'd rather not keep it in memory at all.
You now know the idiomatic patterns for conditional templates. Next, learn how to render and update lists efficiently.