Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

md error: long error messages overlap input fields #4580

Open
kiryl-kazlovich opened this issue May 16, 2017 · 39 comments
Open

md error: long error messages overlap input fields #4580

kiryl-kazlovich opened this issue May 16, 2017 · 39 comments
Labels
area: material/form-field area: material/input needs: discussion Further discussion with the team is needed before proceeding P4 A relatively minor issue that is not relevant to core functions

Comments

@kiryl-kazlovich
Copy link

kiryl-kazlovich commented May 16, 2017

Bug, feature request, or proposal:

Bug (or question about) displaying long error messages in md-error

What is the expected behavior?

The error message needs to be visible without overlapping with other input fields

What is the current behavior?

If there are multiple error messages or if a message is too long it is displayed on top of the next input field

What are the steps to reproduce?

The plunk displays an example of a long error message for Last name, which is required, overlapping Email input field and 'Save' button on blur event: http://plnkr.co/edit/LX2iSTxWPJOvNVl0pzy8

What is the use-case or motivation for changing an existing behavior?

Long error messages in input form need to be displayed correctly

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

+-- @angular/animations@4.1.2
+-- @angular/cli@1.0.3
+-- UNMET PEER DEPENDENCY @angular/common@4.1.2
+-- @angular/compiler@4.1.2
+-- @angular/compiler-cli@4.1.2
| +-- @angular/tsc-wrapped@4.1.2
+-- UNMET PEER DEPENDENCY @angular/core@4.1.2
+-- @angular/flex-layout@2.0.0-beta.8
+-- @angular/forms@4.1.2
+-- @angular/http@4.1.2
+-- @angular/material@2.0.0-beta.5
+-- @angular/platform-browser@4.1.2
+-- @angular/platform-browser-dynamic@4.1.2
+-- @angular/router@4.1.2
| +-- @angular/core@2.4.10

| +-- typescript@2.2.2
| `-- typescript@1.8.10
+-- typescript@2.3.2

@kiryl-kazlovich kiryl-kazlovich changed the title Error messages overlap intput fields Long error messages overlap input fields May 16, 2017
@donroyco
Copy link
Contributor

As stated in the Material Guidelines:

An error message should appear on a single line, if possible.

So it should be as short as possible.

@kiryl-kazlovich
Copy link
Author

"An error message should appear on a single line, if possible."
What if in business case scenario it is not possible?

@kiryl-kazlovich kiryl-kazlovich changed the title Long error messages overlap input fields md error: long error messages overlap input fields May 16, 2017
@donroyco
Copy link
Contributor

They are positioned absolute, so I don't think it will know where the next input field is.

@kiryl-kazlovich
Copy link
Author

kiryl-kazlovich commented May 16, 2017

Exactly, it looks like I will need to build some workarounds. Would be nice to have the error stretched, otherwise md error seems to be not stable enough considering overlapping.

@jelbourn jelbourn added discussion P4 A relatively minor issue that is not relevant to core functions labels Jun 7, 2017
@AhHa45
Copy link

AhHa45 commented Sep 27, 2017

a short input field (like zipcode) would almost always have a hint message thats too long,
do you really think that this issue should be closed?
A workaround is given, however it's not a solution?

@axmad22
Copy link

axmad22 commented Oct 18, 2017

What happened with this BUG, I have an input with multiple mat-errors and they are overlapping the rest of the form. is it cause of this Absolutely-Positioned Flex Children .
"An error message should appear on a single line", what type of input has one single error message `

@xumepadismal
Copy link

This behavior also applies to "Helper text" of form field (<mat-hint>). And MD guidelines mentions the possibility of multiline:

On a single line if possible, or with text wrapping (if multiple lines)

@xumepadismal
Copy link

And here is my workaround for now (in my styles.scss):

// Workaround for https://github.com/angular/material2/issues/4580.
mat-form-field .mat-form-field {
  &-underline {
    position: relative;
    bottom: auto;
  }
  &-subscript-wrapper {
    position: static;
  }
}

@yoonjesung
Copy link

It should be noted that this issue is not only for mat-error labels but for mat-hint labels as well.

@intellix
Copy link

intellix commented Feb 15, 2018

perhaps an option to disable inlining errors? The normal behaviour is fine when you've got something like: This field is required but when you've got a long error message then you're screwed

@juan837
Copy link

juan837 commented Apr 3, 2018

Thanks @xumepadismal faster solution

@philmerrell
Copy link

I definitely agree with the sentiment that error messages and hint messages "should appear on a single line, if possible". That being said it's not always possible. Especially on mobile.

Thanks to @xumepadismal for the css.

@morriq
Copy link

morriq commented Apr 6, 2018

Well basicly error message is defined by browser in js validation api.

So I don't understand why material shouldn't support validationMessage from browser, saying that error messages should appear on a single line if possible?

In most cases it won't.
Simple validationMessage in type"email" in polish has 70 letters.

@blyndcide
Copy link

For 6.0.0 I needed to change @xumepadismal workaround to:

mat-form-field .mat-form-field {
  &-underline {
    position: static;
  }
  &-subscript-wrapper {
    position: static;
  }
}

If there are problems let me know.

@TetonRaven
Copy link

I love how the response to so many Material issues seems to be "you're doing it wrong". Frankly, I'm really starting to regret having committed to using Material, since it's so narrowly implemented for a very biased way of being used and developers seem to be very dismissive of other views. This is flat out a bug. What if you have multiple validators on a field, and the input triggers more than one? The validations messages will absolutely occupy more than one line, because mat-error will make it so. Hence, ugly overlap is pretty much certain, especially in mobile.

@Enngage
Copy link

Enngage commented Jul 8, 2018

Is there any reason the solution from @blyndcide / @xumepadismal could not be merged? I'm using it with mat-hints and errors with success. This is very common problem because hints/errors on mobile almost always take more then a single line... Using different hints/errors depending on screen size is
unrealistic.

@djtahl
Copy link

djtahl commented Oct 31, 2018

Any update on this issue ?

@Hydhen
Copy link

Hydhen commented Nov 20, 2018

For 6.0.0 I needed to change @xumepadismal workaround to:

mat-form-field .mat-form-field {
  &-underline {
    position: static;
  }
  &-subscript-wrapper {
    position: static;
  }
}

If there are problems let me know.

Could you explain me how to use it ?

Just copied it in my css file but doesn't not seems to work for me

@pascalbe-dev
Copy link

pascalbe-dev commented Nov 22, 2018

@Hydhen
Did you paste it to a scss file?

For me, the workaround also did not work. I got it working with the following css:

::ng-deep .mat-form-field-subscript-wrapper {
position: static;
}
::ng-deep .mat-form-field-underline {
position: static;
}

@cport1
Copy link

cport1 commented Dec 6, 2018

For 6.0.0 I needed to change @xumepadismal workaround to:

mat-form-field .mat-form-field {
  &-underline {
    position: static;
  }
  &-subscript-wrapper {
    position: static;
  }
}

If there are problems let me know.

Could you explain me how to use it ?

Just copied it in my css file but doesn't not seems to work for me

You need to nest it in your theme

and in your app.module.ts make sure you have something like :::

export class AppModule {
  // apply custom material theme across the entire application
  constructor(overlayContainer: OverlayContainer) {
    overlayContainer.getContainerElement()
      .classList.add('your-theme-class');
  }
}

@kamleshwebtech
Copy link

mat-form-field .mat-form-field {
  &-underline {
    position: relative;
    bottom: auto;
  }
  &-subscript-wrapper {
    position: static;
  }
}

screenshot 2019-01-09 at 1 41 15 am
I have added your shared css styles, but still does not work.

@jimmmeh
Copy link

jimmmeh commented Apr 16, 2019

Unless I am missing something, here, no one is mentioning the reason the error fields are marked as absolute in the first place and why changing them to static is not an ideal solution.

By default, the form fields have a padding applied to the bottom of them, enough space for the absolute positioned error message to appear in when there is an error. If you change this to static then you introduce arguably a worse problem - whenever an error message appears, any form item underneath the one with an error will suddenly jump down the screen a little because the field with an error now needs more vertical space. With the existing padding + absolute positioning this is not an issue as the form item will always take up a constant amount of vertical space whether an error is shown or not.

To my eyes, having fields jumping around when errors appears/disappear is much worse from a UX perspective than worrying about multi-line errors wrapping. You can always increase the default vertical spacing between form elements such that if multiple lines are required, there is space for them to fit into.

@dJani97
Copy link

dJani97 commented Apr 22, 2019

I had the same problem even with a single line of error message, so I created the below solution, which animates in a 13px margin in case a field is touched and invalid.
If you come up with an idea to scale it based on the number of error lines, make sure to notify me.
The 13px margin comes from a measurement I made in chrome dev-tools, it's identical to the error's height.

add this to styles.css:

/* Additional placeholder for invalid mat-form-fields */
/* src: https://github.com/angular/material2/issues/4580 /*

mat-form-field.ng-invalid.ng-touched {
  animation: example;
  animation-duration: 0.3s;
  margin-bottom: 13px;
}

@keyframes example {
  from {margin-bottom: 0;}
  to {margin-bottom: 13px;}
}

@joagr
Copy link

joagr commented Jun 17, 2019

component.css:

#myOuterDiv ::ng-deep mat-hint {
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
}

In my case, the form-field is a record's code, and the mat-hint is being used to show the descriptive text from the database record for the input code. For us, the record's descriptive text might be too long to fit, but that doesn't matter because the first bit (whatever fits) is enough.

@xumepadismal
Copy link

I agree with these @jimmmeh arguments:

By default, the form fields have a padding applied to the bottom of them, enough space for the absolute positioned error message to appear in when there is an error. If you change this to static then you introduce arguably a worse problem - whenever an error message appears, any form item underneath the one with an error will suddenly jump down the screen a little because the field with an error now needs more vertical space. With the existing padding + absolute positioning this is not an issue as the form item will always take up a constant amount of vertical space whether an error is shown or not.

But as I mentioned earlier, even Material Specs allows multiline subscripts if needed. I believe the best approach would be to have min-height reserved for one line of subscript content. Thereby we won't have that "jumping" for short errors/hint while won't overlap them with sibling components. And yes, form fields WILL jump for long errors which is not-so-bad from my point of view. What do you think guys?

I modified my workaround and share it on Stackblitz (see styles.scss):
https://stackblitz.com/edit/angular-vyvbsj

@MaximBalaganskiy
Copy link
Contributor

MaximBalaganskiy commented Jul 11, 2019

@xumepadismal solution works great, I would only remove bottom padding in case the control is valid or not touched. This way most of the times elements would not jump

mat-form-field {
  &.ng-valid {
    .mat-form-field-wrapper {
      padding-bottom: 1.25em;
    }
  }

  &.ng-invalid,
  &.mat-form-field-invalid {
    .mat-form-field-wrapper {
      padding-bottom: 7px;
    }
  }

  &.ng-untouched {
    .mat-form-field-wrapper {
      padding-bottom: 1.25em;
    }
  }

  .mat-form-field {
    &-underline {
      position: static;
    }

    &-subscript-wrapper {
      position: static;
    }
  }
}

@lucassantosTI
Copy link

@xumepadismal solution works great, I would only remove bottom padding in case the control is valid or not touched. This way most of the times elements would not jump

mat-form-field {
  &.ng-valid {
    .mat-form-field-wrapper {
      padding-bottom: 1.25em;
    }
  }

  &.ng-invalid,
  &.mat-form-field-invalid {
    .mat-form-field-wrapper {
      padding-bottom: 7px;
    }
  }

  &.ng-untouched {
    .mat-form-field-wrapper {
      padding-bottom: 1.25em;
    }
  }

  .mat-form-field {
    &-underline {
      position: static;
    }

    &-subscript-wrapper {
      position: static;
    }
  }
}

This works for me!

@erdemmalliq
Copy link

erdemmalliq commented Nov 13, 2019

Edited @dJani97's solution little bit:

mat-form-field.ng-invalid.ng-touched {
  animation: bigger;
  animation-duration: 0.3s;
  margin-bottom: 17px;
}

@keyframes bigger {
  from {margin-bottom: 0;}
  to {margin-bottom: 17px;}
}

mat-form-field.ng-valid.ng-touched {
  animation: smaller;
  animation-duration: 0.3s;
  margin-bottom: 0px;
}

@keyframes smaller {
  from {margin-bottom: 17px;}
  to {margin-bottom: 0;}
}

@mmalerba mmalerba added needs: discussion Further discussion with the team is needed before proceeding and removed discussion labels Mar 3, 2020
@richardsengers
Copy link

Ith the latest material this works for me

mat-form-field {

    .mat-form-field {
      &-underline {
        position: static;
      }

      &-wrapper {
        padding-bottom: 0;
      }

      &-subscript-wrapper {
        position: static;
        min-height: 1.25em;
      }
    }
  }

Are there any reasons to not use it like this?

@amatisme
Copy link

amatisme commented Feb 4, 2021

I had some good results when changing the position attribute to relative on the CSS. It has to be within the ':root' declaration. I put mine in a media query for mobile.

@media screen and (max-width: 515px) { :root { .mat-form-field-subscript-wrapper { position: relative; } } }

@Saad-Abbasi
Copy link

For me, this z-index worked by adding in style.scss

.mat-form-field-subscript-wrapper {
    z-index: 100; 
  }

@ijakparov
Copy link

.mat-form-field-wrapper {
    display: flex;
    flex-direction: column;

    .mat-form-field-flex {
        order: 1;
    }
    .mat-form-field-underline {
        position: relative;
        order: 2;
        bottom: 0 !important;
    }
    .mat-form-field-subscript-wrapper {
        position: relative;
        order: 3;
    }
}

@loqusion
Copy link

loqusion commented Sep 9, 2022

For reference, MUI does not have this issue since it doesn't absolutely position the error message, which breaks the flow of the document. I'm not sure why something similar can't be implemented here. Expecting the user to apply custom layout logic to material components is not an adequate solution.

@menuka-s
Copy link

menuka-s commented Feb 8, 2023

In Material 15 I believe this is solved in the MDC version of the form fields.

You can add subscriptSizing="dynamic" to a <mat-form-field>.

You can also make that the default behavior by updating your angular.module.ts providers with the option.

@NicolaiKilian
Copy link

NicolaiKilian commented Mar 31, 2023

In Material 15 I believe this is solved in the MDC version of the form fields.

You can add subscriptSizing="dynamic" to a <mat-form-field>.

You can also make that the default behavior by updating your angular.module.ts providers with the option.

And this is how to do that:

import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
...
providers: [
...
{
    provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
    useValue: {
      subscriptSizing: 'dynamic'
   }
}

@ChrTall
Copy link

ChrTall commented Apr 13, 2023

Adding subscriptSizing="dynamic" does not solve the issue for me.

@ValentinoFilipetto
Copy link

Adding subscriptSizing="dynamic" does add some margin but in my case not enough as it creates this awkward effect:

Screenshot 2023-08-09 at 12 07 44

So for the time being I am sticking to @dJani97's solution.

@micobarac
Copy link

micobarac commented Jan 10, 2024

Setting subscriptSizing: 'dynamic' caused the form fields layout to be messed totally, stretching height along with error messages appearances.

Using the solution proposed by @xumepadismal caused error messages to be pushed too much to the bottom, leaving unnecessary empty space at the top.

With Tailwind CSS, this solution worked for me with the latest Angular 17:

.mat-mdc-form-field {
  @apply w-full self-start;

  .mat-mdc-form-field-subscript-wrapper {
    @apply flex;

    .mat-mdc-form-field-error-wrapper {
      @apply static;
    }
  }
}

@BeniFreitag
Copy link

subscriptSizing="dynamic" leads to missing bottom-margin in Angular 17.0.9 (similar as reported by @ValentinoFilipetto):
image

This CSS fixed it for my case:

.mat-mdc-form-field-subscript-dynamic-size .mat-mdc-form-field-hint {
  margin-bottom: 22px;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/form-field area: material/input needs: discussion Further discussion with the team is needed before proceeding P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

No branches or pull requests