Is it possible to remove an inline element without the elements next to it changing their position?

Issue

I have 5 inline squares under a flex parent. When the button is clicked, the first square is removed. Each time the first square is removed, the squares that follow get pushed back to the left by one square’s width (as would be expected). Is it possible to make the other squares maintain their position when this happens (i.e. they stay where they previously were instead of moving to the left)?

One way I can think of to do that is by absolutely positioning each square element. But is that the only way to prevent the squares from moving?

Note: I would like the squares to maintain their positions if I were to remove the last square as well; so something like justify-content: flex-end will not work for my needs because it won’t work for both cases.

Note 2: visibility: hidden or opacity: 0 will also not work for my needs because I do need to actually remove the square element. I also plan to append another square element later and wouldn’t want the layout to shift. Is this possible?

Please see the fiddle for an example.

$('.click-me').on('click', function() {
  // Remove the first square.
  $('.main').children().first().remove();
});
.main {
  position: relative;
  display: flex;
  margin-top: 20px;
}
.main span {
  width: 35px;
  height: 35px;
  background-color: #2e852e;
  border: 1px solid #000;
}
.main .square1,
.main .square5 {
  background-color: #a5a551;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="click-me">Click Me!</button>
<div class="main">
  <span class="square1"></span>
  <span class="square2"></span>
  <span class="square3"></span>
  <span class="square4"></span>
  <span class="square5"></span>
</div>

Solution

UPDATED: You can use grid approach and combine it with using CSS variables.
Set inline style CSS variable with index of square element and then use it in CSS, to have position of this squares in main grid. In this case you can remove any of the child elements and all other will keep their positions.

$('.click-me').on('click', function() {
  // Remove the first square.
  $('.main').children().first().remove();
});
.main {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 35px); /* create grid with 5 columns */
  margin-top: 20px;
}

.square {
  /* make it flex and align it's content */
  display: flex;
  align-items: center;
  justify-content: center;
  /* make it square flexible element */
  width: 100%;
  aspect-ratio: 1/1;
  background-color: #2e852e;
  border: 1px solid #000;
  color: #fff;
  /* using index of element, taken from inline styles, "auto" - callback */
  grid-column-start: var(--sq-index, auto);
}

.square--active {
  background-color: #a5a551;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="click-me">Click Me!</button>
<div class="main">
  <span class="square square--active" style="--sq-index: 1;">1</span>
  <span class="square" style="--sq-index: 2;">2</span>
  <span class="square" style="--sq-index: 3;">3</span>
  <span class="square" style="--sq-index: 4;">4</span>
  <span class="square square--active" style="--sq-index: 5;">5</span>
</div>

<div class="main">
  <span class="square" style="--sq-index: 2;">2</span>
  <span class="square" style="--sq-index: 4;">4</span>
  <span class="square square--active" style="--sq-index: 5;">5</span>
</div>

<!-- 
  Example of using "auto" callback.
  Defined index of first child element, 
  all next siblings will be placed automatically
-->
<div class="main">
  <span class="square" style="--sq-index: 3;">3</span>
  <span class="square">4</span>
  <span class="square square--active">5</span>
</div>

Answered By – Yaroslav Trach

Answer Checked By – Dawn Plyler (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.