Matt93
Matt93

Reputation: 13

Element moves after transforming

I would like to have a span within the .btn rotate 180 deg when I click the .btn. However, the span also moved to the right and went down after it was rotated. Could anyone help me explain why it moved like that. I tried to transform: translate(-21px, 1px) after rotation then the span will moved the right place but I believe there will be another better way to fix it. I also tried transform-origin: 50% 50% but it doesn't work either.

$('.btn').on('click', function(){
  $(this).toggleClass('open');
})
@import "https://fonts.googleapis.com/css?family=Raleway";
body {
  background-color: #ddd;
  font-family: "Raleway", "Microsoft JhengHei", Arial, sans-serif;
  color: #7a7b7c;
}

.btn {
  width: 80px;
  height: 80px;
  background-color: #6F7272;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 2rem #babbbc;
  position: absolute;
}
.btn span {
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before, .btn::after {
  content: "";
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before {
  margin-top: -7px;
}
.btn::after {
  margin-top: 7px;
}

.open {
  transition: 0.3s ease-in-out;
  background-color: #6F7272;
}
.open span {
  transition: .3s ease-in-out;
  transform: rotate(180deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn">
  <span></span>
</div>

Upvotes: 1

Views: 178

Answers (4)

Deepak Yadav
Deepak Yadav

Reputation: 7109

Your approach isn't working as expected, because after click event, you are transforming the X & Y values of your span using translate property and then rotating it. This causes it to shift it's location when transformed.

You used position: absolute to place your span in middle. this can be also be achieved via other CSS properties like display: table or display :flex

Check out the below suggestion - most of the code is all yours with just slight change.

$('.btn').on('click', function() {
  $(this).toggleClass('open');
})
@import "https://fonts.googleapis.com/css?family=Raleway";
body {
  background-color: #ddd;
  font-family: "Raleway", "Microsoft JhengHei", Arial, sans-serif;
  color: #7a7b7c;
}

.btn {
  width: 80px;
  height: 80px;
  background-color: #6F7272;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 2rem #babbbc;
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
}

.btn span {
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  /*  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute; */
}

.btn::before,
.btn::after {
  content: "";
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}

.btn::before {
  margin-top: -7px;
}

.btn::after {
  margin-top: 7px;
}

.open {
  transition: 0.3s ease-in-out;
  background-color: #6F7272;
}

.open span {
  transition: .3s ease-in-out;
  transform: rotate(180deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn">
  <span></span>
</div>

Upvotes: 0

Tushar
Tushar

Reputation: 4418

If you remove transform: translate(-50%, -50%); and just keep left:26% and top: 49% It works fine.

To your question why it is happening. Because you have moved it using left and top position and again you are trying to neutralise it by translate. which is moving the center of animation to different position.

$('.btn').on('click', function(){
  $(this).toggleClass('open');
})
@import "https://fonts.googleapis.com/css?family=Raleway";
body {
  background-color: #ddd;
  font-family: "Raleway", "Microsoft JhengHei", Arial, sans-serif;
  color: #7a7b7c;
}

.btn {
  width: 80px;
  height: 80px;
  background-color: #6F7272;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 2rem #babbbc;
  position: absolute;
}
.btn span {
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 49%;
  left: 26%;
//  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before, .btn::after {
  content: "";
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before {
  margin-top: -7px;
}
.btn::after {
  margin-top: 7px;
}

.open {
  transition: 0.3s ease-in-out;
  background-color: #6F7272;
}
.open span {
  transition: .3s ease-in-out;
  transform: rotate(180deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn">
  <span></span>
</div>

Upvotes: 2

Abin Thaha
Abin Thaha

Reputation: 4633

Check if this is what you are trying to achieve.

Here, I have added a single line to the css transform-origin: 10px;. Everything else is the same. The change in JS is to remove the add class as soon as the animation carried out. Otherwise, you will need to click double times on the button to see the animation again.

$('.btn').on('click', function(){
  $(this).addClass('open');
  setTimeout(function() {
    $('.btn').removeClass('open');
  }, 300);
})
body {
  background-color: #ddd;
  font-family: "Raleway", "Microsoft JhengHei", Arial, sans-serif;
  color: #7a7b7c;
}

.btn {
  width: 80px;
  height: 80px;
  background-color: #6F7272;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 2rem #babbbc;
  position: absolute;
}
.btn span {
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before, .btn::after {
  content: "";
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before {
  margin-top: -7px;
}
.btn::after {
  margin-top: 7px;
}

.open {
  transition: 0.3s ease-in-out;
  background-color: #6F7272;
}
.open span {
  transition: .3s ease-in-out;
  transform: rotate(180deg);
  transform-origin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn">
  <span></span>
</div>

Upvotes: 0

Nandita Sharma
Nandita Sharma

Reputation: 13417

Update this style

.open span {
    transition: .3s ease-in-out;
    transform: rotate(180deg) translate(20px, 1px );
}

$('.btn').on('click', function(){
  $(this).toggleClass('open');
})
@import "https://fonts.googleapis.com/css?family=Raleway";
body {
  background-color: #ddd;
  font-family: "Raleway", "Microsoft JhengHei", Arial, sans-serif;
  color: #7a7b7c;
}

.btn {
  width: 80px;
  height: 80px;
  background-color: #6F7272;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 2rem #babbbc;
  position: absolute;
}
.btn span {
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before, .btn::after {
  content: "";
  width: 40px;
  height: 2px;
  background-color: #ffffff;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}
.btn::before {
  margin-top: -7px;
}
.btn::after {
  margin-top: 7px;
}

.open {
  transition: 0.3s ease-in-out;
  background-color: #6F7272;
}
.open span {
  transition: .3s ease-in-out;
  transform: rotate(180deg) translate(20px, 1px );
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn">
  <span></span>
</div>

Upvotes: 0

Related Questions