skip to Main Content

I have a container which can contain several buttons (feasibly up to 3).

I have used flexbox to make my desired layout. In this layout, all buttons are rendered in a line and space-evenly is used to give space between each item. E.g:

.wrapper {
  display: flex;
  justify-content: space-evenly;
  
  width: 500px;
  background-color: grey;
}

button {
  height: 75px;
}
<div class="wrapper">
  <div id="portalContainer">
    <button>Button 1</button>
  </div>
  <button>Button 2</button>
</div>

Due to how my HTML is set up, one of the buttons is wrapped in a div. This div is always rendered even when it does not have content (a button) to go inside it. The reason for this is because this div is the target for a React portal.

In a situation where I do not wish to render Button 1 I still require the wrapping div portalContainer to exist. I cannot get around this.

The issue therefore arises where the portalContainer has no content (no button was rendered into it) but Button 2 renders off to the side. This is due to flexbox still attempting to space the elements evenly, even when one element has nothing inside it. Example:

.wrapper {
  display: flex;
  justify-content: space-evenly;
  
  width: 500px;
  background-color: grey;
}

button {
  height: 75px;
}
<div class="wrapper">
  <div id="portalContainer"></div>
  <button>Button 2</button>
</div>

How can I make the solo instance of Button 2 show in the centre of the wrapper, even though portalContainer is still in the DOM?

I looked into the possibility of setting portalContainer as display: none; and then using something like :has(button) to unset that style when the container has a button inside. However :has() does not have Firefox support.

Is there a way of doing this? I cannot apply any logic to rendering the portalContainer – it must always be there.

Full example here in Codepen: https://codepen.io/asos-francesca/pen/qBQKPOX

2

Answers


  1. You can use the :empty pseudo-selector instead, which has greater browser support:

    https://caniuse.com/?search=%3Aempty

    .wrapper {
      display: flex;
      justify-content: space-evenly;
      width: 500px;
      background-color: grey;
    }
    
    button {
      height: 75px;
    }
    
    #portalContainer:empty {
      display: none;
    }
    <div class="wrapper">
      <div id="portalContainer"></div>
      <button>Button 2</button>
    </div>
    Login or Signup to reply.
  2. You can use Javascript to set the display:none to portalContainer only if the conainer doesn’t have any childrens.
    The next code snippet resolved the problem on CodePen.

    <script>
      document.querySelectorAll("#portalContainer").forEach((element) => { if (!element.hasChildNodes()) element.style.display = "none" })
    </script>
    

    Keep in mind that id’s must be unique in html!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search