A developer shares a workaround for detecting empty HEEX slots in Phoenix LiveView. Since {nil} renders as whitespace rather than truly empty content, CSS :empty pseudo-class checks fail. An existing article's slot_empty? approach breaks when used with lists of slots that each render to whitespace individually but get concatenated. The post provides a macro, maybe_render_slot, that actually renders the slot content, uses a regex to check if the result is all whitespace, and returns nil if so, allowing conditional rendering with a placeholder sibling element via CSS :only-child selectors.
Questions this post answers
Why does an empty HEEX slot in Phoenix LiveView still fail a CSS :empty check?
An empty slot like <span>{nil}</span> renders as <span> </span> with whitespace rather than truly empty content, and the CSS :empty pseudo-class does not tolerate any whitespace at all. The experimental :blank pseudo-class would solve this but is not yet supported by any browser, so whitespace-only content still fails the :empty test. Developers debugging LiveView rendering quirks can find workarounds like this one on daily.dev.
Why does the slot_empty? helper report a non-empty slot when using a list of slots in Phoenix LiveView?
The slot_empty? approach breaks down when called with a slot from a list of slots because rendering each individually blank slot and checking them in sequence causes the function to report both as not empty even though each renders to nothing but whitespace. This happens specifically with multiple <:item></:item> entries passed to a component. Comparing slot-handling approaches for Phoenix components is easier when tracking real-world edge cases on daily.dev.
How can I conditionally render a Phoenix LiveView slot only if it contains non-whitespace content?
Define a macro that renders the slot via Phoenix.Component.__render_slot__, converts it to iodata with Phoenix.HTML.Safe.to_iodata, and runs a regex check for all-whitespace content using Erlang's :re.run. If the result is blank, return nil so the slot is skipped; otherwise wrap it in Phoenix.HTML.raw for use in the template alongside a placeholder sibling. Elixir developers solving LiveView template quirks can track practical fixes like this on daily.dev.