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:
mmalerba
2017-11-28 10:28:22 -08:00
committed by tinayuangao
parent a6d08472c9
commit 1a7a61a3b0
4 changed files with 45 additions and 18 deletions
+22 -18
View File
@@ -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);
}
}
+12
View File
@@ -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) {
+7
View File
@@ -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>$&nbsp;</span>