覆盖 mat-form-field 的第一个 div 的样式

Posted

技术标签:

【中文标题】覆盖 mat-form-field 的第一个 div 的样式【英文标题】:Override style of first div of mat-form-field 【发布时间】:2018-10-22 21:01:43 【问题描述】:

如何覆盖 <mat-form-field> 生成的第一个 div 上的 CSS?

背景

我在 <mat-card> 中有一堆字段,而 last 字段导致卡片底部的填充过多。

<mat-form-field id="this-feels-hacky-and-wrong"...>
    <!-- I want to remove the padding-bottom from this element -->
    <div class="mat-input-wrapper mat-form-field-wrapper">
      ...
    </div>
</mat-form-field>

在我的stlye.css 我放了

#this-feels-hacky-and-wrong div
  padding-bottom: 0;

这可行,但必须有更好/正确的方法来做到这一点,不是吗?

我会更喜欢我的component.scss 文件中的解决方案。

【问题讨论】:

您介意创建一个可运行的小示例并更详细地解释您要做什么吗? 【参考方案1】:

更新:见上面 pistol-pete 的回答。本质上是一样的。

对于那些迟到的人,还有另一种方法可以做到这一点。不要以各种形式使用 ng-deep,因为它已被弃用。不推荐打破封装,这违背了 Angular 的设计实践。解决方案是全局 CSS,但带有特定的选择器。

mat-form-field 是 Angular 材质的一部分。它有自己的封装。全局样式,而不是组件样式,可以覆盖它。但是,您可能不想覆盖所有这些元素,可能只是一两个。我通过使用一个独特的类来隔离我想要更改的元素来解决这个问题,然后添加.mat-form-field-wrapper 来定位具有填充的元素。这是一个例子:

<mat-form-field class="pb-0">
  <mat-label>Not so hacky</mat-label>
  <imput matInput formControlName="notHacky" />
</mat-form-field>

然后使用pb-0 类,或任何你想调用的类,定位到全局 CSS 空间。在 Angular 中,这是 styles.css。使用 Sass,您可能会将其他全局文件导入到样式文件中。添加这个:

/* sass */
mat-form-field 
  &.pb-0 
    .mat-form-field-wrapper 
      padding-bottom: 0;
    
  


/* plain css */
mat-form-field.pb-0 .mat-form-field-wrapper
 
  padding-bottom: 0;
 

您可以对来自任何框架的任何组件重复此操作,因为全局样式将应用于任何地方。我建议创建一个独特的文件来保存所有这些覆盖。

【讨论】:

【参考方案2】:

使用::ng-deep/deep/ 对我来说不是一个解决方案,因为它很快就会成为deprecated。

ViewEncapsulation.None 对我来说也不是一个好的解决方案,因为它在使用时往往会破坏其他几种组件样式。

您可以将自定义样式(例如no-padding)添加到您的全局样式表中。

//example:
mat-form-field.no-padding .mat-form-field-wrapper 
    padding: 0;

然后根据需要将其应用到您的Material UI Form Fields。

//example:
<mat-form-field class="no-padding">
    <mat-label>First Name</mat-label>
    <input matInput placeholder="First Name">
</mat-form-field>

【讨论】:

【参考方案3】:

试试这个::ng-deep

html

<mat-form-field class="this-feels-better"...>

component.scss

:host ::ng-deep .this-feels-better div.mat-input-wrapper.mat-form-field-wrapper
  padding-bottom: 0;

替代方案

如果你真的不想使用ng-deep,因为它将来会被删除,并且你真的想在你的component.scss文件中包含你的css规则,那么你可以将组件的视图封装更改为None

import ViewEncapsulation from '@angular/core';

@Component(
   //...
   encapsulation: ViewEncapsulation.None
)

但是,在这种情况下,您需要确保在该组件中的所有 CSS 规则前面加上该组件独有的某种选择器,以防止规则泄漏到其他组件。

.uniqueClassOnComponent .this-feels-better div.mat-input-wrapper.mat-form-field-wrapper
   padding-bottom: 0;


//Other generic rules
.uniqueClassOnComponent span  ... 

【讨论】:

How to style child components from parent component's css file?。 Angular Docs:“因此,我们计划放弃对 Angular 的支持(对 /deep/、>>> 和 ::ng-deep 的所有 3 个)。” 他们不会放弃它,直到有替代品,他们还没有找到。否则,将组件的 viewEncapsulation 设置为 none,您的代码应该可以在 component.scss 中运行。但是你应该在你的组件中的所有规则前面加上一些组件独有的选择器,这样样式就不会泄漏到其他组件 好点,不,他们不会!根据我的研究,这是 vNext 解决方案:Add support for Shadow DOM V1 刚刚注意到这一点(或刚刚添加)“...在此之前,应该首选 ::ng-deep 以实现与工具的更广泛兼容性。” 有一个替代解决方案。如果你有一个全局 css 文件,你可以把你的类放在那里,你的组件可以使用这些 css 规则而不改变 ViewEncapsulation。【参考方案4】:

借助 CSS,您可以使用 第 n 个术语。只要您尝试定位的 div 与其他 div 具有相同的父 div,您就可以像这样引用第一个和最后一个子 div:.my-div-class:first-child .my-div-class:last-child 因此,更进一步,nth-term 可用于定位任何这样的孩子:.my-div.class:nth-child(2) 这将针对第二个孩子。 为了进一步澄清您的问题,您的 CSS 应如下所示:

mat-form-field:last-child div 
   padding-bottom: 0;

【讨论】:

投反对票,因为这实际上并没有回答问题。 是的。他们想知道如何定位第一个生成的 div 以删除填充,这就是我的回答显示的方法。 Shadow DOM ...

以上是关于覆盖 mat-form-field 的第一个 div 的样式的主要内容,如果未能解决你的问题,请参考以下文章

mat-form-field 必须包含一个 MatFormFieldControl 并且已经导入

Angular:mat-form-field 必须包含一个 MatFormFieldControl

如何删除轮廓mat-form-field边角半径

Angular Material 表单问题:角度 mat-form-field 必须包含 MatFormFieldControl

在 Angular/Material 中设置 mat-form-field 输入样式

Angular ng-content 不适用于 mat-form-field