How to lower mat-icon with input in angular material? - css

This is my code:
<mat-form-field>
<input type="tel" matInput placeholder="Home">
<mat-icon matSuffix svgIcon="home" class="mdi-icon"></mat-icon>
</mat-form-field>
And this is the result:
As it is seen icon is to high and I want to lower it to decrease the distance between the bottom line and the icon. I tried:
.mdi-icon {
margin-bottom: -5px;
}
But it didn't help. Could anyone say how to do it?

For the CSS to have any effect on a child component you first need to first get around view encapsulation. View encapsulation will add a unique attribute to all of your HTML elements within the template, something like _ngcontent-nvb-c74="", then it will append that identifier to all of your CSS like [_ngcontent-nvb-c74]. That is how the CSS of one component does not affect others.
We need to make the CSS global. So, we need to use a unique selector or else your CSS will leak into other components. I would use the component name personally. I'm using app-my as an example selector for the component MyComponent. So in all three cases your CSS will look like:
app-my .mdi-icon {
...
}
Your options to get around View Encapsulation are:
1. Disable View Encapsulation for the component - not usually recommended
#Component({
...
encapsulation: ViewEncapsulation.None,
})
export class MyComponent {}
This makes all of the CSS in that component global, not great if you want view encapsulation in other areas of your component.
2. Put your CSS in styles.css
Any CSS in this file is global by default.
3. Create a new global style file for this component
Something like my.component.global.css
After creating this file you need to add it to the styles array in angular.json. Any CSS files in this array are applied globally, styles.css is the only one by default.
angular.json
"styles": [
"src/styles.scss",
"src/app/my.component.global.css"
],
If you're using scss, you can import this file into styles.scss instead of adding it to the styles array.
Now for actually moving the icon, I'm just using the non-svg icon but it should work the same
<mat-form-field>
<input type="tel" matInput placeholder="Home" />
<mat-icon class="mdi-icon">home</mat-icon>
</mat-form-field>
I removed matSuffix
app-my .mdi-icon {
position: absolute;
right: 0;
top: 5px;
}
In some cases you will be overriding other css already present in the child, to do that, you may need to increase the specificity by repeating a class (not necessary in this case)
app-my .mdi-icon.mdi-icon.mdi-icon {
position: absolute;
right: 0;
top: 5px;
}

Related

ng-deep not working when switching between components?

I have 2 components A B , in each component's css file I have a ngx-bootstrap datepicker which i need to customize ( align ).
In A component css file I have
::ng-deep .bs-datepicker {
margin-top:-100px
}
In B component css file I have
::ng-deep .bs-datepicker {
margin-top:-80px
}
When I go to component A and inspect element it shows A's css file, which is what i want,
But when go to component B and then come back to component A , It shows B's Css file in Component A, so it shows margin-top:80px in Component A.
How do I segregate styling between these two components without one affecting the other when i switch from one component to other?
You can wrap the bs-datepicker in a container and use it name to capture
::ng-deep .container-one * .bs-datepicker {
margin-top:-100px
}
::ng-deep .container-two * .bs-datepicker {
margin-top:-80px
}
and in HTML files:
<div class="container-one">
<input type="text" bsDatePicker>
</div>
<div class="container-two">
<input type="text" bsDatePicker>
</div>
Those will have different styling
I also recommend stopping using ::ng-deep to prevent unexpected behaviours (just like you had in this situation).
The approach above will also work on styles.scss file without the ::ng-deep with the correct angular.json configuration

how to use angular material form field and flex-layout

I want to have 2 form input fields in one row:
1. the first has a fixed with,
1. the second should grow and shrink, but this does not shrink below 180px.
Here is a full stack-blitz example
When you start the app, we see this
There maybe another issue:
I think the 2nd input field should already show the hint text and the horizontal line - but it will only show it when it get's the focus.
Is this the expected behaviour or am I missing something?
Anyway. The main issue is that the 2nd field does not shrink as expected. It will not shrink below 180px:
In the chrome dev-tool I can see that the input element is wrapped with a div class="mat-form-field-infix"> and the class mat-form-field-infix has a fixed width of 180px!
The only workaround that I came up with is to override this width with using ::ng-deep.
You can activate this in the co-input-field.component.scss file of the Stackblitz example
:host ::ng-deep .mat-form-field-infix {
// width: auto !important;
width: unset !important;
}
With this workaround the 2nd input shrinks as expected:
But ::ng-deep is deprecated and will be removed.
So what is the right way to make the input shrink as expected?
since .mat-form-field-infix has a fixed width of 180px there is no way of making form field shrink beyond 180px. inevitably .mat-form-field-infix must be overridden.
you can achive the same result with ::ng-deep in a couple of ways;
1.disable view encapsulation for that particular component. However, this approach has a huge drawback that all the styles in your component becomes global so they need to be managed carefully.
#Component({
selector: 'app-co-input-field',
templateUrl: './co-input-field.component.html',
styleUrls: ['./co-input-field.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CoInputFieldComponent {}
and then in co-input-field.component.scss you do the following
app-co-input-field {
.mat-form-field-infix {
width: auto !important;
}
// all other component styles goes in here
// in order to keep them isolated from global scope
}
2.don't disable view encapsulation. use the element selector of parent component in global styles.
put the following in styles.scss
app-co-input-field {
.mat-form-field-infix {
width: auto !important;
}
// co-input-field.component.scss still can be used for encapsulated styles
}
3.don't disable view encapsulation. define a global rule for this particular situation.
put the following in styles.scss
.shrinking-mat-form-field {
.mat-form-field-infix {
width: auto !important;
}
}
and apply the .shrinking-mat-form-field class to corresponding element
<mat-form-field style="width: 100%" class="shrinking-mat-form-field">
<input matInput placeholder="placeholder" />
<mat-hint align="end">hint text</mat-hint>
</mat-form-field>
Even though second and third approaches are fundamentally same I personally prefer the third approach in order to make it readable, keep it consistent over the project, have minimal side effects and manage them from a single point.
:host ::ng-deep.mat-form-field-appearance-legacy .mat-form-field-infix {
padding: 0.4375em 0;
display: flex;
}

Applying CSS stylesheet only to active component

I'm working on a ReactJS app that has a header at the top, a menu on the left, and the "frame" in the middle is where routes and their corresponding components are loaded. I want to be able to apply a CSS stylesheet to specific components only when they are loaded. I also don't want them applied all the time or to the top header or left menu.
My expectation was that adding import 'custom.css'; to a specific component would only apply the stylesheet's styles to that component and it's children when the route is active. Instead, it applies it to the entire page even when the route/component are not loaded.
I understand that an alternative approach is styled components, but, for my use-case, a design company is supplying a stylesheet (which should remain unchanged) that we need to consume only for the sub-module I'm working on and I don't want its styles to affect the rest of the app.
How can I have a stylesheet only applied to my active route/component?
Use simple CSS technique. Suppose you have two components with different css files (say about.css and contact.css). Now consider your both CSS file have one common class with different style properties, like:
about.css
.container{
max-width: 400px;
}
contact.css
.container{
max-width: 500px;
}
Yes in ReactJS both the CSS files will load at the same time and will override any one of the style. so to solve this problem add class to differentiate this styles, like:
about.css
.about-component.container{
max-width: 400px;
}
contact.css
.contact-component.container{
max-width: 500px;
}
If you want apply only when the component is mounted, you can use the lifecycle.
The follow example is based in the idea you are using sass, React, sass-node and have the loaders into webpack.
<pre>
import React from 'react';
import './styles.scss';
class MyComponent {
constructor(props) {
super(props);
this.state = { className: '' }
}
componentDidMount() {
this.setState({
className: 'myOwnClass'
});
}
render(){
return (
<div className={this.state.className}>This is a example</div>
);
}
}
export default myComponent;
</pre>
To be able to only call that specific CSS when you need it you can use CSS Modules. You may need to update your version of react.
When saving your CSS file save it with a ".module.css" eg. "styles.module.css". The CSS in these files can only be used and accessed by hte components where are they are imported. As stated in a tutorial from W3Schools.
Let's say this is your CSS code in styles.module.css:
.container {
color: white;
}
.cont-child {
background-color: red;
}
Then in your JS file you can import the CSS file like this if the JS and CSS files are in the same directory. Make sure you point to the correct path.
import styles from './styles.module.css'
Then in your HTML section you can use it like this:
class Home extends React.Component {
render() {
return(
<main className={ styles.container } >
<div className={ styles["cont-child"]} >
Some div text about something...
</div>
</main>
);
}
}
I currently use both ways to access the selectors, since the styles variable acts like an object. I placed both of them here because the second option is capable of fetching selectors named like "btn-active". Which comes in handy in some situations. Camelcasing is considered cleaner though.
Please note: I originally posted this answer as a reply to a similar question here React CSS - how to apply CSS to specific pages only
I want to be able to apply a CSS stylesheet to specific components
only when they are loaded.
Why not apply the styles inline via React.js?
Step 1. Create the style object for the component:
var componentOneStyle = {
color: 'white',
backgroundColor: 'red'
};
Step 2. Populate the component's style attribute with the style object:
ReactDOM.render(<div style={componentOneStyle}>This is Component One</div>, mountNode);

Change styling on hover semantic-ui-react components

if I set up a className for certain components like
<Segment className="Change" color='blue' inverted></Segment>
and in my css I use
.Change:hover{
background-color: black; //or any other change on hover
}
nothing is overriden on the hover.
I have also noticed there are many other components that refuse changes of mine, seemingly randomly. One semantic component will let me change a width the next will not. Is the cause from the same issue? How do I override the color on a hover?
After reviewing the source code of Segment Component (github), I found it has two default classes: segment and ui. In addition, you used two props color=blue and inverted. So I would recommend using the following code.
.ui.segment.blue.inverted.Change:hover {
background-color: black !important;
}
Working DEMO
Choose any color semantic-ui provide for example:
<Form>
<Form.Input label="Email" type="email" />
<Form.Input label="Password" type="password" />
<Button color="teal" type="submit">
Sign In
</Button>
</Form>
Your button appears like:
You can add inverted props inside Button component that react semantic-ui provide
<Form>
<Form.Input label="Email" type="email" />
<Form.Input label="Password" type="password" />
<Button inverted color="teal" type="submit">
Sign In
</Button>
</Form>
your component appears like:
On hover returns to basic style opposite of inverted
styled components usage with react semantic ui
I recommended you to use styled-components in order to override semantic-ui component style
import { Tab, Form, Button, Grid, Icon } from "semantic-ui-react";
import styled from "styled-components";
const Mybutton = styled(Button)`
&:hover {
color: #fff !important;
}
`;
Next use your new styled component instead of semantic-ui
<Mybutton inverted color="teal" type="submit">
Sign In
</Mybutton>
Because you didn't provide more code, hard to guess what overriding style you try to change. Try to add !importanant rule to this style.
.Change:hover {
background-color: black !importanant;
}
To avoid !important, which is not always a good solution, add a more specific CSS selector, for exaple Segment.Change:hover.
UPDATE:
Try to remove color='blue' from the template and check if will work with and without !important rule.

Add custom styling to ion-select

I have a ion-select with few options i gave a header using [selectOptions], is there a way to define a css so that i could able to set background-color to header, button alignment ,and add a icon to the header
<ion-select [selectOptions]="daysOptions" #selectDays="ngModel" required name="selectedDay" [(ngModel)]="selectDay" >
<ion-option *ngFor="let day of Days;" [value]="day.val">{{day.name}}</ion-option>
</ion-select>
could someone help me
You can fix this easily now
Add to ion-select element:
[interfaceOptions]="{cssClass: 'my-class'}"
Add to css:
.my-class .alert-wrapper {
max-width: 94% !important;
}
Yes, you can use cssClass in option like this:
// In your component
daysOptions = {
cssClass: 'my-class',
...,
}
Then in css you can do what you want eg:
.my-class .alert-wrapper {
max-width: 94% !important;
}
Thank's to ionic docs: https://ionicframework.com/docs/api/components/alert/AlertController/#advanced
I needed a color selector couple of months ago but I couldn’t find any.
The only way to do this was using custom CSS. I tried adding CSS classes to ion-select and ion-option but the classes doesn’t get reflected in the generated output. So the only way to apply the custom CSS to ion-select and ion-options is by using the parent element and some JS.
You can check the logic in:
HTML:
https://github.com/ketanyekale/ionic-color-and-image-selector/blob/master/src/pages/home/home.html
TS:
https://github.com/ketanyekale/ionic-color-and-image-selector/blob/master/src/pages/home/home.ts
SCSS:
https://github.com/ketanyekale/ionic-color-and-image-selector/blob/master/src/pages/home/home.scss

Resources