У меня есть родительский компонент:


И я хочу заполнить эту группу дочерними компонентами:


  
  
  

Родительский шаблон:

Дочерний шаблон:

Test

Поскольку родительский и дочерний - это два отдельных компонента, их стили привязаны к их собственной области действия.

В моем родительском компоненте я пытался сделать:

.parent .child {
  // Styles for child
}

Но стили .child не применяются к компонентам child.

I tried using styleUrls to include the parent's stylesheet into child component to solve the scope issue:

// child.component.ts
styleUrls: [
  './parent.component.css',
  './child.component.css',
]

Но это не помогло, также попробовали другой способ, загрузив дочернюю таблицу стилей в родительский, но это тоже не помогло.

Итак, как вы стилизуете дочерние компоненты, которые включены в родительский компонент?

Ответы (20)

Обновление - Новейший способ

Не делай этого, если можно этого избежать. Как отмечает Девон Санс в комментариях: эта функция, скорее всего, будет устаревшей.

Последнее обновление

Начиная с Angular 4.3.0 и до сих пор (Angular 12.x), все комбинаторы css не рекомендуются. Команда Angular представила новый комбинатор :: ng-deep, как показано ниже,

ДЕМО: https://plnkr.co/edit/RBJIszu14o4svHLQt563?p=preview

styles: [
    `
     :host { color: red; }
     
     :host ::ng-deep parent {
       color:blue;
     }
     :host ::ng-deep child{
       color:orange;
     }
     :host ::ng-deep child.class1 {
       color:yellow;
     }
     :host ::ng-deep child.class2{
       color:pink;
     }
    `
],



template: `
      Angular2                                //red
                                      //blue
                               //orange
                //yellow
                //pink
            
    `

по старинке

Вы можете использовать режим инкапсуляции и / или комбинаторы CSS с проникновением >>>, / deep / и :: shadow

рабочий пример: http://plnkr.co/edit/1RBDGQ?p=preview

styles: [
    `
     :host { color: red; }
     :host >>> parent {
       color:blue;
     }
     :host >>> child{
       color:orange;
     }
     :host >>> child.class1 {
       color:yellow;
     }
     :host >>> child.class2{
       color:pink;
     }
    `
    ],

template: `
  Angular2                                //red
                                  //blue
                           //orange
            //yellow
            //pink
        
`

Была такая же проблема, поэтому, если вы используете angular2-cli с scss / sass, используйте '/ deep /' вместо '>>>', последний селектор еще не поддерживается (но отлично работает с css).

Есть несколько способов добиться этого в Angular:

1) Вы можете использовать глубокие селекторы css

:host >>> .childrens {
     color: red;
 }

2) Вы также можете изменить инкапсуляцию представления, для которой по умолчанию установлено значение «Эмуляция», но ее можно легко изменить на «Нативная», которая использует встроенную реализацию браузера Shadow DOM, в вашем случае вам просто нужно отключить ее

Например: `

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'parent',
  styles: [`
    .first {
      color:blue;
    }
    .second {
      color:red;
    }
 `],
 template: `
    
First Second
`, encapsulation: ViewEncapsulation.None, }) export class ParentComponent { constructor() { } }

Если вы хотите быть более ориентированными на фактический дочерний компонент, вам следует сделать следующее. Таким образом, если другие дочерние компоненты имеют то же имя класса, они не пострадают.

Plunker: https://plnkr.co/edit/ooBRp3ROk6fbWPuToytO?p=preview

Например:

import {Component, NgModule } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    

I'm the host parent






`, styles: [` /deep/ child-component.target1 .child-box { color: red !important; border: 10px solid red !important; } /deep/ child-component.target2 .child-box { color: purple !important; border: 10px solid purple !important; } /deep/ child-component.target3 .child-box { color: orange !important; border: 10px solid orange !important; } /* this won't work because the target component is spelled incorrectly */ /deep/ xxxxchild-component.target4 .child-box { color: orange !important; border: 10px solid orange !important; } /* this will affect any component that has a class name called .child-box */ /deep/ .child-box { color: blue !important; border: 10px solid blue !important; } `] }) export class App { } @Component({ selector: 'child-component', template: `
Child: This is some text in a box
`, styles: [` .child-box { color: green; border: 1px solid green; } `] }) export class ChildComponent { } @NgModule({ imports: [ BrowserModule ], declarations: [ App, ChildComponent ], bootstrap: [ App ] }) export class AppModule {}

Надеюсь, это поможет!

кодовая матрица

Вы НЕ должны использовать :: ng-deep, это устарело. В Angular правильный способ изменить стиль дочернего компонента от родительского - использовать инкапсуляцию (прочтите предупреждение ниже, чтобы понять последствия):

import { ViewEncapsulation } from '@angular/core';

@Component({
    ....
    encapsulation: ViewEncapsulation.None
})

И тогда вы сможете изменить CSS-форму вашего компонента без необходимости из :: ng-deep

.mat-sort-header-container {
  display: flex;
  justify-content: center;
}

ПРЕДУПРЕЖДЕНИЕ: в результате все правила css, которые вы пишете для этого компонента, станут глобальными.

Чтобы ограничить область действия вашего css только этим компонентом и его дочерним элементом, добавьте класс css в верхний тег вашего компонента и поместите свой css «внутрь» этого тега:

template:
    
First
,

Scss-файл:

.my-component {
  // All your css goes in there in order not to be global
}

Я предлагаю пример, чтобы сделать его более понятным, поскольку angular.io / guide / component-styles утверждает:

Комбинатор потомков с пропусканием теней устарел, и его поддержка прекращается из основных браузеров и инструментов. По этой причине мы планируем отказаться от поддержки Angular (для всех трех из / deep /, >>> и :: ng-deep). До тех пор следует отдавать предпочтение :: ng-deep для более широкой совместимости с инструментами.

На app.component.scss, при необходимости импортируйте ваш *. Scss._colors.scss имеет несколько общих значений цвета:

$button_ripple_red: #A41E34;
$button_ripple_white_text: #FFF;

Применить правило ко всем компонентам

Все кнопки с классом btn-red будут стилизованы.

@import `./theme/sass/_colors`;

// red background and white text
:host /deep/ button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}

Применить правило к отдельному компоненту

Все кнопки с классом btn-red в компоненте app-login будут стилизованы.

@import `./theme/sass/_colors`;

/deep/ app-login button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}

Вы не должны писать правила CSS для элементов дочернего компонента в родительском компоненте, поскольку компонент Angular является автономным объектом, который должен явно объявлять, что доступно для внешнего мира. Если дочерний макет изменится в будущем, ваши стили для элементов дочерних компонентов, разбросанных по файлам SCSS других компонентов, могут легко сломаться, что сделает ваш стиль очень хрупким. Вот для чего ViewEncapsulation в случае CSS. В противном случае было бы то же самое, если бы вы могли назначать значения частным полям какого-то класса из любого другого класса в объектно-ориентированном программировании.

Следовательно, вам следует определить набор классов, которые вы могли бы применить к дочернему элементу хоста, и реализовать то, как дочерний элемент будет на них реагировать.

Технически это можно было сделать так:

// child.component.html:


// child.component.scss:
:host.child-color-black {
    .label-1 {
        color: black;
    }
}

:host.child-color-blue {
    .label-1 {
        color: blue ;
    }
}

// parent.component.html:


In other words, you use :host pseudo-selector provided by Angular + set of CSS classes to define possible child styles in child component itself. You then have the ability to trigger those styles from outside by applying pre-defined classes to the host element.

Я решил это вне Angular. Я определил общий scss, который я импортирую своим детям.

shared.scss

%cell {
  color: #333333;
  background: #eee;
  font-size: 13px;
  font-weight: 600;
}

child.scss

@import 'styles.scss';
.cell {
  @extend %cell;
}

Предлагаемый мной подход - это способ решения проблемы, о которой спрашивает ОП. Как уже неоднократно упоминалось, :: ng-deep,: ng-host обесценится, а отключение инкапсуляции, на мой взгляд, слишком большая утечка кода.

У меня тоже была эта проблема, и я не хотел использовать устаревшее решение так что я получил:

в парилете

 
 

дочерний компонент

@Input() ContainerCustomStyle: string;

в дочернем элементе html div

 

и в коде

constructor(private sanitizer: DomSanitizer) {  }

  GetStyle(c) {
    if (isNullOrUndefined(c)) { return null; }
    return  this.sanitizer.bypassSecurityTrustStyle(c);
  }

работает должным образом и не рекомендуется к использованию;)

По мере обновления Интернета я нашел решение.

Сначала некоторые оговорки.

  1. Still don't do it. To clarify, I wouldn't plan on child components allowing you to style them. SOC. If you as the component designer want to allow this then all the more power to you.
  2. If your child doesn't live in the shadow dom then this won't work for you.
  3. If you have to support a browser that can't have a shadow dom then this also won't work for you.

Во-первых, отметьте инкапсуляцию вашего дочернего компонента как тень, чтобы она отображалась в реальном теневом пространстве. Во-вторых, добавьте атрибут части к элементу, который вы хотите разрешить родителю стилизовать. В таблице стилей родительского компонента вы можете использовать метод :: part () для доступа к

Я предпочитаю достичь следующего:

используйте @ Component, чтобы добавить класс css к элементу хоста и установить для инкапсуляции значение none. Затем укажите этот класс, который был добавлен к хосту в компонентах style.css.scss. Это позволит нам объявлять стили, которые будут влиять только на нас и наших детей в рамках нашего класса. например

@Component({
  selector: 'my-component',
  templateUrl: './my-component.page.html',
  styleUrls: ['./my-component.page.scss'],
  host: {
    class: 'my-component-class'
  },
  encapsulation: ViewEncapsulation.None
})

в сочетании со следующим css (my-component.page.scss)

// refer ourselves so we are allowed to overwrite children but not global styles
.my-component-class {
  // will effect direct h1 nodes within template and all h1 elements within child components of the 
  h1 {
    color: red;
  }
}
// without class "scope" will affect all h1 elements globally
h1 {
  color: blue;
}

Быстрый ответ - вам вообще не следует этого делать. Это нарушает инкапсуляцию компонентов и подрывает преимущества, которые вы получаете от автономных компонентов. Подумайте о том, чтобы передать флаг свойства дочернему компоненту, после чего он может сам решить, как выполнять другой рендеринг или при необходимости применить другой CSS.


  

Angular не поддерживает все способы воздействия на дочерние стили от родителей.

https://angular.io/guide/component-styles#deprecated-глубокий-и-нег-глубокий

Для присвоения класса элемента дочернему компоненту вы можете просто использовать строку @ Input в дочернем компоненте и использовать ее как выражение внутри шаблона. Вот пример того, что мы сделали, чтобы изменить тип значка и кнопки в общем компоненте кнопки загрузки Bootstrap, не повлияв на то, как он уже использовался во всей кодовой базе:

app-loading-button.component.html (дочерний)


app-loading-button.component.ts

@Input() additionalClasses: string;

parent.html

...

Я считаю, что чище передать переменную @INPUT, если у вас есть доступ к коду дочернего компонента:

Идея состоит в том, что родитель сообщает дочернему элементу, каким должно быть его состояние внешнего вида, и ребенок решает, как отображать это состояние. Хорошая архитектура

Путь SCSS:

.active {
  ::ng-deep md-list-item {
    background-color: #eee;
  }
}

Лучше: - используйте selected переменную:


    
        
    

пусть 'parent' будет именем класса родителя, а 'child' будет именем класса дочернего

.parent .child{
//css definition for child inside parent components
} 

вы можете использовать этот формат для определения формата CSS для «дочернего» компонента внутри «родительского» * ​​100002 *

Собственно есть еще один вариант. Что довольно безопасно. Вы можете использовать ViewEncapsulation.None, НО поместите все стили компонентов в его тег (он же селектор). Но в любом случае всегда предпочитаю какой-то глобальный стиль плюс инкапсулированные стили.

Вот модифицированный пример Дениса Рыбалки:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'parent',
  styles: [`
    parent {
      .first {
        color:blue;
      }
      .second {
        color:red;
      }
    }
 `],
 template: `
    
First Second
`, encapsulation: ViewEncapsulation.None, }) export class ParentComponent { constructor() { } }

К сожалению, похоже, что селектор / deep / устарел (по крайней мере, в Chrome) https://www.chromestatus.com/features/6750456638341120

Короче говоря, похоже, что (в настоящее время) нет долгосрочного решения, кроме как каким-то образом заставить ваш дочерний компонент динамически стилизовать вещи.

Вы можете передать объект стиля своему ребенку и применить его через:



Или, если у вас есть определенный стиль, вы можете использовать что-то вроде:

Дополнительные обсуждения, связанные с этим: https://github.com/angular/angular/issues/6511

Поскольку / deep /, >>> и :: ng-deep устарели. Наилучший подход - использовать в стиле вашего дочернего компонента следующее

:host-context(.theme-light) h2 {
  background-color: #eef;
}

Это будет искать световую тему в любом из предков вашего дочернего компонента. См. Документы здесь: https://angular.io/guide/component-styles#host-context

ОБНОВЛЕНИЕ 3:

:: ng-deep также устарел, что означает, что вам больше не следует этого делать. Неясно, как это влияет на то, где вам нужно переопределить стили в дочерних компонентах из родительского компонента. Мне кажется странным, если это будет полностью удалено, потому что как это повлияет на вещи как библиотеки, где вам нужно переопределить стили в библиотечном компоненте?

Прокомментируйте, если вы понимаете это.

ОБНОВЛЕНИЕ 2:

Так как / deep / и все другие селекторы с пропусканием теней теперь устарели. Angular упал :: ng-deep, который следует использовать вместо этого для более широкой совместимости.

ОБНОВЛЕНИЕ:

Если вы используете Angular-CLI, вам нужно использовать / deep / вместо >>>, иначе это не сработает.

ОРИГИНАЛ:

После перехода на страницу Angular2 на Github и случайного поиска «стиля» я нашел следующий вопрос: Angular 2 - стиль innerHTML

В котором говорилось об использовании того, что было добавлено в селекторы 2.0.0-beta.10, >>> и :: shadow.

(>>>) (и эквивалент / deep /) и :: shadow были добавлены в 2.0.0-beta.10. Они похожи на комбинаторы CSS shadow DOM (которые устарели) и работают только с инкапсуляцией: ViewEncapsulation.Emulated, которая используется по умолчанию в Angular2. Они, вероятно, также работают с ViewEncapsulation.None, но затем игнорируются только потому, что в них нет необходимости. Эти комбинаторы являются лишь промежуточным решением до тех пор, пока не будут поддерживаться более продвинутые функции для кросс-компонентного стиля.

Так просто:

:host >>> .child {}

В файле таблицы стилей parentрешена проблема. Обратите внимание, как указано в приведенной выше цитате, это решение является промежуточным до тех пор, пока не будет поддерживаться более продвинутое кросс-компонентное оформление.

На сегодняшний день (Angular 9) Angular использует Shadow DOM для отображения компонентов как пользовательских HTML-элементов. Один из элегантных способов стилизации этих настраиваемых элементов может заключаться в использовании настраиваемых переменных CSS. Вот общий пример:

класс ChildElement расширяет HTMLElement {
  constructor () {
    супер();
    
    var shadow = this.attachShadow ({режим: 'открытый'});
    var wrapper = document.createElement ('div');
    wrapper.setAttribute ('класс', 'оболочка');
    
    // Создаем CSS для применения к теневому объекту
    var style = document.createElement ('стиль');
    
    style.textContent = `
    
      / * Здесь мы определяем значение по умолчанию для переменной --background-clr * /
      :хозяин {
        --background-clr: зеленый;
      }
      
      .wrapper {
        ширина: 100 пикселей;
        высота: 100 пикселей;
        цвет фона: var (- background-clr);
        граница: сплошной красный 1px;
      }
    `;
    
    shadow.appendChild (стиль);
    shadow.appendChild (обертка);
  }
}

// Определяем новый элемент
customElements.define ('дочерний элемент', ChildElement);
/ * КОД CSS * /

/ * Этот элемент называется: host с точки зрения настраиваемого элемента. Комментирование этого CSS приведет к тому, что фон станет зеленым, как определено в пользовательском элементе * /

child-element {
  --background-clr: желтый;
}

Как видно из приведенного выше кода, мы создаем настраиваемый элемент, точно так же, как Angular сделал бы для нас с каждым компонентом, а затем мы переопределяем переменную, отвечающую за цвет фона в теневом корне настраиваемого элемента, из глобальная область видимости.

В приложении Angular это может быть что-то вроде:

parent.component.scss

child-element {
  --background-clr: yellow;
}

child-element.component.scss

:host {
  --background-clr: green;
}

.wrapper {
  width: 100px;
  height: 100px;
  background-color: var(--background-clr);
  border: 1px solid red;
}

2022 WebDevInsider