mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(input): Add pure-CSS floating label logic that will work on... (#8491)
* fix(input): Add pure-CSS floating label logic that will work on... ...server-side-rendered pages. * address comments
This commit is contained in:
@@ -90,6 +90,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Used to make instances of the _mat-form-field-placeholder-floating mixin negligibly different,
|
||||
// and prevent Google's CSS Optimizer from collapsing the declarations. This is needed because some
|
||||
// of the selectors contain pseudo-classes not recognized in all browsers. If a browser encounters
|
||||
// an unknown pseudo-class it will discard the entire rule set.
|
||||
$dedupe: 0;
|
||||
|
||||
// Applies a floating placeholder above the form field control itself.
|
||||
@mixin _mat-form-field-placeholder-floating($font-scale, $infix-padding, $infix-margin-top) {
|
||||
// We use perspective to fix the text blurriness as described here:
|
||||
@@ -97,25 +103,14 @@
|
||||
// This results in a small jitter after the label floats on Firefox, which the
|
||||
// translateZ fixes.
|
||||
transform: translateY(-$infix-margin-top - $infix-padding) scale($font-scale) perspective(100px)
|
||||
translateZ(0.001px);
|
||||
translateZ(0.001px + $dedupe);
|
||||
// The tricks above used to smooth out the animation on chrome and firefox actually make things
|
||||
// worse on IE, so we don't include them in the IE version.
|
||||
-ms-transform: translateY(-$infix-margin-top - $infix-padding) scale($font-scale);
|
||||
-ms-transform: translateY(-$infix-margin-top - $infix-padding + $dedupe) scale($font-scale);
|
||||
|
||||
width: 100% / $font-scale;
|
||||
}
|
||||
width: 100% / $font-scale + $dedupe;
|
||||
|
||||
// This is a total duplicate of the mixin above with insignificant values added to the rules.
|
||||
// This exists because the mixin is used in two places. When Google's CSS Optimizer runs over this
|
||||
// css (after compiling from sass), it combines those two declarations into one. However, one of
|
||||
// those places uses `:-webkit-autofill`. When Firefox encounters this unknown pseuedo-class,
|
||||
// it ignores the entire rule. To work around this, we force one of the delcarations to be
|
||||
// technically different but still render the same by adding a tiny value to the transform / width.
|
||||
@mixin _mat-form-field-placeholder-float-nodedupe($font-scale, $infix-padding, $infix-margin-top) {
|
||||
transform: translateY(-$infix-margin-top - $infix-padding) scale($font-scale) perspective(100px)
|
||||
translateZ(0.002px);
|
||||
-ms-transform: translateY(-$infix-margin-top - $infix-padding) scale($font-scale);
|
||||
width: (100% / $font-scale) + 0.0001;
|
||||
$dedupe: $dedupe + 0.00001 !global;
|
||||
}
|
||||
|
||||
@mixin mat-form-field-typography($config) {
|
||||
@@ -188,14 +183,23 @@
|
||||
}
|
||||
|
||||
.mat-form-field-can-float {
|
||||
&.mat-form-field-should-float .mat-form-field-placeholder {
|
||||
&.mat-form-field-should-float .mat-form-field-placeholder,
|
||||
.mat-input-server:focus + .mat-form-field-placeholder-wrapper .mat-form-field-placeholder {
|
||||
@include _mat-form-field-placeholder-floating(
|
||||
$subscript-font-scale, $infix-padding, $infix-margin-top);
|
||||
$subscript-font-scale, $infix-padding, $infix-margin-top);
|
||||
}
|
||||
|
||||
.mat-form-field-autofill-control:-webkit-autofill + .mat-form-field-placeholder-wrapper
|
||||
.mat-form-field-placeholder {
|
||||
@include _mat-form-field-placeholder-float-nodedupe(
|
||||
@include _mat-form-field-placeholder-floating(
|
||||
$subscript-font-scale, $infix-padding, $infix-margin-top);
|
||||
}
|
||||
|
||||
// Server-side rendered matInput with a placeholder attribute but placeholder not shown
|
||||
// (used as a pure CSS stand-in for mat-form-field-should-float).
|
||||
.mat-input-server[placeholder]:not(:placeholder-shown) + .mat-form-field-placeholder-wrapper
|
||||
.mat-form-field-placeholder {
|
||||
@include _mat-form-field-placeholder-floating(
|
||||
$subscript-font-scale, $infix-padding, $infix-margin-top);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,18 @@ $mat-form-field-default-infix-width: 180px !default;
|
||||
}
|
||||
}
|
||||
|
||||
// Server-side rendered matInput with focus or a placeholder attribute but placeholder not shown
|
||||
// (used as a pure CSS stand-in for mat-form-field-should-float).
|
||||
.mat-input-server:focus + .mat-form-field-placeholder-wrapper .mat-form-field-placeholder,
|
||||
.mat-input-server[placeholder]:not(:placeholder-shown) + .mat-form-field-placeholder-wrapper
|
||||
.mat-form-field-placeholder {
|
||||
display: none;
|
||||
|
||||
.mat-form-field-can-float & {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the placeholder animation when the control is not empty (this prevents placeholder
|
||||
// animating up when the value is set programmatically).
|
||||
.mat-form-field-placeholder:not(.mat-form-field-empty) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import {Subject} from 'rxjs/Subject';
|
||||
import {getMatInputUnsupportedTypeError} from './input-errors';
|
||||
import {MAT_INPUT_VALUE_ACCESSOR} from './input-value-accessor';
|
||||
|
||||
|
||||
// Invalid input type. Using one of these will throw an MatInputUnsupportedTypeError.
|
||||
const MAT_INPUT_INVALID_TYPES = [
|
||||
'button',
|
||||
@@ -49,6 +50,7 @@ let nextUniqueId = 0;
|
||||
exportAs: 'matInput',
|
||||
host: {
|
||||
'class': 'mat-input-element mat-form-field-autofill-control',
|
||||
'[class.mat-input-server]': '_isServer',
|
||||
// Native input properties that are overwritten by Angular inputs need to be synced with
|
||||
// the native input element. Otherwise property bindings for those don't work.
|
||||
'[attr.id]': 'id',
|
||||
@@ -85,6 +87,9 @@ export class MatInput implements MatFormFieldControl<any>, OnChanges, OnDestroy,
|
||||
/** The aria-describedby attribute on the input for improved a11y. */
|
||||
_ariaDescribedby: string;
|
||||
|
||||
/** Whether the component is being rendered on the server. */
|
||||
_isServer = false;
|
||||
|
||||
/**
|
||||
* Stream that emits whenever the state of the input changes such that the wrapping `MatFormField`
|
||||
* needs to run change detection.
|
||||
@@ -185,6 +190,8 @@ export class MatInput implements MatFormFieldControl<any>, OnChanges, OnDestroy,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._isServer = !this._platform.isBrowser;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
|
||||
@@ -103,6 +103,10 @@
|
||||
|
||||
<h2>Input</h2>
|
||||
|
||||
<mat-form-field floatPlaceholder="never">
|
||||
<input matInput placeholder="name">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<input type="number" matInput placeholder="amount">
|
||||
<span matPrefix>$ </span>
|
||||
|
||||
Reference in New Issue
Block a user