I thought I understood how modules worked but apparently not
I have nested scss/sass styles that I'm trying to apply on an element but when I add those multiple styles to my element it doesn't take any of the styles while other elements that only take one class do.
The generated class names are appearing but not the actual styling just to be clear
scss
.cell {
width: 22.5%;
display: flex;
justify-content: center;
flex-direction: column;
position: relative;
.iconColumn {
width: 10%;
}
}
jsx
<div classname={`${styles.cell} ${styles.iconColumn}`}> // this styling doesn't appear
<IconButton
size="small"
onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</div>
<div className={styles.cell}> // this styling appears
<Typography component="div" varient="h3">{row.label}</Typography>
</div>
// ...
how it appears in web browser
<div classname="NonTablePricingTable_cell__3OzOv NonTablePricingTable_iconColumn__2e9YO"> // the one that doesn't add the styling as per the class
<div class="NonTablePricingTable_cell__3OzOv"> // does add styling as per the class
You have a typo in className attribute. It should be in camel case and you have used small case.
Changing classname={`${styles.cell} ${styles.iconColumn}`} to className={`${styles.cell} ${styles.iconColumn}`} should fix the issue.
Related
In Ionic, the ion-title component has the content encapsulated in an extra div within its shadow-dom.
This div has the class .toolbar-title set. How can i select this div via scss-selector to change its overflow behavior?
I tried:
.toolbar-title { ... }
ion-title .toolbar-title
ion-title::shadow .toolbar-title { ... }
ion-title::shadow(div) { ... }
and a lot other combinations including :host & ::ng-deep selectors.
And, yes i know , ::shadow and ng-deep is deprectaded.
I also know that ionic has introduced css-variables for this purposes, but unfortunatley not for the overflow attribute.
THX in advance!
The concept of shadowDOM is you can't touch its content with CSS from the outside.
It is an open shadowDOM, so you can change it with JavaScript.
document.querySelector("ion-title")
.shadowRoot
.querySelector(".toolbar-title")
.style
.overflow = "initial";
Ionic v6 allows you to target and modify shadowDOM contents with CSS. See https://ionicframework.com/docs/theming/css-shadow-parts
However, the element you want to select inside the shadowDOM needs to expose a part attribute. For instance the ion-select element:
<ion-select>
#shadow-root
<div part="placeholder" class="select-text select-placeholder"></div>
<div part="icon" class="select-icon"></div>
</ion-select>
You can select the placeholder element with:
ion-select::part(placeholder) {
color: blue;
opacity: 1;
}
Unfortunately, the ion-title element does not expose any shadow parts. You need to wrap the contents of ion-title in a container to be able to modify them:
<ion-title>
<div class="content">
<img src="..." />
Hello World!
</div>
</ion-title>
CSS:
.content {
display: flex;
align-items: center;
}
StackBlitz example: https://stackblitz.com/edit/ionic-title-modification-8a1qst
I'm trying to modify the css color picker of a module, in order to adapt it to my website (align it to center).
Here's the code of the color picker:
#Component({
selector: 'color-circle',
template: `
<div
class="circle-picker {{ className }}"
[style.width.px]="width"
[style.margin-right.px]="-circleSpacing"
[style.margin-bottom.px]="-circleSpacing"
>
<color-circle-swatch
*ngFor="let color of colors"
[circleSize]="circleSize"
[circleSpacing]="circleSpacing"
[color]="color"
[focus]="isActive(color)"
(onClick)="handleBlockChange($event)"
(onSwatchHover)="onSwatchHover.emit($event)"
></color-circle-swatch>
</div>
`,
styles: [
`
.circle-picker {
display: flex;
flex-wrap: wrap;
}
`,
],
I'm using justify-content: center to the class circle-picker to align it, but nothing happens, so I don't really know if I'm able to do it.
Here's how I use the selector:
<color-circle [colors]="colors" [color]="productForm.get('color')?.value" (onChange)="onColorChanged($event)" width="190px" circleSize="34" circleSpacing="18"></color-circle>
When I inspect the code with the browser, I can make it, but with the CSS file nothing works.
Could anyone help?
This is what I want:
This is what I have:
Author of the color picker:
https://github.com/scttcper/ngx-color
If you want to set style to elements inside your host component. you must use :host
and to change deeper elements you have to use ::ng-deep
Use
:host color-circle ::ng-deep color-circle-swatch{
justify-content: center;
align-items:center
}
May be this two line of code can fix your problem
.color-circle-swatch{
margin: 0 auto;
width:100%;
}
I'm trying to style a component in my React application, but I do not want to create an external stylesheet because it's a small project. How can I style this image component without using an external stylesheet?
return (
<div>
<Image>
<div>
<img src='./resources/image.png alt='image'>
</div>
</Image>
</div>
);
I've found resources online for using inline styling on a specific element, but I want to make my code clean by putting it at the top of the component like using a style tag at the top of an HTML file. I haven't been able to find anything that resembles this in React.
For inline styles you can define a style object, either at the top of the file, or in your render method, and then refer to it:
var myStyle = { margin: 10 }
return (
<div>
<Image>
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
</Image>
</div>
)
More info in the docs: https://reactjs.org/docs/dom-elements.html#style
Internal CSS styling in JSX is very similar to how it's done in HTML. The only difference is that you need to declare the style names as variables because they are treated like JS objects. With this in mind, you also need to end each property with a comma instead of a semicolon, and the last property should have no punctuation at the end. Using this approach, you should also use style={} instead of className={}. You can read more about JSX styling here.
const myStyle = {
width: '300px',
height: '300px',
border: '2px solid black'
}
const Image = () => {
return (
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
);
}
You can do something like this:
const Image = styled.div`
background: #1d9ac2;
img {
border: 1px solid red;
}
`;
There are several solutions for this, and a big debate about which one is "the best".
I don't know which one is the best, but I can tell you which one I use:
Styled components (https://www.styled-components.com/)
With this, you would define an object like this
let styled = require('styled-components');
// Or for fancy people
import styled from 'styled-components';
const Image = styled.div`
background-color: red;
/* You can even put classes or selectors in here that will match the sub-components */
.some_class_used_inside { color: black; }
img { width: 100px }
`
and use it like this
return (
<div>
<Image> {/* This will be the `<div>` with `background-color: red` */}
<div className="some_class_used_inside"> {/* This will now have `color: black` applied */
<img src='./resources/image.png alt='image'> {/* This will have `width: 100px` applied to it */}
</div>
</Image>
</div>
);
Ofcourse, there are many other libraries to do it, and everyone will have to find their own favorite I guess :)
I am having trouble getting my styled component to make a change to an <input /> wrapped in a React component. In Dev Tools I can see the style I am trying to override here:
.ui.input input {...}
I think the wrapping component needs to pass className to input i.e
<input className = {this.props.className} ..> ... </input>
but I cannot get the style to override with or without that. I will provide some snippets below.
//styled component
const StyledSearch = styled(Searchbar)`
&.ui.input input{
border: 0px !important;
}
`;
class SearchBar extends Component {
...
render() {
const style = {
display: this.state.showResults ? 'block' : 'none',
maxHeight: 500,
overflowY: 'scroll',
};
return (
<div className="ui search fluid" ref="container">
<div
className={`ui icon fluid input ${this.props.loading ? 'loading' : ''}`}>
<input type="text"
placeholder={this.props.placeholder}
onFocus={this.focus}
className = {this.props.className}
value={this.props.value}
onChange={this.props.onChange}/>
<i className="search icon"></i>
</div>
<div
className="results"
style={style}>
{
this.props.results.map((result, index) => (
<a
className="result"
key={index}
onClick={this.select.bind(this, result)}>
<div className="content">
{
result.get('image') ?
(
<div className="image">
<img src={result.get('image')} style={{ maxWidth: 50 }}/>
</div>
) : null
}
<div className="title">
{result.get('title')}
</div>
<div className="description">
{result.get('description')}
</div>
</div>
</a>
)
)
}
</div>
</div>
);}}
Basically, styled-components creates a new unique class name (in other words, a new namespace) for any DOM or React Components for which the styled function is called.
That means, when you use styled(SearchBar), styled-components wraps SearchBar component and attaches a unique class name to its root DOM. Then it passes that unique class name to the descendent DOMs and components (in your cases, nested div, input, a).
For this method to work, your root DOM must have a className that can be configured from outside. That's why, styled-components expects that, root DOM has the definition ${this.props.className} as the value of its className props. If your component lacks this, styled-components will not be able to create a new namespace which it can use to apply styling specific to it.
So, for your technique to work, you must assign ${this.props.className} as one of the values of className prop defined at the root div of SearchBar.
Working Demo
If you don't have access to SearchBar, you can wrap it with another component. Overhead of this process is that, you have to use an extra DOM level
Working Demo
From what I can tell, you need to apply the styles generated with styled-components to the wrapper element. This is due to the specificity of the .ui.input input external style. Meaning we can't simply target the input element with a new style because the .ui.input input selector is more specific and takes precedence. Here's a simple CSS example showing how the specificity of the .ui.input input selector takes precedence over the input styling:
.ui.input input {
border:2px solid red !important;
}
input {
border: 0px !important;
}
<div class="ui input">
<input />
</div>
This same issue is at play in your case. In the example below I've created a new Wrapper component, which has a style of:
&.ui.input input {
border: 0px !important;
font-size: 24px;
}
defined on it. This targets the inner input element, with more specificity, to override the external styles.
import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
class InputWrapper extends React.Component {
render() {
const Wrapper = styled.div`
&.ui.input input {
border: 0px !important;
font-size: 24px;
}
`;
return(
<Wrapper className="ui input">
<input type="text" placeholder="Input" />
</Wrapper>
)
}
}
ReactDOM.render(
<InputWrapper />,
document.getElementById("app")
);
Here's a WebpackBin example.
Currently at version 4 you can do it as simple as
const Input = styled.input`
border:2px solid red !important;
`;
it will rendered as native input with SC className
With reference to this plunker:
https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview
I have the same css specified in the styles.css file, and in the src/app.ts file.
If I comment in the css in styles.css and comment out the css in src/app.ts, it works.
styles.css:
/* If these are commented in, and the ones in src/app.ts are
* commented out, the three items are spaced appropriately. */
/***
md-toolbar-row {
justify-content: space-between;
}
md-toolbar {
justify-content: space-between;
}
***/
If I comment out the css in styles.css and comment in the css in src/app.ts, it fails.
src/app.ts:
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<md-toolbar color="primary">
<span><md-icon>mood</md-icon></span>
<span>Yay, Material in Angular 2!</span>
<button md-icon-button>
<md-icon>more_vert</md-icon>
</button>
</md-toolbar>
</div>
`,
// If these are commented in, and the ones in style.css are
// commented out, the three items are scrunched together.
/***/
styles: [
`md-toolbar-row {
justify-content: space-between;
}`,
`md-toolbar {
justify-content: space-between;
}`
]
/***/
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
I'm having trouble visualizing the difference between defining the css for the whole application, and for the specific component. Can someone tell me what's going on?
=================================
#bryan60 and #Steveland83 seem to indicate that the problem lies somewhere in the view encapsulation. And upon further investigation, it does in a sense.
If you look at the code below, you will see that the styles for md-toolbar and md-toolbar-row have an attribute attached. But the html for md-toolbar and md-toolbar-row does not match. Only md-toolbar has the attribute attached. md-toolbar-row doesn't. I have marked the relevant four lines with >>>>>.
So that's the problem but:
1. Do I report it to the material design people as an error?
2. Is there some workaround I can use today?
<html>
<head>
:
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
<link href="https://rawgit.com/angular/material2-builds/master/prebuilt-themes/indigo-pink.css" rel="stylesheet">
<style>
>>>>> md-toolbar-row[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
>>>>> md-toolbar[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
.mat-toolbar {
display: flex;
: :
.mat-mini-fab,
.mat-raised-button {
outline: solid 1px
}
}
</style>
</head>
<body class="mat-app-background">
<my-app _nghost-c0="" ng-version="4.4.0-RC.0">
<div _ngcontent-c0="">
<h2 _ngcontent-c0="">Hello Angular! v4.4.0-RC.0</h2>
>>>>> <md-toolbar _ngcontent-c0="" class="mat-toolbar mat-primary" color="primary" role="toolbar" ng-reflect-color="primary">
<div class="mat-toolbar-layout">
>>>>> <md-toolbar-row class="mat-toolbar-row">
<span _ngcontent-c0=""><md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">mood</md-icon></span>
<span _ngcontent-c0="">Yay, Material in Angular 2!</span>
<button _ngcontent-c0="" class="mat-icon-button" md-icon-button=""><span class="mat-button-wrapper">
<md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">more_vert</md-icon>
</span>
<div class="mat-button-ripple mat-ripple mat-button-ripple-round" md-ripple="" ng-reflect-trigger="[object HTMLButtonElement]" ng-reflect-centered="true" ng-reflect-disabled="false"></div>
<div class="mat-button-focus-overlay"></div>
</button>
</md-toolbar-row>
</div>
</md-toolbar>
</div>
</my-app>
</body>
</html>
One of the Angular features is View Encapsulation which basically means that you can define styles scoped only to a specific component without affecting any other components.
By default styles are scoped only for the component they are referenced in, but you can choose to override that to make them available globally by setting your components encapsulation to None.
E.g.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'component-that-shares-styles',
templateUrl: './component-that-shares-styles.component.html',
styleUrls: ['./component-that-shares-styles.component.scss'],
encapsulation: ViewEncapsulation.None // <-- Set encapsulation here
})
*Note that you will need to import ViewEncapsulation from #angular/core
Okay, with help from #Steveland83 and #bryon60, I came to a definite answer. The Material Design people are aware of this problem. They have made a writeup.
https://github.com/angular/material2/blob/master/guides/customizing-component-styles.md
Here's their summary:
Styling other components
If your component has view encapsulation turned on (default), your component styles will only
affect the top level children in your template. HTML elements belonging to child components cannot
be targeted by your component styles unless you do one of the following:
Add the overriding style to you global stylesheet. Scope the selectors so that it only affects
the specific elements you need it to.
Turn view encapsulation off on your component. If you do this, be sure to scope your styles
appropriately, or else you may end up incidentally targeting other components elswhere in your
application.
Use a deprecated shadow-piercing descendant combinator to force styles to apply to all the child
elements. Read more about this deprecated solution in the
Angular documentation.
I don't want to use global css, or a deprecated solution. I guess I will style with classes, and not elements. If someone has a better idea, tell me!