Rotate Child Element Around The Parent Element with Transition

Rotate child element around the parent element with transition

This orbiting like animation can be achieved by setting the smaller circle outside of the parent circle at start (using top, left) and then setting the transform-origin as parent's radius + smaller circle's radius. This is because the center of rotation should be at the center of the larger circle which is offset by the top-left of the smaller circle by the combined distance of their radii.

When we set the transform-origin as 0% 50%, the 50% is half of the smaller circle's height (which is 32.5px) and so the rotation diameter and so the rotation happens around a smaller imaginary circle. Whereas what we actually need is for it to animate around the larger circle and so imaginary's circles radius has to be higher.

.center-circle {  position: relative;  top: 100px;  left: 100px;  width: 180px;  height: 180px;  border: 1px solid black;  border-radius: 100%;}.quarter-circle {  position: absolute;  width: 65px;  height: 65px;  top: -32.5px;  left: -32.5px;  border: 1px solid #F28B46;  border-radius: 100%;  transform: rotate(-45deg);  animation: spin-back 2s ease-in-out forwards;  transform-origin: 122.5px 122.5px;}@keyframes spin-back {  0% {    transform: rotate(-45deg);  }  100% {    transform: rotate(135deg);  }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script><div class="center-circle">  <div class="quarter-circle"></div></div>

Rotate a child element while clicking its parent

Here's my solution

I added an animated class so that the element with make the rotation animation slowly in 0.5sec

.animated {
-moz-transition: transform 0.5s;
-webkit-transition: transform 0.5s;
transition: transform 0.5s;
}

and then i made a script to handle the rotation of each arrow line

$(document).ready(function() {
var leftdegplus = -45;
var leftdegminus = 45;
var rightdegplus = 45;
var rightdegminus = -45;
$(".left").click(function() {
leftdegplus = leftdegplus + 180;
$(this).find("#left-top").css("transform", "rotate(" + leftdegplus + "deg)");

leftdegminus = leftdegminus - 180;
$(this).find("#left-bottom").css("transform", "rotate(" + leftdegminus + "deg)");

});
$(".right").click(function() {

rightdegplus = rightdegplus - 180;
$(this).find("#right-top").css("transform", "rotate(" + rightdegplus + "deg)");

rightdegminus = rightdegminus + 180;
$(this).find("#right-bottom").css("transform", "rotate(" + rightdegminus + "deg)");
});

});

This is the full code snippet:

$(document).ready(function() {  var leftdegplus = -45;  var leftdegminus = 45;  var rightdegplus = 45;  var rightdegminus = -45;  $(".left").click(function() {    leftdegplus = leftdegplus + 180;    $(this).find("#left-top").css("transform", "rotate(" + leftdegplus + "deg)");
leftdegminus = leftdegminus - 180; $(this).find("#left-bottom").css("transform", "rotate(" + leftdegminus + "deg)");
}); $(".right").click(function() {
rightdegplus = rightdegplus - 180; $(this).find("#right-top").css("transform", "rotate(" + rightdegplus + "deg)");
rightdegminus = rightdegminus + 180; $(this).find("#right-bottom").css("transform", "rotate(" + rightdegminus + "deg)"); });

});
.button-back {  width: 50px;  height: 50px;  background-color: #fff;  border-radius: 100%;  position: absolute;  display: flex;  flex-direction: column;  justify-content: center;  transition: background-color 0.3s;  cursor: pointer;}
.button-back:hover { background-color: #2da6ff;}
.left { left: 5%;}
.right { right: 5%;}
#left-top { margin-bottom: 3px; width: 15px; height: 3px; position: relative; transform: rotate(-45deg); left: 30%; background: #e2e2e2; z-index: 3;}
#left-bottom { margin-top: 3px; width: 15px; height: 3px; position: relative; transform: rotate(45deg); left: 30%; background: #e2e2e2; z-index: 3;}
#right-top { margin-bottom: 3px; width: 15px; height: 3px; position: relative; transform: rotate(45deg); left: 40%; background: #e2e2e2;}
#right-bottom { margin-top: 3px; width: 15px; height: 3px; position: relative; transform: rotate(-45deg); left: 40%; background: #e2e2e2;}
.animated { -moz-transition: transform 0.5s; -webkit-transition: transform 0.5s; transition: transform 0.5s;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="button-back left">  <div class="animated " id="left-top"></div>  <div class="animated " id=left-bottom></div></div><div class="button-back right">  <div class="animated " id="right-top"></div>  <div class="animated " id="right-bottom"></div></div>

When child element is bigger than the parent, how to place the child centered above/below the parent element (plus rotate it)?

First we need to center some thing in the center of the parent. For that we use left: 50%; top: 50%; top: 50%. position: absolute; is needed as well.

This centers the top left corner of the text span rectangle at the parent's center.

Then we need to do the transformations including the rotation. Without rotation, we'd only need translate(-50%, 4px) for the bottom label and translate(-50%, -4px) translate(0, -100%); for the top label.
For proper rotation, we need to put it between translations. We can use transform-origin, which makes the transformation slightly easier to understand, or use transform only, which is more symmetric, but harder to understand.
Here is how to understand the transformations that do not use transform-origin: The default transform-origin is the object center (50% 50%), which is initially 50% to the right and 50% down from the parent's center. We need to first translate the element to the desired side of its original center (top/bottom/left/right), then rotate and then translate to from the element's original center to the parent's center (translate(-50%, -50%)).

Note that the angles are clockwise due to the Y axis pointing down.

We can develop very similar transforms for all sides - top, bottom, left and right.

.handle {
border: 1px solid black;
border-radius: 4px;
position: absolute;
width: 6px; /* width = 2*border-radius - 2*border-width */
height: 6px;
}

.label {
font-family: monospace;
opacity: 0.5;
background: red;
left: 50%;
top: 50%;
position: absolute;
display: block;
white-space: nowrap;
}

/* Variant with transform-origin */
.label_top1 {
transform-origin: 50% 0%;
transform: translate(-50%, 0px) rotate(-40deg) translate(0px, -4px) translate(0, -100%);
}

.label_bottom1 {
transform-origin: 50% 0%;
transform: translate(-50%, 0px) rotate(-40deg) translate(0, 4px);
}

/* Variant without transform-origin */
.label_top {
transform: translate(-50%, -50%) rotate(-40deg) translate(0px, -4px) translate(0, -50%);
}

.label_bottom {
transform: translate(-50%, -50%) rotate(-40deg) translate(0, 4px) translate(0, 50%);
}

.label_left {
transform: translate(-50%, -50%) rotate(-40deg) translate(-4px, 0) translate(-50%, 0);
}

.label_right {
transform: translate(-50%, -50%) rotate(-40deg) translate(4px, 0) translate(50%, 0);
}
<div class="handle" style="left: 50px; top: 100px">
<span class="label label_top">0|0</span>
</div>
<div class="handle" style="left: 50px; top: 100px">
<span class="label label_bottom">0|0</span>
</div>

<div class="handle" style="left: 120px; top: 100px">
<span class="label label_top">000|000</span>
</div>

<div class="handle" style="left: 120px; top: 100px">
<span class="label label_bottom">000|000</span>
</div>

<div class="handle" style="left: 250px; top: 100px">
<span class="label label_top">----top---|---top----</span>
</div>
<div class="handle" style="left: 250px; top: 100px">
<span class="label label_bottom">--bottom--|--bottom--</span>
</div>
<div class="handle" style="left: 250px; top: 100px">
<span class="label label_left">---left---|---left---</span>
</div>
<div class="handle" style="left: 250px; top: 100px">
<span class="label label_right">---right--|--right---</span>
</div>

How to dynamically fit a rotated element to the parent element with CSS?

You need to consider transform-origin and some translation too

body {  background-color: #333;}
.container { background-color: #000; position: absolute; height: 25vh; width: 25vw; margin: auto; top: 0; left: 0; right: 0; bottom: 0;}
.element { position: absolute; background-color: #abc; height: 25vw; width: 25vh; transform: translateY(-100%) rotate(90deg); transform-origin: bottom left;}
<div class="container">  <div class="element"></div></div>

CSS how to transition(with transform) a parent and child both, differently

In fact you have a wrong selector (which is .mommy:hover ~ .baby), so the animation for the .baby in fact does not run. Only the animation of the parent .daddy is run, it rotates and makes the inner child .baby also rotate. This effect made you think both animations run at the same time. Also because of this effect, I'm not sure what the exact effect you want. I've tried editing the code mainly to show that both animations can work right on the hovering:

/* This is what the selector should be */
.mommy:hover ~ .daddy > .baby {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-transition: .1s ease-in .9s;
transition: .1s ease-in .9s;
}

Demo.

Prevent children from inheriting rotate transformation in CSS

I believe that you are going to need to fake it using a second child, the specification does not seem to allow for the behavior you would like, and I can understand why the position of a child element has to be affected by a transform to its parent.

This isn't the most elegant of solutions, but I think you're trying to do something that the specification is never going to allow. Take a look at the following fiddle for my solution: