6

This site states, that I can change the width of the side-nav with CSS like this:

md-sidenav {
   width: 200px;
}

This arouses the following question for me: Can I apply the standard CSS properties like width, position, etc... to custom components without to define them in my component?

Example:

my-component {
    width: 500px;
}

I tried it out and it does not work. So I think, that the answer is no, am I right?

To find out how they set width with CSS I have read through the sources on github. But I can't figure out how they did that. The component has no width property. So, how did they make width accessible with CSS?


EDIT:

To clarify the question I will give you the following example:

I have programmed the following component:

test.component.html:

<p>test works!</p>

test.component.css:

p {
   border: 2px solid red;
}

test.component.ts:

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

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {

  constructor() { }

  ngOnInit() { }

}

This is my app root, that gets bootstrapped by angular:

app.component.html:

<app-test>

</app-test>

app.component.css

app-test {
  height: 100px;
  width: 200px;
}

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Test App';
  constructor() { }

}

The _app.component.css_ shows what I want to do. I want to set the size of the _app-test_ component with CSS. I saw this working with the _side-nav_ component of the angular material and I want to understand how they have enabled the _side-nav_ to get its width from the parent components CSS file.

FAISAL
  • 33,618
  • 10
  • 97
  • 105
Jonas Erbe
  • 177
  • 1
  • 12
  • [This guide](https://github.com/willshowell/material2/blob/cc8a3b9601cb8fcaad0060a470935e7e7d13f0b3/guides/customizing-component-styles.md) will hopefully be merged in soon and covers customizing component css. – Will Howell Aug 21 '17 at 19:32
  • Is no one there who can help me? – Jonas Erbe Aug 25 '17 at 09:53
  • Try to use `:host { height: ..., width: ... }` in `app.component.css`. I think that will accomplish what you're asking. – Will Howell Aug 25 '17 at 13:53
  • I dont want to accomplish it that way. I want to understand why the Syntax i wrote in my question is working with _md-sidenav_. I have studied the sources, but i can't figure out why the width css rule can be applied to_md-sidenav_. – Jonas Erbe Aug 25 '17 at 14:27
  • The sidenav component has view encapsulation turned off. If you do the same in your app component, it should have the same effect. – Will Howell Aug 25 '17 at 14:46
  • I already tried to set the encapsulation of_app-test_ to none. The width still does not affect_app-test_ – Jonas Erbe Aug 25 '17 at 14:52
  • Ah ok I was misreading something. Add `:host { display: block; }` to `app-test`'s styles. Components default to displaying as inline elements which cannot take height/width properties. – Will Howell Aug 25 '17 at 15:10
  • @ Will Howell: Thats it, thank you. I will write it down as an answer for the question. – Jonas Erbe Aug 28 '17 at 08:00

2 Answers2

6

UPDATE After OP's edit:

Change your app.component.css to this:

:host {
  display:block; 
  height: 100px;
  width: 200px;
}

This will apply the styles on the <app-test> selector. Here is the plunker demo.


ORIGINAL Answer:

You can override the default styles of Material 2 components by setting encapsulation: ViewEncapsulation.None in the component.

Then you'll have to define the styles in your component.css file.

.mat-sidenav {
    width: 250px;
}

See this plunker demo with user defined width.


Update after OP's comments:

Suppose you have a component file, my.component.ts and it has styles in my.component.css, you can define the styles of the component in the css file and apply then on the component selector using :host.

my.component.ts :

@Component({
    selector: 'my-comp', 
    templateUrl: 'my.component.html',
    styleUrls: ['my.component.css']
})
export class MyComponent{
}

my.component.css :

:host {
    width: 500px;
    background-color: red;
}

my.component.html:

<h2>Some Heading in the Template </h2>
FAISAL
  • 33,618
  • 10
  • 97
  • 105
  • 1
    I believe the correct Component metadata property name is `encapsulation`, not `ViewEncapsulation`. See [here](https://angular.io/api/core/Component) – Andrei Matracaru Aug 21 '17 at 15:24
  • Correct, my bad. Updated plunker and answer – FAISAL Aug 21 '17 at 15:33
  • In your demo, neither the alternate selector nor the change to selection are required. See [forked plunk](https://plnkr.co/edit/VhqUrTfZX8gCc4bt63FQ?p=preview) – Will Howell Aug 21 '17 at 16:05
  • @Will Hoowell, your gorked demo will work in this specific case, however it wont run for all components. Try setting height of `md-toolbar` your way – FAISAL Aug 21 '17 at 16:34
  • Sorry guys, but that did not answer my Question. What do I have to do to create a component which width can be set with css? – Jonas Erbe Aug 21 '17 at 17:14
  • Every component's width can be set using css. What is your exact requirement? – FAISAL Aug 21 '17 at 17:43
  • 1
    As an example a div has the property width. Thus i can set its width in my css file. Now I build a custom component _mycomponent_. Does it have the width property out of the box, hence i can set it with css? – Jonas Erbe Aug 21 '17 at 17:50
  • No it does not. You have to define a css class and set the properties in thay class. I'll update my answer with the solution you want, if I understood correctly. – FAISAL Aug 21 '17 at 17:53
  • I have edited my question to clarify what I want to know. I would be pleased if you can help me. – Jonas Erbe Aug 22 '17 at 08:48
  • @Faisal But i want to know, why this Syntax '.mat-sidenav { width: 250px; }' is working. That did they implement in their component, that i can set the width like that. They dont use the host selector: https://material.angular.io/components/sidenav/overview – Jonas Erbe Aug 22 '17 at 09:44
  • `.mat-sidenav` is the css class provided by Material2, we can use that to override the default styles with out own. – FAISAL Aug 22 '17 at 09:45
  • they dont use .mat-sidenav. Just the element selector _mat-sidenav_ – Jonas Erbe Aug 22 '17 at 09:47
  • yes because they are using `:host` - you got the answer what you wanted to achieve, what is the problem now? – FAISAL Aug 22 '17 at 09:48
  • no i didn get the answer I wanted to achieve. I want to know, why this part of code is possible: md-sidenav { width: 200px; } – Jonas Erbe Aug 22 '17 at 12:16
  • Watch this plunker: https://plnkr.co/edit/7vjuEKNBqIq2b4ITPZ2s?p=preview Why can they set padding of _.example-sidenav_ in CSS. That does not work out of the box. The component _side-nav_ does not have the property padding. Why can it be set with CSS? – Jonas Erbe Aug 22 '17 at 12:27
2

My Question was answered with the comment of Will howel beneath my question. This post should recap what I have learnered through the comments of the other users, so that people with a similar question could learn from it.

The template of every component is wrapped in a host element. In the sidenav example, this element is the md-sidenav tag. The host element is a regular dom-element, wherefore you can add standard css rules to that element. That means that you can apply css rules like width to every custom angular component out of the box. But you have to take into account that you need to set the display property of the host element to block. If you don't do that, the width rule has no effect to the element. To accomplish that in case of the md-sidenav component they applied the class mat-drawer within the component-decorator to the element.

exerpt from sidenav.ts:

    host: {
    'class': 'mat-drawer mat-sidenav',
    ...
  },

Then they set the rule in the stylesheet. Exerpt of drawer.scss:

 .mat-drawer {
     @include mat-drawer-stacking-context();

     display: block;
}
Jonas Erbe
  • 177
  • 1
  • 12