Ke1sy
Ke1sy

Reputation: 29

How to align the inputs with multiline error in bottom-aligned form?

I have a form with the bottom-aligned behaviour, I need all the inputs in a row to be aligned to the bottom and be on one line visually. The reason for this is that the label can include instructions or not include them. The controls can be of different hight and type (text input, select, radio group, checkbox group, fieldset). The form that is used is antd Form component that is build using flex, that's why the markup of input's and label's wrappers cannot be changed. Also the each ant class have it's own styles:

I use the align-self: end;to make the control div to be aligned to the bottom. It works fine when I have one-line error But it doesn't look good when I have multi-line error.

Can anyone suggest how to align the controls properly using the CSS (maybe grid...)?

The desired result (the right input is located one the same line as the left one):

enter image description here

Thank you!

https://codepen.io/Ke1sy/pen/gOELweY

HTML:

<div class="container">
  <div class="ant-form ant-form-vertical ant-form-align-fields-bottom">
    <div class="ant-row">
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">
              <div>Label </div>
              <div style="color: grey">Long instructionsLong instructionsLong instructionsLong </div>
            </div>
            <div class="ant-col ant-form-item-control">
              <div class="input"><input type="text"></div>
              <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong error</div>
            </div>
          </div>
        </div>
      </div>
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">Label</div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Short instructions</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

The styles that are applied over the antd styles:

body {
  margin: 0;
}
.container {
  max-width: 900px;
}

.error {
  color: red;
  padding: 5px 0;
}

.ant-form-item {
  border: 5px solid rgb(111, 41, 97);
}

.ant-form-item-label {
  background: orange;
  width: 100%;
}

.ant-form-item-control {
  background: #eee;
  padding: 10px;
  width: 100%;
}

.ant-form-align-fields-bottom {
  .ant-form-item {
    height: 100%;
    .ant-form-item-row {
      height: 100%;
      display: grid;
      .ant-form-item-control {
        align-self: end;
      }
    }
  }
}

Antd css file to include: https://cdnjs.cloudflare.com/ajax/libs/antd/4.24.15/antd.compact.min.css

Upvotes: 2

Views: 466

Answers (5)

puffleeck
puffleeck

Reputation: 121

maybe try a tooltip for :hover?

changes marked with comments. as always :3


UPD 18.01.2024

body {
  margin: 0;
}

.container {
  max-width: 900px;
}

/* changes start */
.ant-form{
display:grid;
grid-template-columns: 1fr 1fr;
}
.ant-form-item-control{position: relative;}
.input{margin-bottom: 2.3em;}
.error {
  color: red;
  padding: 3px 0;
  position: absolute;
  bottom: 0;
  height: 1.1em;
  background: #eee;
  overflow: hidden;
  border: 3px double red;
  border-radius: .5em .5em 0 0;
  border-bottom: none;
}
.error:hover {
  height: auto;
}
/* changes end */

.ant-form-item {
  border: 5px solid #6f2961;
}

.ant-form-item-label {
  background: orange;
  width: 100%;
}

.ant-form-item-control {
  background: #eee;
  padding: 10px;
  width: 100%;
}

.ant-form-align-fields-bottom .ant-form-item {
  height: 100%;
}

.ant-form-align-fields-bottom .ant-form-item .ant-form-item-row {
  height: 100%;
  display: grid;
}

.ant-form-align-fields-bottom .ant-form-item .ant-form-item-row .ant-form-item-control {
  align-self: end;
}
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/antd/4.24.15/antd.compact.min.css'>
<div class="container">
  <div class="ant-form ant-form-vertical ant-form-align-fields-bottom">
    <div class="ant-row">
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">
              <div>Label </div>
              <div style="color: grey">Long instructionsLong instructionsLong instructionsLong </div>
            </div>
            <div class="ant-col ant-form-item-control">
              <div class="input"><input type="text"></div>
              <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong error</div>
            </div>
          </div>
        </div>
      </div>
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">Label</div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Short instructions</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

imhvost
imhvost

Reputation: 9815

Based on your html, you can apply .form-item { grid-template-rows:subgrid; }. Here is a simple example:

body {
  margin: 0;
}

.form {
  display: grid;
  grid-template-columns: repeat(auto-fit, 300px);
}

.error {
  color: red;
  padding: 5px 0
}

.form-item {
  border: 5px solid rgb(111, 41, 97);
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 2;
}

.label {
  background: orange;
}

.control {
  background: #eee;
  padding: 10px;
}
<form class="form">
  <div class="form-item">
    <div class="label">
      <div>Label </div>
      <div style="color: grey">Long instructionsLong instructionsLong instructionsLong instructions Long instructions Long instructionsLong instructionsLong instructionsLong instructions Long instruction </div>
    </div>
    <div class="control">
      <div class="input"><input type="text"></div>
      <div class="error">Long error Long error Long errorLong errorLong </div>
    </div>
  </div>
  <div class="form-item">
    <div class="label">Label</div>
    <div class="control">
      <div class="input"><input type="text"></div>
      <div class="error">Short error</div>
    </div>
  </div>
  <div class="form-item">
    <div class="label">Label</div>
    <div class="control">
      <div class="input"><input type="text"></div>
      <div class="error">errorLong errorLong errorLong errorLong error Long error Long errorLong errorLong errorLong errorLong errorLong er</div>
    </div>
  </div>
</form>


Using your provided html code:

body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.ant-form>.ant-row{
  display: grid;
  grid-template-columns:1fr 1fr;
}

.error {
  color: red;
  padding: 5px 0
}

.ant-form>.ant-row>.ant-col{
  border: 5px solid rgb(111, 41, 97);
  display: grid;
  grid-template-rows:subgrid;
  grid-row:span 2;
  width:auto;
  max-width:unset;
}

.ant-form>.ant-row>.ant-col>.ant-form-item,
.ant-form>.ant-row>.ant-col>.ant-form-item>.ant-form-item-row{
    display: grid;
    grid-template-rows:subgrid;
    grid-row:span 2;
}

.ant-form>.ant-row>.ant-col>.ant-form-item{
    margin:0;
}

.ant-form>.ant-row .ant-form-item-label {
  background: orange;
  padding: 10px;
}

.control {
  background: #eee;
  padding: 10px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.24.15/antd.compact.min.css">
<div class="container">
  <div class="ant-form ant-form-vertical ant-form-align-fields-bottom">
    <div class="ant-row">
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">
              <div>Label </div>
              <div style="color: grey">Long instructionsLong instructionsLong instructionsLong </div>
            </div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong error</div>
            </div>
          </div>
        </div>
      </div>
      <div class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-lg-8">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">Label</div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Short instructions</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


You don't mention in your question that you have no control over the grid markup. Just understand that there is either css grid or javascript. So if this form, let's say, comes with a backend, then you probably know exactly which columns are all defined. If you can set this in a variable for grid-template-columns and add variable styles similar to the .ant-col style.

And, yes, it will be a difficult decision, and maybe even a crazy one...

body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.ant-form>.ant-row{
  display: grid;
}

@media (min-width: 992px) {
  .ant-form>.ant-row{
    --lg-8:33%;
    --lg-6:25%;
  }
}

@media (min-width: 768px) {
  .ant-form>.ant-row{
    --md-8:33%;
    --md-6:25%;
  }
}

@media (min-width: 576px) {
  .ant-form>.ant-row{
    --sm-6:50%;
    --sm-6:50%;
  }
}

.error {
  color: red;
  padding: 5px 0
}

.ant-form>.ant-row>.ant-col{
  border: 5px solid rgb(111, 41, 97);
  display: grid;
  grid-template-rows:subgrid;
  grid-row:span 2;
  width:auto;
  max-width:unset;
}

.ant-form>.ant-row>.ant-col>.ant-form-item,
.ant-form>.ant-row>.ant-col>.ant-form-item>.ant-form-item-row{
    display: grid;
    grid-template-rows:subgrid;
    grid-row:span 2;
}

.ant-form>.ant-row>.ant-col>.ant-form-item{
    margin:0;
}

.ant-form>.ant-row .ant-form-item-label {
  background: orange;
  padding: 10px;
}

.control {
  background: #eee;
  padding: 10px;
  min-width: 0;
}

.ant-form input{
  max-width: 100%;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.24.15/antd.compact.min.css">
<div class="container">
  <div class="ant-form ant-form-vertical ant-form-align-fields-bottom">
    <div class="ant-row" style="grid-template-columns:var(--lg-8, var(--md-8, var(--sm-6))) var(--lg-6, var(--md-6, var(--sm-6)));">
      <div class="ant-col ant-col-lg-8 ant-col-md-8 ant-col-sm-6">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">
              <div>Label </div>
              <div style="color: grey">Long instructionsLong instructionsLong instructionsLong Long instructionsLong instructionsLong instructionsLong Long instructionsLong instructionsLong instructionsLong Long instructionsLong instructionsLong instructionsLong Long instructionsLong instructionsLong instructionsLong</div>
            </div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong error Long error Long error Long errorLong errorLong errorLong errorLong errorLong error Long error Long error Long errorLong errorLong errorLong errorLong errorLong error </div>
            </div>
          </div>
        </div>
      </div>
      <div class="ant-col ant-col-lg-6 ant-col-md-6 ant-col-sm-6">
        <div class="ant-form-item ant-form-item-with-help">
          <div class="ant-row ant-form-item-row">
            <div class="ant-col ant-form-item-label">Label</div>
            <div class="ant-col ant-form-item-control control">
              <div class="input"><input type="text"></div>
              <div class="error">Short instructions</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 1

realPro
realPro

Reputation: 1846

 
body {
  margin: 0;
}

.container {
  max-width: 900px;
  width: 500px;
}

.ant-row-tbl {
  display: grid;
   grid-template-columns: repeat(auto-fill, 1fr); /* Creates a flexible number of columns */
  grid-template-rows: auto auto; /* Creates two rows, auto-sized */
  column-gap: 6px; /* Vertical gap between columns */
  row-gap: 0;  /* no gap between rows */
}

/* Assuming .ant-col is a shared class for label and control */
.ant-col {
  /* Styling for both label and control */
  padding: 10px; /* Adjust padding as needed */
  box-sizing: border-box; /* Padding included in the width */
  
}

.ant-form-item-label {
  background: orange;
  grid-row: 1; /* Place label in the first row */
}

.ant-form-item-control {
  background: #eee;
  grid-row: 2; /* Place control in the second row */
}

/* Assuming .ant-col is a shared class for label and control */

.ant-col {
  /* Styling for both label and control */
  padding: 10px;
  /* Adjust padding as needed */
  box-sizing: border-box;
  /* Padding included in the width */
}

.ant-form-item-label {
  background: orange;
  grid-row: 1;
  /* Place label in the first row */
}

.ant-form-item-control {
  background: #eee;
  grid-row: 2;
  /* Place control in the second row */
}
   <div class="container">
  <div class="ant-form ant-form-vertical ant-form-align-fields-bottom">
<div class="ant-row-tbl">
  <div class="ant-col ant-form-item-label">
    <div>Label </div>
    <div style="color: grey">Long instructionsLong instructionsLong<br /><br />instructionsLong </div>
  </div>
  <div class="ant-col ant-form-item-control">
    <div class="input"><input type="text"></div>
    <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong error</div>
  </div>
  <div class="ant-col ant-form-item-label">
    <div>Label</div>
  </div>
  <div class="ant-col ant-form-item-control">
    <div class="input"><input type="text"></div>
    <div class="error">Short instructions</div>
  </div>
 <div class="ant-col ant-form-item-label">
    <div>Label3</div>
  </div>
  <div class="ant-col ant-form-item-control">
    <div class="input"><input type="text"></div>
    <div class="error">Short rrrr</div>
  </div>
</div>
  </div>
</div>

Upvotes: 0

sawacrow
sawacrow

Reputation: 321

you could use that site for grid helper: for more https://cssgrid-generator.netlify.app/

    
    body {
        padding: 50px;
        font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
    }

    .form {
        display: grid;
    grid-template-columns: repeat(2, 1fr);
    /* for more https://cssgrid-generator.netlify.app/ */
    grid-column-gap: 0px;
    grid-row-gap: 0px;
    }
    @media only screen and (max-width: 600px) {
        .form {
    grid-template-columns: repeat(1, 1fr);
        }
    }

    .error {
        color: red;
        padding: 5px 0
    }

    .form-item {
        border: 5px solid rgb(111, 41, 97);
        display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: repeat(2, 1fr);
    grid-column-gap: 0px;
    grid-row-gap: 0px;
    
    }

    .label {
        background: orange;
    }

    .control {
        background: #eee;
        padding: 10px;
    
    }
    <form class="form ">
        <div class="form-item">
        <div class="label">
            <div>Label </div>
            <div style="color: grey">Long instructionsLong instructionsLong instructionsLong instructions Long instructions Long instructionsLong instructionsLong instructionsLong instructions Long instruction </div>
        </div>
        <div class="control">
            <div class="input"><input type="text"></div>
            <div class="error">Long error Long error Long errorLong errorLong errorLong errorLong errorLong errorLong error Long error Long errorLong errorLong errorLong errorLong errorLong er</div>
        </div>
        </div>
        <div class="form-item">
        <div class="label">Label</div>
        <div class="control">
            <div class="input"><input type="text"></div>
            <div class="error">Short error</div>
        </div>
        </div>
        
    </form>

alternative solution are:

  1. you can give line-clamp for texts.
  2. for text div: height:100px; overflow-y:auto;

Upvotes: 0

JB17
JB17

Reputation: 459

Depending on the rest of your layout or other requirements you could use css-grid in order to get your desired layout.

If you remove the divs around each input and label, you could just use a grid, which flows in the column direction. The height of the rows will be defined by the largest item and therefore affect the other control-divs as well.

.form {
  display: grid;
  grid-template-rows: repeat(2, 1fr);
  grid-auto-flow: column;
}

.error {
  color: red;
  padding: 5px 0;
}

.label {
  background: orange;
}

.control {
  background: #eee;
  padding: 10px;
}
 <form class="form">
    <div class="label">
      <div>Label</div>
      <div style="color: grey">
            Long instructionsLong instructionsLong instructionsLong instructions
            Long instructions Long instructionsLong instructionsLong
            instructionsLong instructions Long instruction sjhdjsdhdjshdsj
            hsdjhsdssdhj jshdsjhjsh hjsdhdjsdhjshjdhjdshdjssdhjdhsjdshjsdd
            jhjshdhjdsdhjsdhj
      </div>
    </div>
    <div class="control">
      <div class="input"><input type="text" /></div>
      <div class="error">
            Long error Long error Long errorLong errorLong errorLong errorLong
            errorLong errorLong error Long error Long errorLong errorLong
            jhsdhsjdhsjdh
      </div>
    </div>
    <div class="label">Label</div>
    <div class="control">
      <div class="input"><input type="text" /></div>
      <div class="error">Short error</div>
    </div>
 </form>

Upvotes: 0

Related Questions