Search code examples
htmlcsscss-gridgrid-layout

Push element in the opposite direction if space is available


I'm writing a form with CSS Grid Layout and trying to align inputs at same level. Fields will have label for name and error, and each field could have none, one or both.

Currently, I have this:

form error css grid layout

Want it like this:

form desired style css grid layout

So if there is space available up or down the element should be pushed in opposite direction in order to keep fields aligned always.

This is CSS for form tag:

grid-template-columns: repeat(2, 1fr);
    grid-column-gap: 16px;

    & > :nth-child(3),
    & > :nth-child(4),
    & > :nth-child(7) {
        grid-column-start: 1;
        grid-column-end: 3;
    }

    & > * {
        overflow: hidden;
    }

Thanks!

Edit:

Here the basic composition of the HTML (using React so I'm putting just the important tags):

form {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-column-gap: 16px;
}

form > :nth-child(3),
form > :nth-child(4),
form > :nth-child(7) {
  grid-column-start: 1;
  grid-column-end: 3;
}

& > * {
    overflow: hidden;
}

.content {
  display: flex;
  flex-direction: column;
}

.label {
  margin-bottom: 4px;
}

.error {
  margin-top: 4px;
}
<form>
    <div class="content"> <!-- Each form's child is a div which contains labels and input -->
        <span class="label">Label</span> <!-- Span rendered only if exists -->
        <input />
        <!-- Span not rendered when there is no value -->
    </div>
    <div class="content"> <!-- Each form's child is a div which contains labels and input -->
      <!-- Span not rendered if no label value exists -->
      <input />
      <span class="error">Error</span> <!-- Span rendered if exists -->
  </div>
</form>


Solution

  • How about having fixed height for span (label or error) unless it can be multiple lines

    form {
      grid-template-columns: repeat(2, 1fr);
      grid-gap: 16px;
      display: grid;
    }
    
    form > :nth-child(3),
    form > :nth-child(4),
    form > :nth-child(7) {
      grid-column-start: 1;
      grid-column-end: 3;
    }
    
    form > * {
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }
    
    form > div > span {
      height: 20px;
    }
    <form>
    <div> <!-- Each form's child is a div which contains labels and input -->
        <span>Label</span> <!-- Label if exists -->
        <input />
        <span></span> <!-- Error if exists -->
    </div>
    <div> <!-- Each form's child is a div which contains labels and input -->
        <span></span> <!-- Label if exists -->
        <input />
        <span>Error</span> <!-- Error if exists -->
    </div>
    <div> <!-- Each form's child is a div which contains labels and input -->
        <span>Label</span> <!-- Label if exists -->
        <input />
        <span></span> <!-- Error if exists -->
    </div>
    <div> <!-- Each form's child is a div which contains labels and input -->
        <span>Label</span> <!-- Label if exists -->
        <input />
        <span></span> <!-- Error if exists -->
    </div>
    </form>