skip to content

CSS: Hiding content before and after an empty container

Sometimes our websites are designed with placeholders for dynamically generated content such as news articles. If there are no articles to display then the surrounding headings, icons and other elements may need to be removed as well.

This could be achieved by pre-querying the database, or by post-processing the DOM using JavaScript, but neither option is ideal.

Working Example

In this example we have a container (green) which may or may not contain some HTML content. When there is no content we can easily hide the following container by using a combination of the :empty and adjacent selectors:

There is nothing special about the HTML:

<div>... before ...</div> <div class="container">...</div> <div>... after ...</div>

The CSS code for this example is as follows:

<style> div.container:empty { display: none; } div.container:empty + div { opacity: 0.25; /* N.B. display: none; would be used in practice */ } </style>

Instead of the adjacent sibling combinator (+) we could also use the general sibling combinator (~) which would hide all following containers at the same DOM level - not just the first.

As you can see this works perfectly well for the content following the container, but does not address the preceding content.

Hiding content before an empty container

It is similarly possible to hide the content preceding our container by using some CSS trickery:

<div style="display: flex; flex-flow: column-reverse nowrap;"> <div>... after ...</div> <div class="container">...</div> <div>... before ...</div> </div>

By reversing the order of the content in the HTML, and then again for display on the page, we can cause the content preceding our container to be hidden. Only now the subsequent content is not hidden.

Hiding content before and after

As you may have guessed, the solution is to rearrange the HTML so that the container comes first, followed by both content blocks. We can do that by using the CSS Grid Layout as follows:

<div style="display: grid;"> <div class="container" style="grid-row: 2;">...</div> <div style="grid-row: 1;">... before ...</div> <div style="grid-row: 3;">... after ...</div> </div>

This other change is that we hve to use the general sibling (~) combinator:

<style> div.container:empty ~ div { display: none; } </style>

Together these changes have the desired effect:

As you can see, as long as the .container element is completely empty, the entire content section is removed (hidden) from the page, in this case leaving just an outline.

As an extension of this approach you could set up your entire page layout using grid and use the :empty selector on one element to affect how content is displayed in a completely different part of the page.


User Comments

Post your comment or question

3 March, 2023

Hi, thanks for your article, it is exactly what i was looking for. Except that the grid solution is not working at all. It seems that the ~ compinator use order as defined in DOM, not the order computed by css engine :/