0

I want to make elements that are placed together explode out from each other by increasing the margin on each of them with a CSS animation. The problem I have is that they end up pushing against the left of the container instead of going outside it, and they end up getting stacked on top of each other. Is there any way to just make them expand outwards? You can see what I've done so far in this example.

function ct(tag, id, attrs) {
  var e = document.createElement(tag)
  if (typeof id == 'object') attrs=id
  if (typeof id == 'string') e.setAttribute('id', id)
  for (var a in attrs)
    if (attrs[a] !== undefined)
      e.setAttribute(a, attrs[a])
  return e
}

for (var i = 0; i < 3; i++) {
  $('#page').append(ct('div', {'class': 'row_'}))
  for (var y = 0; y < 3; y++) {
    $('.row_').eq(i).append(ct('div', {'class': 'abc'}))
  }
}

$('#start').click(function() {
  $('.abc').addClass('move')
})
#page {
  height: 160px;
  width: 200px;
  background: lightgrey;
  display: flex;
  flex-flow: column;
  justify-content: center;
}

.abc {
  margin: 1px;
  padding: 10px;
  background: black;
  width: 30px;
  display: inline-block;
}

.move {
  animation: move 0.6s cubic-bezier(1, 0, 1, 1);
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes move {
  from {
    margin: 1px;
  }
  to {
    margin: 10px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<body>
  <div id=page>
  </div>
  <button id=start>
    Start
  </button>
</body>

</html>
Rob Kwasowski
  • 2,690
  • 3
  • 13
  • 32

2 Answers2

2

Consider the row to be inline-flex element to fit the width of the content including the margin and since the default behavior is nowrap you will have the overflow you want. Then center everything horizontally like you did vertically:

function ct(tag, id, attrs) {
  var e = document.createElement(tag)
  if (typeof id == 'object') attrs=id
  if (typeof id == 'string') e.setAttribute('id', id)
  for (var a in attrs)
    if (attrs[a] !== undefined)
      e.setAttribute(a, attrs[a])
  return e
}

for (var i = 0; i < 3; i++) {
  $('#page').append(ct('div', {'class': 'row_'}))
  for (var y = 0; y < 3; y++) {
    $('.row_').eq(i).append(ct('div', {'class': 'abc'}))
  }
}

$('#start').click(function() {
  $('.abc').addClass('move')
})
#page {
  height: 160px;
  width: 200px;
  background: lightgrey;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items:center; /* added this */
}
.row_ {
 display:inline-flex; /* added this */
}
.abc {
  margin: 1px;
  padding: 10px;
  background: black;
  width: 30px;
  /*display: inline-block; no more needed*/
}

.move {
  animation: move 0.6s cubic-bezier(1, 0, 1, 1);
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes move {
  from {
    margin: 1px;
  }
  to {
    margin: 30px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<body>
  <div id=page>
  </div>
  <button id=start>
    Start
  </button>
</body>

</html>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • That's good, but the elements are now pushing against the top of the container. Can you make it so the black squares are just pushing evenly outwards? – Rob Kwasowski May 02 '19 at 15:07
  • @RobKwasowski what browser are you using? – Temani Afif May 02 '19 at 15:08
  • I'm using Chrome – Rob Kwasowski May 02 '19 at 15:09
  • @RobKwasowski I think I am not sure what you want exactly. can you do a small mockup of the before and after? – Temani Afif May 02 '19 at 15:10
  • If you look at this animated GIF you can see that in your example everything gets pushed downwards at the end. I want the squares to just move outwards from the centre. https://imgur.com/a/hya2qlE – Rob Kwasowski May 02 '19 at 15:18
  • @RobKwasowski it doesn't behave like the GIF for me .. you have this output if your run the snippet here? – Temani Afif May 02 '19 at 15:24
  • Yes, it's recorded from here. What browser are you on? – Rob Kwasowski May 02 '19 at 15:24
  • @RobKwasowski I am on Chrome and also tested with FF (windows) .. you are on MAC by any chance? – Temani Afif May 02 '19 at 15:26
  • No, I'm on Windows. I just ran your example on Firefox and you're right, it runs perfectly like how I want. That's strange that it's different for me on Chrome. – Rob Kwasowski May 02 '19 at 15:27
  • I just looked at this post https://stackoverflow.com/questions/52283106/why-do-chrome-and-firefox-show-different-flex-layout-results and it sounds like `align-items` may still be a draft. There may be a way to solve my problem in the answer to that post. – Rob Kwasowski May 02 '19 at 15:40
  • @RobKwasowski this is about align-content and not align-items .. and align-items has the same support as justify-content (I am on chrome and it's working fine for me) – Temani Afif May 02 '19 at 15:43
  • It may be to do with the version of Chrome. I'm not on the latest version of Chrome. – Rob Kwasowski May 02 '19 at 15:44
  • I might be able to fix the problem by updating but I don't want to update because then I'll have the annoying rounded tabs, and I want to make my website compatible for older versions of Chrome. – Rob Kwasowski May 02 '19 at 15:47
0

Temani Afif's answer works great on Firefox and the latest version of Chrome, but on older versions of Chrome flexbox doesn't work completely. So I discovered that you have to also animate min-height on the row containers for better compatibility.

function ct(tag, id, attrs) {
  var e = document.createElement(tag)
  if (typeof id == 'object') attrs=id
  if (typeof id == 'string') e.setAttribute('id', id)
  for (var a in attrs)
    if (attrs[a] !== undefined)
      e.setAttribute(a, attrs[a])
  return e
}

for (var i = 0; i < 3; i++) {
  $('#page').append(ct('div', {'class': 'row_'}))
  for (var y = 0; y < 3; y++) {
    $('.row_').eq(i).append(ct('div', {'class': 'abc'}))
  }
}

$('#start').click(function() {
  $('.abc').addClass('move')
  $('.row_').addClass('test')
})
#page {
  height: 160px;
  width: 200px;
  background: lightgrey;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center; /* added this */
}

.row_ {
 display: inline-flex; /* added this */
}

.abc {
  margin: 1px;
  padding: 10px;
  background: black;
  width: 30px;

  /* display: inline-block; no more needed */
}

.move {
  animation: mover 0.6s cubic-bezier(1, 0, 1, 1);
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes mover {
  from {
    margin: 1px;
  }

  to {
    margin: 40px;
  }
}

.test {
  animation: tester 0.6s cubic-bezier(1, 0, 1, 1);
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes tester {
  from {
    min-height: 22px;
  }

  to {
    min-height: 100px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<body>
  <div id=page>
  </div>
  <button id=start>
    Start
  </button>
</body>

</html>
Rob Kwasowski
  • 2,690
  • 3
  • 13
  • 32