0
\$\begingroup\$

I have an outer div with...

  1. Width
  2. Number of slots the outer div represents

The intent is to add a child div, but position the child div based on the start and end slot in the parent div.

To achieve this behavior, I am calculating the width per slot and the width of child div, plus the margin left of child div.

import React from 'react';

let parentDivStyle = {
    border: '1px solid black',
    height: '50px',
    align: 'center',
    display: 'inline-block'
}

let childDivStyle = {
    backgroundColor: 'darkseagreen',
    marginTop: '5px',
    height: '40px',
}

const DivColoring = (props) => {
    let parentDivWith = props.parentDivWidth;
    let totalSlots = props.totalSlots;
    let startSlot = props.startSlot;
    let endSlot = props.endSlot;

    let widthPerSlot = Math.round(parentDivWith / totalSlots);

    console.log('widthPerSlot= ', widthPerSlot);
    let childWidth = parentDivWith;

    let marginLeft = 0;

    //if startSlot is greater than 1, calculate the Left Margin and Width.
    if (startSlot > 1) {
        marginLeft = (startSlot - 1) * widthPerSlot;
    }

    //if end is present and is less than totalSlots update childWidth

    if (endSlot && endSlot <= totalSlots) {
        childWidth = widthPerSlot * (endSlot - startSlot + 1);
    }


    //add 1 px to marginLeft of child div
    marginLeft = marginLeft + 1;
    //remove 2 px from childWidth to add a padding of 1px at end
    childWidth = childWidth - 2;

    return (<div style={{ ...parentDivStyle, width: parentDivWith + 'px', }}>
        <div style={{
            ...childDivStyle, marginLeft: marginLeft
            , width: childWidth + 'px'
        }}></div>
    </div>);
}

export default DivColoring;

Please see the working example here https://stackblitz.com/edit/react-be8wxg

Is there any better of achieving this behavior. Thanks.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

There are 2 more ways to do this using css without the calculation. They are:

  • css positioning

    Make the position of parent relative and child absolute. Now, using the slots value, left and right properties can be easily calculated for child div which will place it properly. The entire logic is reduces to the following without adding any additional elements:
const DivColoring = props => {
  let parentDivWidth = props.parentDivWidth;
  let totalSlots = props.totalSlots;
  let startSlot = props.startSlot;
  let endSlot = props.endSlot;
  return (
    <div style={{ ...parentDivStyle, width: parentDivWidth + "px" }}>
      <div
        style={{
          ...childDivStyle,
          position: "absolute",
          left: `${((startSlot - 1) * 100) / totalSlots}%`,
          right: `${((totalSlots - endSlot) * 100) / totalSlots}%`
        }}
      />
    </div>
  );
};

The entire code can be found here: https://stackblitz.com/edit/react-qj3xsp

  • css flex

    The DivColoring component can contain 3 child divs instead of one and you can use flex property to define relative width of the divs. The relative width can be easily calculated using totalSlots, startSlot and endSlot. The basic logic can be written as:
const DivColoring = props => {
  let totalSlots = props.totalSlots;
  let startSlot = props.startSlot;
  let endSlot = props.endSlot;
  let div3 = totalSlots - endSlot;
  let div2 = endSlot - startSlot + 1;
  let div1 = startSlot - 1;
  return (
    <div style={{ ...parentDivStyle, width: props.parentDivWidth + "px" }}>
      <div id="" style={{ flex: div1 }} />
      <div id="" style={{ ...childDivStyle, flex: div2 }} />
      <div id="" style={{ flex: div3 }} />
    </div>
  );
};

The complete code can be found here: https://stackblitz.com/edit/react-4mgl4c.
You also need to apply some extra css. Pros are calculation is reduced but con is that DOM will become heavy. Instead of 1, now there are 3 divs for each block.

The recommended approach will be using css positioning.

Hope it helps. Revert for any doubts/clarifications.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks Sunil. I understand the cons in the second approach. Certainly do not want to introduce additional divs making the DOM heavy. \$\endgroup\$
    – DKG
    May 14, 2020 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.