Home > Enterprise >  Absolute positioning translate loop is positioning related to sibling, not relative position paren
Absolute positioning translate loop is positioning related to sibling, not relative position paren

Time:12-18

I'm attempting to position a series of circles (divs) along a circular path. I've been running into an issue where, it seems, absolutely-positioned siblings of the same class are being translated according to the position of their siblings. I'm sure it's something funny with the way I've structured the loop, but I'm at a loss as to how to achieve it.

The JS below has the plot-along-a-circle logic commented out, I'm just trying to get the outer-circle elements positioning absolutely on top of one another at the centerpoint of the containing-circle. But, as you can see in the Codepen (link below, before the code blocks), the outer-circles are being positioned in a diagonal line, each transform added to the previous.

https://codepen.io/AceaSpades/pen/bGKXZNo

<!-- HTML -->
<main class='container'>
  <section id='containing-circle' >
    <div class='center-circle' />
    <div id='circle-1' class='outer-circle' />
    <div id='circle-2' class='outer-circle' />
    <div id='circle-3' class='outer-circle' />
    <div id='circle-4' class='outer-circle' />
    <div id='circle-5' class='outer-circle' />
  </section>
</main>
/* CSS */
html,
body {
  background-color: black;
}

.container {
  height: 100%;
  width: 100%;
}

.containing-circle {
  width: 300px;
  height: 300px;
  margin: 40px auto;
  outline: 1px solid #fff;
  border-radius: 50%;
  position: relative;
}

.center-circle {
  top: 0;
  left: 0;
  position: absolute;
  background-color: hsl(0, 0%, 10%);
  width: 120px;
  height: 120px;
  border-radius: 100%;
  outline: 1px solid magenta;
}

.outer-circle {
  top: 0;
  left: 0;
  position: absolute;
  background-color: hsl(0, 0%, 10%);
  width: 80px;
  height: 80px;
  border-radius: 100%;
  outline: 1px solid pink;
}
// JS
const containingCircle = document.getElementById("containing-circle");
const radius = containingCircle.offsetWidth / 2;

const outerCircles = document.getElementsByClassName("outer-circle");
const width = containingCircle.offsetWidth,
  height = containingCircle.offsetHeight;

let angle = 0,
  step = 360 / outerCircles.length;

for (let i = 1; i <= outerCircles.length; i  ) {
  let circle = document.getElementById("circle-"   i);
  let x = width / 2 - circle.offsetWidth / 2;
  let y = height / 2 - circle.offsetHeight / 2;
  circle.style.translate = x   "px "   y   "px";
  circle.style.top = 0;
  // let x = (width / 2)   (Math.cos(angle) * radius);
  // let y = (height / 2)   (Math.sin(angle) * radius);
  // outerCircles[i].style.left = x   'px';
  // outerCircles[i].style.top = y   'px';
  // angle  = step;
}

CodePudding user response:

div is not a self-closing tag.

Solution :

<main class='container'>
  <section id='containing-circle' >
    <div class='center-circle'></div>
    <div id='circle-1' class='outer-circle'></div>
    <div id='circle-2' class='outer-circle'></div>
    <div id='circle-3' class='outer-circle'></div>
    <div id='circle-4' class='outer-circle'></div>
    <div id='circle-5' class='outer-circle'></div>
  </section>
</main>

In your code,
Every outer-circle are not actually siblings.
They are parents of their corresponding outer-circle

Hence this :

 <section>
   <div />
   <div />
 </section>

Is equivalent to (In the browser) :

<section>
   <div >
       <div ></div>
   </div>
 </section>

CodePudding user response:

this works. I left lot script with all the steps to be easily understandable and with console log.

const containingCircle = document.getElementById("containing-circle");

const outerCircles = document.getElementsByClassName("outer-circle");
const width = containingCircle.offsetWidth,
  height = containingCircle.offsetHeight;

const rect_cc = containingCircle.getBoundingClientRect();
console.log(rect_cc);
const radius_cc = rect_cc.width / 2; // or height, it's circle
const xCenter_cc = rect_cc.left   radius_cc;
const yCenter_cc = rect_cc.top   radius_cc;
console.log(xCenter_cc, yCenter_cc, radius_cc);

const offset_c = 80 / 2;

let angle = 360 / outerCircles.length;
let angle_cur = 0;


for (let i = 1; i <= outerCircles.length; i  ) {
  let circle = document.getElementById("circle-"   i);
  console.log(angle_cur);

  // Math.cos, sin need radians not degrees
  let rad = angle_cur * Math.PI / 180;

  let x = xCenter_cc   (radius_cc * Math.cos(rad));
  let y = yCenter_cc   (radius_cc * Math.sin(rad));
  console.log(x, y);

  circle.style.left = x - offset_c - rect_cc.left   'px';
  circle.style.top = y - offset_c - rect_cc.top   'px';
  console.log(circle.style.left, circle.style.top);

  angle_cur  = angle;
}
html,
body {
  background-color: black;
  margin: 0;
}

.container {
  height: 500px;
  width: 500px;
  margin: 20px;
  position: relative;
}

.containing-circle {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  height: 300px;
  border: 1px solid #fff;
  border-radius: 100%;
  z-index: 1;
}

.center-circle {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color: hsl(0, 0%, 10%);
  width: 120px;
  height: 120px;
  border-radius: 100%;
  border: 1px solid magenta;
  z-index: 1;
}

.outer-circle {
  top: 0;
  left: 0;
  position: absolute;
  background-color: hsl(0, 0%, 10%);
  width: 80px;
  height: 80px;
  border-radius: 50%;
  outline: 1px solid pink;
  z-index: 2;
}
<main class='container'>
  <section id='containing-circle' >
    <div class='center-circle'></div>
    <div id='circle-1' class='outer-circle'></div>
    <div id='circle-2' class='outer-circle'></div>
    <div id='circle-3' class='outer-circle'></div>
    <div id='circle-4' class='outer-circle'></div>
    <div id='circle-5' class='outer-circle'></div>
  </section>
</main>

  • Related