Best way to pass styling to a component

I would just use a styles input property on InputEdit, and pass in an object with the desired styles:

<InputEdit [styles]="stylesObj">                 // in host component's template

stylesObj = {font-size: '1.1em', color: 'red'};  // in host component class

<input [ngStyle]="stylesObj" ...>                // in InputEdit component's template

If you have multiple DOM elements you want to style, pass in a more complex object:

<InputEdit [styles]="stylesObj">

stylesObj = {
  input: {font-size: '1.1em', color: 'red'}
  label: { ... } 
};

<label [ngStyle]="styles.label" ...>
<input [ngStyle]="styles.input" ...>

Mark Rajcok's answer is good for a group of styles, but if you're only going to allow the font-size and color to be changed, you may want to use a more direct approach like you started with (in this example, also enforcing only pixels instead of a more flexible string for demonstration purposes):

For Individual Style Properties:

Component:
<InputEdit [color]="'red'" [fontSize]="16">

component.ts:
Input() color: string = 'black';
Input() fontSize: number = 18;

component.template:
<input type="text" [style.color]="color" [style.fontSize.px]="fontSize">


If Allowing a Group of Styles:

Component:
<InputEdit [styles]="{backgroundColor: 'blue', 'font-size': '16px'}"> NOTE: Make sure the CSS properties are camelCased or in a string if there is more than one word.

component.ts:
@Input() styles: any = {};

component.template:
<input type="text" [ngStyle]="styles">


update

::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

original

/deep/, ::shadow and >>> are deprecated. ::ng-deep is the best option until all browsers properly support style encapsulation and ViewEncapsulation.Emulated can be removed.

The deprecation is only for the native implementation in Chrome (other browsers never implemented it) but Angular has its own emulation of these CSS combinators in ViewEncapsulation.Emulated (default)

/deep/, ::shadow and >>>::ng-deep can therefore be used just fine in Angular2.

For more than simple classes or style property settings use ngStyle Angular 2.0 and ng-style


If you want to leave it up to the component to define the actual css you can try one of the following:

Add a property on your component for each 'logical' style setting, for instance headerSize.

@Input('headerSize') headerSize: ('small' | 'large');

Then your component can check its value in one of a few ways to style itself:

  1. Modify the HTML itself by showing or hiding child elements

    <h1 *ngIf="headerSize == 'large'">{{ title }}</h1>
    <h2 *ngIf="headerSize == 'small'">{{ title }}</h2>
    
  2. Set a custom class dynamically inside the component somewhere, and style it:

    <div [ngClass]="'header-' + headerSize">
    
    .header-small { h1 { font-size: 20px; } }
    .header-large { h1 { font-size: 30px; } }
    
  3. Set a custom class dynamically at the class level. This is the same as #2 and doesn't require a wrapper element. However it's less than trivial to actually enable and disable these classes.

    @HostBinding('class.header-small') _header_small;
    @HostBinding('class.header-large') _header_large;
    

Also note that if you're using ng-content that the styles applied are the styles defined in the containing component and not the component that actually does the content replacement.

Tags:

Angular