DEV Community

Cover image for how to make dynamic element center horizontally in react js?
Jackson Kasi
Jackson Kasi Subscriber

Posted on

how to make dynamic element center horizontally in react js?

Hello Devs

I need one help! i am not a master in css. so i did something for my case. but this does not help full. here i try to explain my problem.

any one can help?

Live Code Demo

import "./styles.css";
import React, { useRef, useState, useEffect } from "react";
import styles from "styled-components";

const DotsWrapper = styles.div`
  display: flex;
  justify-content: center;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
`;

const Dot = styles.div`
  width: 50px;
  height: 50px;
  text-align: center;
  padding: 2rem;
  border-radius: 50%;
  background-color: ${({ isActive }) => (isActive ? "#fc916a" : "#436073")};
  transition: transform 0.3s, background-color 0.3s;
  transform: ${({ isActive, index, activeIndex, centerIndex }) => {
    const distanceFromCenter = index - centerIndex;
    const distanceFromActive = index - activeIndex;
    if (isActive) {
      return "scale(1.3)";
    } else if (distanceFromActive === 1) {
      return "translateX(25px)";
    } else if (distanceFromActive === -1) {
      return "translateX(-25px)";
    } else if (distanceFromCenter > 0) {
      return "translateX(50px)";
    } else if (distanceFromCenter < 0) {
      return "translateX(-50px)";
    } else {
      return "scale(1)";
    }
  }};
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 20px;
  margin: 0 10px;
`;

const CenterDot = styles(Dot)`
  transform: scale(1.3);
`;

export default function App() {
  const mobileContent = {
    page_blocks: [
      { info_date: "01-01-2002" },
      { info_date: "01-01-2003" },
      { info_date: "01-01-2004" },
      { info_date: "01-01-2005" },
      { info_date: "01-01-2006" },
      { info_date: "01-01-2007" }
    ]
  };

  const [activeIndex, setActiveIndex] = React.useState(0);
  const activeDot = React.useRef(null);

  const centerIndex = Math.floor(mobileContent.page_blocks.length / 2);
  const windowWidth = window.innerWidth;
  const centerPosition = windowWidth / 2;
  const [activePosition, setActivePosition] = React.useState(0);

  React.useEffect(() => {
    const activeDotPosition = activeDot.current.getBoundingClientRect();
    const activePosition =
      activeDotPosition.x + activeDotPosition.width / 2 - centerPosition;
    setActivePosition(activePosition);
  }, [windowWidth]);

  const result = centerPosition - activePosition;
  const translateX = result > 0 ? `${result}px` : `-${Math.abs(result)}px`;

  return (
    <React.Fragment>
      <div
        className="line"
        style={{
          position: "relative",
          width: "100%",
          overflowX: "hidden",
          height: "350px"
        }}
      >
        <br />
        <br />
        <br />
        windowWidth = {windowWidth}
        <br />
        centerPosition = {centerPosition}
        <br />
        activePosition = {activePosition}
        <br />
        result= {result}
        <br />
        {translateX}
        <br />
        <DotsWrapper style={{ transform: `translateX(${translateX})` }}>
          {mobileContent.page_blocks.map((item, index) =>
            index === activeIndex ? (
              <CenterDot
                key={index}
                isActive
                index={index}
                centerIndex={centerIndex}
                activeIndex={activeIndex}
                ref={activeDot}
              >
                {new Date(item.info_date).getFullYear()}
              </CenterDot>
            ) : (
              <Dot
                key={index}
                isActive={index === activeIndex}
                index={index}
                centerIndex={centerIndex}
                activeIndex={activeIndex}
                onClick={() => setActiveIndex(index)}
              >
                {new Date(item.info_date).getFullYear()}
              </Dot>
            )
          )}
        </DotsWrapper>
      </div>
    </React.Fragment>
  );
}


Enter fullscreen mode Exit fullscreen mode

this pic out put of code

the active circle needs to be always the center of windows horizontally.
and the remaining circles need to be auto align based on the active circle.

how to do this? i hope u will understand. anyone can please help me?

i try to explain here.

in this code above, the active dot circle will be in the center.
so what u need to do is,
current

1) get the total width of widows.
2) get the center of the total width position.
3) get the current position of active dot.

ex diagram.

|-------------------|-------------------|
1000px ( total width )

----active-dot-------------------------
250px

so,

we need to measure. how much space or px u need to move active dot for making it center?

(total width ) - ( center position ) - (active dot position )
ex 1:
result = 1000px - 500px - 500px = 250px

ex 2:
result = 1000px - 500px - 800px = -350px

so now
(active dot position ) + ( result )
ex 1:
250px + 250px = 500px
ex 2:
800px + ( - 300px ) = 500px

so using this calculation make an active dot position center ( use css translateX or any other )

and other not active dots will auto align

Image of AssemblyAI tool

Challenge Submission: SpeechCraft - AI-Powered Speech Analysis for Better Communication

SpeechCraft is an advanced real-time speech analytics platform that transforms spoken words into actionable insights. Using cutting-edge AI technology from AssemblyAI, it provides instant transcription while analyzing multiple dimensions of speech performance.

Read full post

Top comments (4)

Collapse
 
longtngo profile image
Long Ngo

Would this work for you? code sandbox

It still has the problem of not staying in the middle when the window resizes.

Collapse
 
jacksonkasi profile image
Jackson Kasi

wow! thanks, man/bro 🙏

how did u fix that. ok i explore the code.

Collapse
 
longtngo profile image
Long Ngo • Edited

You had the right idea of using translate to push the DotContainer using middle calculation. But the main problem was that you are fighting the justify-content: center; which already trying to move the content to center already. So by removing it, the content Dots display locations are deterministic, always show up at 0px from left, and each dot has a size of 114px, and the gap between each dot is 10.

From there, you can calculate how far you want to push the container toward the middle of the screen. The farthest you want to push is window.innerWith / 2. As you increase the activeIndex, since it need to be in the middle, you need to reduce the translation value by its width and its gap 114 * activeIndex.

You should also need to account the bigger width of the active item 114 * 1.3. Hence the final calculation look like this:

const middleX = window.innerWidth / 2 - 114 * activeIndex - 114 * 1.3;

It probably not exact at the dead center of the screen. You might want to fine tune the calc a little bit. But the basic is that.

Hope this help.

Thread Thread
 
jacksonkasi profile image
Jackson Kasi

ohh! i got it thanks!

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️