I'm learning Angular from a ReactJS and JSVanilla background. I'm trying to understand how Angular build its views and how can we work with them.
My question is: What is the best way (or available options) to make parent css reflect / constraint child css on Angular?
Example, using JSVanilla:
<section class="parent">
<section class="child">
<section class="grandchild">
</section>
</section>
</section>
.parent{
height: 1000px;
width: 800px;
}
.child{
height: 80%;
width: 90%;
}
.grandchild{
height: 30%;
width: 20%;
}
In this case, each section would be a component by itself.
Well, studying for a few, I've come up with a nice solution which involves the :host selector.
In angular, after all the components in a module being rendered, we get the following pseudo-tree:
<app-parent>
<section class="parent">
<app-child>
<section class="child">
<app-grandchild>
<section class="grandchild">
</section>
</app-grandchild>
</section>
</app-child>
</section>
</app-parent>
As we can see, the constraints of the child is being marked by the <app-tag/>, which dictates how the children will be rendered.
In terms of size, but not all attributes, the best option for me was to use the :host selector, which selects the <app-tag/>. In the css, will look like this:
:host{
height:80%;
width: 90%;
}
.child{
/* child styles here */
}
And this resolved my problems.
You can read about View Encapsulation concept in Angular.
There are 3 types of View encapsulation.
ViewEncapsulation.None
ViewEncapsulation.Emulated
ViewEncapsulation.ShadowDom
You can place encapsulation in #Component decorator as shown in the below code snippet
#Component({
selector: 'app-shadow-dom-encapsulation',
template: `
<h2>ShadowDom</h2>
<div class="shadow-message">Shadow DOM encapsulation</div>
<app-emulated-encapsulation></app-emulated-encapsulation>
<app-no-encapsulation></app-no-encapsulation>
`,
styles: ['h2, .shadow-message { color: blue; }'],
encapsulation: ViewEncapsulation.ShadowDom,
})
Please read the below article, Hope it helps!!
https://codecraft.tv/courses/angular/components/templates-styles-view-encapsulation/
Related
I tried out Angular before switching to Vue and found the :host selector in their components to be very handy. The jist of this is that it applies the stylings for :host to the component itself.
Is there an equivalent of this that works with .vue files in they <style scoped></style> section?
Examples:
Using Scoped
Parent:
<template>
<div class="host">
<layout-header :open-nav="openNav" #toggle-open="toggleOpen"></layout-header>
<layout-sidebar :open-nav="openNav"></layout-sidebar>
<layout-content></layout-content>
<layout-footer></layout-footer>
</div>
</template>
<style scoped>
.host {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
}
</style>
Content:
(<layout-content>)
<div class="host">
stuff
</div>
<style scoped>
.host{
flex: 1;
}
</style>
Output:
(removing the header, footer, and sidebar for simplicities sake.)
This results in the header, sidebar, content, and footer inheriting the parents css if they have a .host class.
HTML:
<div data-v-238e7577="" class="host">
<div data-v-7412829c="" data-v-238e7577="" class="host">stuff</div>
</div>
The CSS applied to the child element:
There is no equivalent for Angular's :host in Vue.
The closest you are gonna get is by using CSS module.
Demo: App.vue in https://codesandbox.io/s/o4orw9nz35
<template>
<div id="app" :class="$style.container">
<p class="red">p tag</p>
<div class="blue">div tag</div>
</div>
</template>
<style lang="scss" module>
.container :global {
.red {
color: red;
}
.blue {
color: blue;
}
}
</style>
Note how the .container class is used as $style.container as class in the root div.
CSS module will generate unique class name for .container, making it impossible to have class name collisions.
What does :global do?
CSS module transform the CSS class name into something unique by default.
for e.g. .container will be transformed into something like .container_7ba5bd90 when used as $style.container.
To avoid this transformation on certain classes, use :global to wrap them.
(Explanation for :global can be found here.)
I am trying to use Flexbox in my React app to create a simple two column webpage that occupies the full width and height.
I can get this to work with HTML and CSS on their own but not within a React app.
So far I have:
:root {
overflow-x: hidden;
height: 100%;
}
body {
min-height: 100%
}
.flexbox {
height: 100%;
display: flex;
}
.left {
flex: 0 0 200px;
height: 100%
}
.right {
flex: 1
}
and:
<div class="flexbox">
<div class="left">
Left
</div>
<div class="right">
Right
</div>
</div>
I realise that I need to account for the additional <div id="root"></div> tag in my index.html so I have also added the following to my css:
#root {
height: 100%;
}
And my render function:
render() {
return (
<div className="flexbox">
<div className="left">Left</div>
<div className="right">Right</div>
</div>
)
}
but this doesn't work. The columns exist but are not full height. Why not?
If you use create-react-app, it adds an element with class=App and an element with id=root to the DOM. They should also get height: 100%
html, body, #root, .App {
height: 100%;
}
Use viewport height units in css:
#root {
min-height: 100vh;
}
You forgot that <html> is also a tag. Moreover, it is parent to all parents! That's why you should give it height of 100% as well.
html, body {
height: 100%;
}
The body looks to its parent (HTML) for how to scale the dynamic property, so the HTML element needs to have its height set as well.
However, the content of the body will probably need to change dynamically. Setting min-height to 100% will accomplish this goal.
html {
height: 100%;
}
body {
height: 100%;
}
To the parent div of the page, add the following css.
position: fixed;
overflow: auto;
height: 100vh;
Try This:
[data-reactroot]
{height: 100% !important; }
Alternatively, if anything suggested above doesn't seems to be working for some reason, try using normalize.css package. It wipes all browser provided CSS and creates a fresh window for the app.
"normalize.css": "^8.0.1" //package.json (yarn add or npm install)
import "normalize.css/normalize.css"; //in app.js
Then in css file define the body height and width as 100vh & 100vw respectively.
docs: https://necolas.github.io/normalize.css/
There are a lot of answers here but none of them is working. I have tested all of them.
The best way to achieve minimum height in react js is to use the main tag inside your app and then add the minimum height for that tag.
Your App.js code should look like this.
<React.Fragment>
<Header />
<main>
<Container>
</Container>
</main>
<Footer />
</React.Fragment>
Note
You can simply remove React.Fragment if you want to use empty fragments.
then your code should look like this.
<>
<Header />
<main>
//Write your code here
</main>
<Footer />
</>
Now add CSS to your CSS file.
main {
min-height: 80vh;
}
Important
Few things you have to keep in mind.
Your header and footer or component call should be outside of the main tag. Like the code, I have shared above. I have called the header and footer outside the tag.
If you want to use routing then simply add Router above the tag.
Your code with routing and components call should look like this.
<React.Fragment>
<Router>
<Header />
<main>
<Container>
<Route path='/' component={HomeScreen} exact />
<Route path='/products' component={ProductScreen} />
<Route path='/cart' component={CartScreen} />
<Route path='/login' component={LoginScreen} />
</Container>
</main>
<Footer />
</Router>
</React.Fragment>
Here is a plunker demo that uses Angular 2 Material md-tab-group component.
Basically, this
<md-tab-group>
<md-tab>
<template md-tab-label>Tab</template>
<template md-tab-content>
<md-content class="md-padding">
<p>200 px height</p>
</md-content>
</template>
</md-tab>
</md-tab-group>
renders to a tab that has a body with 200px height. It uses flex layout, and I cannot find from the sources how to change minimum height. Actually, this style is listed for md-tab-group:
[_nghost-vvf-2] {
display: flex;
flex-direction: column;
font-family: Roboto,"Helvetica Neue",sans-serif;
min-height: 248px;
}
How can minimum height be restored to 0 for md-tab-group properly? And where did this min-height come from?
It appears that the problem is specific to 2.0.0-alpha.5 and 2.0.0-alpha.5-2, it doesn't appear in master.
If you have noticed, 48px height is declared for childs of 'md-tab-label'
.md-tab-label[_ngcontent-rru-2] {
line-height: 48px;
height: 48px;}
So remaining height(200px) is taken by the 'md-tab-content'.
You can override the min-height to zero for 'md-tab-group' in your app CSS file. (read CSS specificity)
min-height can be restored in component style attribute;
#Component({
selector: 'material-app',
templateUrl: 'app.component.html',
styles: [`
md-tab-group {
background:#fff;
min-height:0;
}
`],
directives: [MD_TABS_DIRECTIVES]
})
When writing css using BEM if you need to make changes to a module element when it is in a sub-module do you nest the module-element in the sub-module or create a new class name for the module-element?
Creating a New Class
Creating a new class name(i.e. module--modifier__element) seems to be more in the spirit of BEM. It prevents unnecessary specificity. But it also adds a lot of extra work adding an extra class to each element within the module.
Nesting
Nesting the existing element class within the module modifier(i.e. module--modifier module__element {} will add some extra specificity but saves you a lot of work(at least for large modules) and makes the markup easier to maintain. For example if you needed to change the modifier of a module you would only have to change it one place in the markup rather than having to change it on every child element.
In addition to that if not all of the child elements change then you will have to refer to the css to figure out which child elements need a class added to them.
EXAMPLE CODE
.module {
display: block;
width: 90%;
height: 2rem;
margin: 2rem auto;
padding: 0.5em;
background: #fff;
border: 2px solid #333;
}
.module--modified1 {
background: #333;
border: none;
}
.module--modified2 {
background: #baa;
border: 3px solid #8f8;
}
.module__element {
color: #333;
text-align: center;
}
/* Option 1 */
/* In sass this would actually be nested within the module_modified1 block */
.module--modified1 .module__element {
color: #fff;
}
/* Option 2 */
.module--modified2__element {
color: #fff;
font-size: 1.3em;
}
<div class="module">
<div class="module__element">Module</div>
</div>
<div class="module module--modified1">
<div class="module__element">Module Modifier 1</div>
</div>
<div class="module module--modified2">
<div class="module__element module--modified2__element">Modulue Modifier 2</div>
</div>
Both options are valid. Reduce the specificity is a good practice, but make the code simple is also a good practice.
However, BEM blocks have to be context-free. If a block can be recursively included into itself, then cascades must be avoided. For example, a generic block fun-rounded-block could be recursively reused like this:
<div class="fun-rounded-block fun-rounded-block--blue-version">
<div class="fun-rounded-block__content">
<div class="some-block-here">
<div class="fun-rounded-block">
<p class="fun-rounded-block__content">element in the sub-block here</p>
</div>
</div>
</div>
</div>
In this example, you cannot use a cascade for styling elements because the selector .fun-rounded-block--blue-version .fun-rounded-block__content would interfere with the sub-block.
I know that we can import a css style into another css style. That's not the thing I'm going to talk about.
I want to create a css style that depend on other css style. In other word, I want to create my own cascading tree system. How can I do that?
For example, how I pictured it in my mind:
div.priceinfo { border: 1px solid gray; width: 200px; }
div.disabled { background-color: gray; color: 333333; }
div.shippinginfo { depend: div.pricebox; border-color: green; }
div.taxinfo { depend: div.pricebox; border-color: blue; }
so I can use it like this:
<div class="priceinfo"> ... </div>
<div class="shippinginfo"> ... </div>
<div class="taxinfo disabled"> ... </div>
but I do not want like this:
<div class="priceinfo shippinginfo"> ... </div>
<div class="priceinfo taxinfo disabled"> ... </div>
I know that the last way is possible, but I'm curious whether there's any way I can do something like the one I described earlier? Thanks for the help.
I think you have to see a LESS CSS for this. a LESS CSS provides a coding for CSS.
http://lesscss.org