Search code examples
javascriptcssreactjsstyled-components

React component layout: how to make child component to spread and take space evenly?


I have a dropdown-select component, which lists each option as a row. Each row is a <User> component consisting of 3 child components: <Avatar>, <Username>, and <Quota>.

I want these 3 component to layout such that:

  1. Avatar is on the left most of the row, and Username is immediately next to Avatar;
  2. Quota is a string of varying length; it extends to the right end of the row, such that the last letter / digit should be just touching the right end.
<User
    key={user.id}
    isSelectValue={isSelectValue}
    withBottomMargin={false}
    onClick={() => {}}
  >
    <Avatar avatarUrl={user.avatarUrl} name={user.name} size={24} />
    <Username>{user.name}</Username>
    <Quota>{`${user.used}/${user.quota}`}</Quota>
  </User>

For the parent <User> component and child <Username> / <Quota> components, they are defined as:

export const User = styled.div`
  display: flex;
  align-items: center;
  ${mixin.clickable}
  ${props =>
    props.isSelectValue &&
    css`
      margin: 0 10px ${props.withBottomMargin ? 5 : 0}px 0;
      padding: 4px 8px;
      border-radius: 4px;
      background: ${color.backgroundLight};
      transition: background 0.1s;
      &:hover {
        background: ${color.backgroundMedium};
      }
    `}
`;

export const Username = styled.div`
  display: flex;
  padding: 0 3px 0 8px;
  ${font.size(14.5)}
`;

export const Quota = styled.div`
  display: flex;
  padding: 0 3px 0 120px;
  ${font.size(14.5)}    
`;

However, currently the position of Quota is fixed by padding: 0 3px 0 120px;. If the string is too short, it will not spread out in the row / extend to the right end: enter image description here

And if the string is too long, it will not take enough space to the left, and it extends too far to the right, and destroy the whole layout: enter image description here

How can I make <Quota> flexible, such that it will take enough space and just extends to the right border depending on its string length?


Solution

  • You're already using a flex layout, so let it do its thing: instead of all the padding, just give the div in the middle flex-grow: 1;.

    That way the middle div will stretch to fill up all the space not needed by the other two divs. The div on the right will take up as much space as its content requires, and be pushed all the way to the right.

    Also, now delete align-items: center;.

    And you can use the gap property on the containing div to control the spaces between the three child divs.