angular: Components should create a `display:block` style by default
Let’s say I create a new component in Angular2 and I attempt to style it:
// hello_world_cmp.ts
@Component({
selector: 'hello-world',
styleUrls: ['hello-world.css']
template: 'hello world!'
})
class HelloWorldCmp { }
// hello_world.css
:host { background: red; }
The styling fails to be applied for the sole reason that browsers have no clue what the <hello-world></hello-world>
HTML element is. This is expected, but it’s tricky to debug for those of whom are new to Angular and to web components. This is also the case with predefined Angular components (like <router-outlet></router-outlet>
).
Solution
I think it’s best if Angular keeps track of each of the components created in an application and builds a CSS selector which is placed at the HEAD of the index.html file within a style tag.
<head>
<style>
router-outlet, hello-world { display:block; }
<style>
</head>
Since the CSS selectors are tag selectors this means that they have the lowest specificity and the fact that the styles are placed at the top of the index.html document this then allows for ui-libraries and user-defined styles to easily override the styles without having to use a heavier selector (e.g. is a .class
selector is used to match all components then a user style like hello-world
would lose to that in the specificity battle).
We should also have a flag to disable this.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 27
- Comments: 20 (8 by maintainers)
@tbosch we can’t use
element.style.display
because that’s an inline style and inline styles have the highest specificity. So something like this would always require!important
.@tbosch and @kasperpeulen The reason why we use
display:block
here is because almost all components that contain inner element data are block by default in HTML (think<div>
,<p>
). Even HTML5 elements like<section>
,<footer>
,<aside>
are all block level (here’s proof: http://plnkr.co/edit/aaIVUpEhqrVx6NltvFya?p=preview). That being said, there’s a higher chance that the user expects this as the default and then overrides to support something likeflex
orinline
.This isn’t so much about the component author vs the template author, it’s more about allowing the user to skip an annoying step for every component created.
I would prefer that angular components just received a css class when compiled. for example:
<my-component></my-component> would become: <my-component class="ng-component"></my-component>
Thus, the author could do a global style to default components to whatever they want:
This is the 1st result (or one of the firsts) in Google when searching about Angular components display block.
Maybe this link (to the Angular 2 Doc: Component Styles) which describes about styling the Component with
display: block;
using:host
could be useful: https://angular.io/docs/ts/latest/guide/component-styles.html#!#-hostUpdate: Angular 4 doc link: https://angular.io/guide/component-styles#host
You can use
host: { 'style': 'display: block' }
. I had to do this to get routing animations to work.+1 @nawlbergs
They discussed this and I understand the reasoning why they didn’t change the
display
property.obsolete (would be a breaking change)
FWIW if you’re arriving here from google, Angular components using
display: flex
have a really bad interaction where if you don’t setdisplay: block
it seems to just be inherited into the children components forever and they all flex. More importantly, even though they will mostly display “OK”, half a dozen javascript properties will showheight: 0
since they are notblock
, which messes up a lot of libraries probing for element width/height (it’s arguable whether this is a bug in the libraries or whatever, I’ll leave it at that).You have to ‘tie the knot’ with
display: block
in your:host
style for your children or use a solution provided from here. You don’t usually notice this because thedisplay: block;
ondiv
usually takes higher precedence and does this automatically …Another solution is to use
:host > * { display: block; }
but this can be messy depending on your content.If it is an
ng-content
container use:host /deep/ > *
(at time of writing, this was very recently deprecated but there is no replacement yet afaik).Why would
display: block
by default be better thandisplay:inline
?I don’t understand, why would not just style the
host
css using css yourself. As creator/designer of the web component, you would know best if it should be display: block or display: inline?