Angular 6/7 css 媒体查询未应用于孙子
Angular 6/7 css media queries are not applied on grand-child
我在使用以下组件架构的应用程序上应用媒体查询(用于响应行为)时遇到一些问题
base components:使用默认封装,有使用外部插件的地方,目前我们正在申请,某些情况下,PrimeNG external模块。这个想法是将这些基本组件移动到其他应用程序。这些都集成在它自己的共享模块中。
品牌组件:它重用基本组件,应用自定义样式和翻译文本,做一些特定的事情,它使用原生封装(为了与基本组件),但它不应用业务逻辑。这些都集成在导入共享模块的自己的品牌模块中。
业务组件:它重用品牌组件并在此处应用自己的业务逻辑(在多个视图中使用时)。这些都集成在导入品牌模块的自己的业务模块中。这些组件实现了默认的 angular 封装模式。
然后 我们有视图,它们集成在自己的模块中并导入业务模块。它将使用品牌和/或业务组件,这里我们面临一些关于 css 媒体查询 的问题。这些视图使用默认的 angular 封装模式。
具体情况是我们尝试为特定视图自定义输入字段,以便在响应情况下正确运行(移动设备、平板电脑和台式机在不同的方向上)。为此,我们使用外部插件 angular flex layout (beta 7)
此输入字段存在于基本组件中,但我们将其用于品牌案例。我们想要的是更改其在品牌上设置的默认 width/height 以适应将封装它的 div 容器。
这是我们目前所做的:
特定视图的css:
// MEDIA QUERIES
:host ::ng-deep {
@media screen and (min-width: 300px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width: 95%;
}
}
@media screen and (min-width: 300px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.625);
}
}
@media screen and (min-width: 480px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.9);
}
}
@media screen and (min-width: 640px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2);
height:(16px * 1.6);
}
}
@media screen and (min-width: 640px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.68);
height:(16px * 1.6);
}
}
@media screen and (min-width: 768px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.3);
height:(16px * 1.6);
}
}
@media screen and (min-width: 768px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.5);
height:(16px * 1.6);
}
}
@media screen and (min-width: 900px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.5);
height:(16px * 1.625);
}
}
@media screen and (min-width: 900px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 1.875);
height:(16px * 1.625);
}
}
@media screen and (min-width: 1200px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.75);
height:(16px * 1.625);
}
}
@media screen and (min-width: 1200px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.5);
height:(16px * 1.625);
}
}
}
以前的自定义 类 存在并用于品牌化输入字段组件,以便根据不同情况更改其 UX。
品牌输入字段组件模板文件:
<sh-input-field [id]="id"
[caption]="caption | translate"
[(model)]="userInput"
[placeholder]="placeholder | translate"
[type]="inputType"
[color]="color"
[font-size]="fontsize"
[isDisabled]="!enabled"
[style]="{'width': width,
'height': height}"
[status]="status"
[baseClass]="INPUT_CLASS_ENABLED"
[extendedClass]="extendedClass"
[stateClasses]="{
focusedOn: INPUT_CLASS_EDITING,
enabledOn: INPUT_CLASS_ENABLED,
enabledOff: INPUT_CLASS_DISABLED,
valueChanged: INPUT_CLASS_CHANGED
}"
[passwordWeakCaption]="passwordWeakCaption"
[passwordMediumCaption]="passwordMediumCaption"
[passwordStrongCaption]="passwordStrongCaption"
[isPasswordFeedbackShown]="isPasswordFeedbackShown">
</sh-input-field>
品牌输入字段组件 scss 文件:
/* CAPTION */
.uiElemSideCaptionLeft,
.uiElemSideCaptionRight,
.uiElemSideCaptionDisabled {
position: relative;
display: inline-block;
padding-top: 2px;
text-align: left;
font-size: 14px;
-ms-opacity: 1;
opacity: 1;
color: #333;
}
.uiElemSideCaptionRight {
-ms-opacity: 1;
opacity: 1;
text-align: right;
}
.uiElemSideCaptionDisabled {
-ms-opacity: 0.4;
opacity: 0.4;
}
/* INPUT-FIELD */
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
position: relative;
display: inline-block;
height: 16px;
width: 80px;
padding: 4px;
background-color: #dddddd;
border-width: 1px;
border-color: #979797;
border-style: solid;
font-size: 14px;
text-align: left;
color: rgba(0, 0, 0, 1);
-ms-opacity: 1;
opacity: 1;
}
.inputFieldEditing {
-ms-opacity: 1;
opacity: 1;
background-color: #eee;
height: 14px;
border-width: 2px;
border-color: #F8E71C;
color: rgba(0, 0, 0, 1);
border-style: solid;
}
.inputFieldChanged {
-ms-opacity: 1;
opacity: 1;
background-color: rgba(245, 166, 35, 0.5);
height: 16px;
border-width: 1px;
border-color: #979797;
color: rgba(0, 0, 0, 1);
border-style: solid;
}
.inputFieldDisabled {
-ms-opacity: 0.6;
opacity: 0.6;
height: 16px;
background-color: lightgray;
border-width: 1px;
border-color: #979797;
border-style: solid;
color: rgba(0, 0, 0, 1);
}
品牌输入字段组件定义:
@Component({
selector: 'br-input-field',
templateUrl: './input-field.component.html',
styleUrls: ['./input-field.component.scss'],
encapsulation: ViewEncapsulation.Native
})
基本输入字段组件模板文件:
<div class="sh-input-field-global-container">
<div class="sh-input-field-label-container" *ngIf="caption !== '' && caption !== undefined && caption !== null">
<label [for]="id">{{caption}}</label>
</div>
<div class="sh-input-field-container" [ngClass]="extendedClass">
<input *ngIf="controlType !== 'password'"
[ngClass]="getCssClases('sh-input-field', baseClass)"
[attr.id]="id"
[placeholder]="placeholder"
[disabled]="isDisabled"
(focus)="InvokeFocus($event)"
(blur)="InvokeBlur($event)"
(keyup.enter)="InvokeKeyUpEnterEvent($event)"
(keyup.escape)="InvokeKeyUpEscapeEvent($event)"
[(ngModel)]="model"
[attr.name]="formName"
[maxLength]="length"
[type]="controlType"
[ngStyle]="style"/>
<input *ngIf="controlType === 'password'"
[ngClass]="GetCssClases('sh-input-field', baseClass)"
[attr.id]="id"
[disabled]="isDisabled"
(focus)="InvokeFocus($event)"
(blur)="InvokeBlur($event)"
(keyup.enter)="InvokeKeyUpEnterEvent($event)"
(keyup.escape)="InvokeKeyUpEscapeEvent($event)"
[(ngModel)]="model"
[attr.name]="formName"
[maxLength]="length"
[type]="controlType"
pPassword
[promptLabel]="placeholder"
[weakLabel]="passwordWeakCaption"
[mediumLabel]="passwordMediumCaption"
[strongLabel]="passwordStrongCaption"
[feedback]="isPasswordFeedbackShown"
[ngStyle]="style"/>
</div>
</div>
基本输入字段组件定义:
@Component({
selector: 'sh-input-field',
templateUrl: './input-field.component.html',
styleUrls: ['./input-field.component.scss']
})
那么这里可能出了什么问题? 我们是否在特定视图上错误地使用了 :host :ng-deep? 我们已经看到,如果我们将这些媒体查询直接应用于品牌输入字段 sass 文件,它工作正常(删除 :host :ng-deep 标签)
尝试 :host /deep/
而不是 :host ::ng-deep
,如下所示
:host /deep/ {
/*your style goes here*/
}
或
使用encapsulation: ViewEncapsulation.None
代替encapsulation: ViewEncapsulation.Native
But, I have to add !important to all properties values set on media queries in order that it makes an effect.
为了解决这个问题,我在 scss 上使用了 Vikas mentioned in this link。
您可以将它放在单独的文件中,然后将其包含在您要使用它的任何文件中。
$phone : '(max-width: 480px)';
$phone-landscape : '(max-height: 480px)';
$tablet-portrait: '(max-width: 767px)';
$tablet-landscape: '(min-width: 768px) and (max-width: 979px) and (max-height: 768px)';
$large-desktop: '(min-width: 1200px)';
$non-retina: 'screen and (-webkit-max-device-pixel-ratio: 1)';
$retina: '(min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(-webkit-min-device-pixel-ratio: 1.5),
(min-device-pixel-ratio: 1.5),
(min-resolution: 144dpi),
(min-resolution: 1.5dppx)';
@mixin respond-to($media) {
@media only screen and #{$media} {
@content;
}
}
然后在声明中调用:
.bookItem {
max-height: 450px;
min-height: 150px;
padding: 25px;
@include respond-to($phone) {
max-height: 150px;
padding: 15px;
}
}
而且有效。
我在使用以下组件架构的应用程序上应用媒体查询(用于响应行为)时遇到一些问题
base components:使用默认封装,有使用外部插件的地方,目前我们正在申请,某些情况下,PrimeNG external模块。这个想法是将这些基本组件移动到其他应用程序。这些都集成在它自己的共享模块中。
品牌组件:它重用基本组件,应用自定义样式和翻译文本,做一些特定的事情,它使用原生封装(为了与基本组件),但它不应用业务逻辑。这些都集成在导入共享模块的自己的品牌模块中。
业务组件:它重用品牌组件并在此处应用自己的业务逻辑(在多个视图中使用时)。这些都集成在导入品牌模块的自己的业务模块中。这些组件实现了默认的 angular 封装模式。
然后 我们有视图,它们集成在自己的模块中并导入业务模块。它将使用品牌和/或业务组件,这里我们面临一些关于 css 媒体查询 的问题。这些视图使用默认的 angular 封装模式。
具体情况是我们尝试为特定视图自定义输入字段,以便在响应情况下正确运行(移动设备、平板电脑和台式机在不同的方向上)。为此,我们使用外部插件 angular flex layout (beta 7)
此输入字段存在于基本组件中,但我们将其用于品牌案例。我们想要的是更改其在品牌上设置的默认 width/height 以适应将封装它的 div 容器。
这是我们目前所做的:
特定视图的css:
// MEDIA QUERIES
:host ::ng-deep {
@media screen and (min-width: 300px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width: 95%;
}
}
@media screen and (min-width: 300px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.625);
}
}
@media screen and (min-width: 480px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.9);
}
}
@media screen and (min-width: 640px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2);
height:(16px * 1.6);
}
}
@media screen and (min-width: 640px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.68);
height:(16px * 1.6);
}
}
@media screen and (min-width: 768px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.3);
height:(16px * 1.6);
}
}
@media screen and (min-width: 768px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.5);
height:(16px * 1.6);
}
}
@media screen and (min-width: 900px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.5);
height:(16px * 1.625);
}
}
@media screen and (min-width: 900px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 1.875);
height:(16px * 1.625);
}
}
@media screen and (min-width: 1200px) and (orientation: portrait) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 3.75);
height:(16px * 1.625);
}
}
@media screen and (min-width: 1200px) and (orientation: landscape) {
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
width:(80px * 2.5);
height:(16px * 1.625);
}
}
}
以前的自定义 类 存在并用于品牌化输入字段组件,以便根据不同情况更改其 UX。
品牌输入字段组件模板文件:
<sh-input-field [id]="id"
[caption]="caption | translate"
[(model)]="userInput"
[placeholder]="placeholder | translate"
[type]="inputType"
[color]="color"
[font-size]="fontsize"
[isDisabled]="!enabled"
[style]="{'width': width,
'height': height}"
[status]="status"
[baseClass]="INPUT_CLASS_ENABLED"
[extendedClass]="extendedClass"
[stateClasses]="{
focusedOn: INPUT_CLASS_EDITING,
enabledOn: INPUT_CLASS_ENABLED,
enabledOff: INPUT_CLASS_DISABLED,
valueChanged: INPUT_CLASS_CHANGED
}"
[passwordWeakCaption]="passwordWeakCaption"
[passwordMediumCaption]="passwordMediumCaption"
[passwordStrongCaption]="passwordStrongCaption"
[isPasswordFeedbackShown]="isPasswordFeedbackShown">
</sh-input-field>
品牌输入字段组件 scss 文件:
/* CAPTION */
.uiElemSideCaptionLeft,
.uiElemSideCaptionRight,
.uiElemSideCaptionDisabled {
position: relative;
display: inline-block;
padding-top: 2px;
text-align: left;
font-size: 14px;
-ms-opacity: 1;
opacity: 1;
color: #333;
}
.uiElemSideCaptionRight {
-ms-opacity: 1;
opacity: 1;
text-align: right;
}
.uiElemSideCaptionDisabled {
-ms-opacity: 0.4;
opacity: 0.4;
}
/* INPUT-FIELD */
.inputField,
.inputFieldEditing,
.inputFieldChanged,
.inputFieldDisabled {
position: relative;
display: inline-block;
height: 16px;
width: 80px;
padding: 4px;
background-color: #dddddd;
border-width: 1px;
border-color: #979797;
border-style: solid;
font-size: 14px;
text-align: left;
color: rgba(0, 0, 0, 1);
-ms-opacity: 1;
opacity: 1;
}
.inputFieldEditing {
-ms-opacity: 1;
opacity: 1;
background-color: #eee;
height: 14px;
border-width: 2px;
border-color: #F8E71C;
color: rgba(0, 0, 0, 1);
border-style: solid;
}
.inputFieldChanged {
-ms-opacity: 1;
opacity: 1;
background-color: rgba(245, 166, 35, 0.5);
height: 16px;
border-width: 1px;
border-color: #979797;
color: rgba(0, 0, 0, 1);
border-style: solid;
}
.inputFieldDisabled {
-ms-opacity: 0.6;
opacity: 0.6;
height: 16px;
background-color: lightgray;
border-width: 1px;
border-color: #979797;
border-style: solid;
color: rgba(0, 0, 0, 1);
}
品牌输入字段组件定义:
@Component({
selector: 'br-input-field',
templateUrl: './input-field.component.html',
styleUrls: ['./input-field.component.scss'],
encapsulation: ViewEncapsulation.Native
})
基本输入字段组件模板文件:
<div class="sh-input-field-global-container">
<div class="sh-input-field-label-container" *ngIf="caption !== '' && caption !== undefined && caption !== null">
<label [for]="id">{{caption}}</label>
</div>
<div class="sh-input-field-container" [ngClass]="extendedClass">
<input *ngIf="controlType !== 'password'"
[ngClass]="getCssClases('sh-input-field', baseClass)"
[attr.id]="id"
[placeholder]="placeholder"
[disabled]="isDisabled"
(focus)="InvokeFocus($event)"
(blur)="InvokeBlur($event)"
(keyup.enter)="InvokeKeyUpEnterEvent($event)"
(keyup.escape)="InvokeKeyUpEscapeEvent($event)"
[(ngModel)]="model"
[attr.name]="formName"
[maxLength]="length"
[type]="controlType"
[ngStyle]="style"/>
<input *ngIf="controlType === 'password'"
[ngClass]="GetCssClases('sh-input-field', baseClass)"
[attr.id]="id"
[disabled]="isDisabled"
(focus)="InvokeFocus($event)"
(blur)="InvokeBlur($event)"
(keyup.enter)="InvokeKeyUpEnterEvent($event)"
(keyup.escape)="InvokeKeyUpEscapeEvent($event)"
[(ngModel)]="model"
[attr.name]="formName"
[maxLength]="length"
[type]="controlType"
pPassword
[promptLabel]="placeholder"
[weakLabel]="passwordWeakCaption"
[mediumLabel]="passwordMediumCaption"
[strongLabel]="passwordStrongCaption"
[feedback]="isPasswordFeedbackShown"
[ngStyle]="style"/>
</div>
</div>
基本输入字段组件定义:
@Component({
selector: 'sh-input-field',
templateUrl: './input-field.component.html',
styleUrls: ['./input-field.component.scss']
})
那么这里可能出了什么问题? 我们是否在特定视图上错误地使用了 :host :ng-deep? 我们已经看到,如果我们将这些媒体查询直接应用于品牌输入字段 sass 文件,它工作正常(删除 :host :ng-deep 标签)
尝试 :host /deep/
而不是 :host ::ng-deep
,如下所示
:host /deep/ {
/*your style goes here*/
}
或
使用encapsulation: ViewEncapsulation.None
代替encapsulation: ViewEncapsulation.Native
But, I have to add !important to all properties values set on media queries in order that it makes an effect.
为了解决这个问题,我在 scss 上使用了 Vikas mentioned in this link。
您可以将它放在单独的文件中,然后将其包含在您要使用它的任何文件中。
$phone : '(max-width: 480px)';
$phone-landscape : '(max-height: 480px)';
$tablet-portrait: '(max-width: 767px)';
$tablet-landscape: '(min-width: 768px) and (max-width: 979px) and (max-height: 768px)';
$large-desktop: '(min-width: 1200px)';
$non-retina: 'screen and (-webkit-max-device-pixel-ratio: 1)';
$retina: '(min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(-webkit-min-device-pixel-ratio: 1.5),
(min-device-pixel-ratio: 1.5),
(min-resolution: 144dpi),
(min-resolution: 1.5dppx)';
@mixin respond-to($media) {
@media only screen and #{$media} {
@content;
}
}
然后在声明中调用:
.bookItem {
max-height: 450px;
min-height: 150px;
padding: 25px;
@include respond-to($phone) {
max-height: 150px;
padding: 15px;
}
}
而且有效。