Why won't the JSX CSS be applied? - next.js

I'm working off of the documents from the "Learn" section on the Next.js website.
The CSS below does not get applied to the component if using the jsx style tag; however, if I add the CSS as an object literal attribute it gets applied. How can I to get the jsx style tag CSS to be applied?
This won't be applied:
import Layout from "../components/Layout";
export default function Post() {
return (
<Layout>
<div className="container"> This is a div. <div/>
// This wont be applied
<style jsx>{`
.container {
margin: 20;
padding: 20;
border: "1px solid #DDD;
}
`}</style>
</Layout>
);
}
But this works:
import Layout from "../components/Layout";
const layoutStyle = {
margin: 20,
padding: 20,
border: "1px solid #DDD"
};
export default function Post() {
return (
<Layout>
<div className="container" style={layoutStyle}> This is a div. <div/>
</Layout>
);
}

When using the object attribute the unit is not supplied and the border field value is in quotes.
const layoutStyle = {
margin: 20,
padding: 20,
border: "1px solid #DDD"
};
For it to work with JSX CSS it needs to be normal CSS syntax!
.container {
margin: 20px;
padding: 20px;
border: 1px solid #DDD;
}

Try this:
<style>{`
.container {
margin: 20;
padding: 20;
border: 1px solid #DDD;
}
`}</style>

This is not a good approach if you are using the next js on your website. You should use the next css in your project that is so easy to use and maintain your CSS files as well.
Here is a documentation link to use next css.
https://github.com/zeit/next-plugins/tree/master/packages/next-css

Related

How to select multiple components at once with Emotion?

I have the following styled elements:
const LogoSide = styled.div``
const NavSide = styled.p``
const Nav = styled.nav`
position: absolute;
right: 0;
top: 0;
width: 100%;
${LogoSide} {
width: 200px; // <-- How to combine those ?
};
${NavSide} {
width: 200px; // <-- How to combine those ?
}
`
And I would like to be able to use the same CSS properties for multiple elements, something like this :
const Nav = styled.nav`
position: absolute;
right: 0;
top: 0;
width: 100%;
${LogoSide} ${NavSide} {
width: 200px;
};
`
Is there a way to achieve this ?
I looked at the docs but could not find what i'm looking for.
Just put a comma between the components and it will work. You won't find it in the documentation is works just like in plain CSS when you combine classes. But for correct work you need to use Macro.
All of Emotion's Babel Macros are available by adding /macro to the end of the import you'd normally use. Docs
import styled from "#emotion/styled/macro";
const NavSide = styled.p`
border: 2px solid red;
`;
const LogoSide = styled.div`
border: 2px solid red;
`;
const Nav = styled.nav`
position: absolute;
right: 0;
top: 0;
width: 100%;
${LogoSide}, ${NavSide} {
width: 200px;
}
`;
You can use the css prop to help with creating reusable, composable styles.
Note that you'll need to configure the JSX import source using this technique, so be sure to read the documentation I linked above.
If you're using create-react-app, and you don't feel confident after reading the docs, then you can probably just add /** #jsxImportSource #emotion/react */ at the top of each of your modules which have components that use the prop to take care of it.
Using it is pretty straightforward:
/** #jsxImportSource #emotion/react */
import {css} from '#emotion/react';
// Use this in any element's `css` prop:
const bold = css`
font-weight: bold;
`;
const red = css`
color: red;
`;
const boldRedUppercase = css`
${bold};
${red};
text-transform: uppercase;
`;
export function Component () {
return (
<p>
<span css={bold}>This</span> is bold and <span css={[bold, red]}>this</span> is bold red, and <span css={boldRedUppercase}>this</span> is bold red uppercase!
</p>
);
}

How to call SCSS 'parent selector reference &' to react css module?

This is my SCSS style for .br
.br {
&--red {
border: 2px solid red;
}
&--green {
border: 2px solid rgb(32, 170, 8);
}
}
This is my nextjs react code:
import layout from "../styles/layout.module.scss";
export default function Index() {
return (
<div className={layout.br}>
<h1>Khan</h1>
</div>
);
}
How to access this ".br--red" in jsx?
.br{
&--red{
border:2px solid red;
}
}
If you use dash in an object's properties name(in this case, it's class name), for use of it you must use Bracket notation, and your property name should be in ' '(quotation or double-quotation).
<div className={layout['br--red']}>
<h1>Khan</h1>
</div>
You can read more about it in this article.
Adding on the comment above, you can also use dynamic variable in the brackets like so using backticks.
className={styles[`br--${color}`]}

Apply CSS styles on html tags after create them dynamically (inside .ts file)

I'm trying to add DIV after the project run (add it dynamically) but the problem is it didn't take the CSS style that I've set to it.
import { Component, OnInit, AfterViewInit } from '#angular/core';
#Component({
selector: 'app-chat2',
templateUrl: './chat2.component.html',
styleUrls: ['./chat2.component.css']
})
export class Chat2Component implements OnInit,AfterViewInit {
messages = [];
totalOnline = 0;
user = 1;
constructor() { }
ngOnInit() {
}
ngAfterViewInit(){
const divMessages: HTMLDivElement = document.querySelector(".msg_history");
let m = document.createElement("div");
m.innerHTML =
`<div class="incoming_msg">
<div class="incoming_msg_img" > <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="received_msg">
<div class="received_withd_msg">
<p>Abdulaziz Burghal , Hello from Chat</p>
<span class="time_date"> 4:53 AM | June 9</span></div>
</div>
</div>`;
divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
}
}
Note: div that I've created it inside HTML file took the CSS style without any problem .
So, how could apply the CSS style on div's that I'll create them by code
Update:
Added CSS
.incoming_msg_img {
display: inline-block;
width: 6%;
}
.received_msg {
display: inline-block;
padding: 0 0 0 10px;
vertical-align: top;
width: 92%;
}
.received_withd_msg p {
background: #ebebeb none repeat scroll 0 0;
border-radius: 3px;
color: #646464;
font-size: 14px;
margin: 0;
padding: 5px 10px 5px 12px;
width: 100%;
}
Update 2
when I add the CSS styles as inline style it's work but the problem is the Div that contains the image it's CSS doesn't work!
You can apply the css in a few ways.
Via css
It's not clear why the css style isn't working, if you post it we can probably help more. Are you targeting the div or class of your dynamicly created html in the css?
Dynamically in JS
You'll have to get the element in JavaScript, either by using the m element you have or attaching a unique id to one of your elements.
const el = document.getElementById("${unique id})
Then you can set the style
el.style.cssText = "${your style text}"
If you use angular way to fill your list the CSS will work:
HTML
<div class="inbox_chat">
<div class="chat_list active_chat" *ngFor="let userData of listOfUsers">
<div class="chat_people">
<div class="chat_ib">
<h5>{{userData.userName}} <span class="chat_date">{{userData.creationDate}}</span></h5>
<p>{{userData.messageText}}</p>
</div>
</div>
</div>
</div>
TypeScript part:
listOfUsers: Array<InboxChatBoxDto> = [];// define it gloably
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
this.listOfUsers=result;
// });
});
}
If you use javascript to build your HTML you need to use an inline CSS property:
HTML part
<div class="inbox_chat"></div>
TypeScript part (use javascript code within it):
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
const divMessages: HTMLDivElement = document.querySelector(".inbox_chat");
result.forEach((item,index)=>{
let m = document.createElement("div");
m.className="chat_list"
m.style.cssText=` border-bottom: 1px solid #c4c4c4;
margin: 0;
padding: 18px 16px 10px;`
m.innerHTML = `<div class="chat_people" style='overflow:hidden; clear:both;' >
<div class="chat_ib" (click)="fillMessageHistory(`+item.userId+`)">
<h5 style='font-size:15px; color:#464646; margin:0 0 8px 0;'>` + item.userName +`<span class="chat_date" style='font-size:13px; float:right;'>`+ moment(item.creationTime ).format('YYYY/MM/ddd') +`</span></h5>
<p style='font-size:14px; color:#989898; margin:auto'>`+ item.messageText+`</p>
</div>
</div>`;
divMessages.appendChild(m);
});
});
}

Change styles of parent on hover only if children not focused - Styled components

I have a div component:
const Parent = styled.div`
&:not(${Input}:focus):hover {
border-color: blue;
}
`;
and child which is input
const Input = styled.input``;
As you can see, I dont want to change border-color on Parent, if Input is focused. However atm the :hover doesnt work at all. Looking for help, thanks!
You can leverage :focus-within to do that.
div {
padding: 1em;
margin: 2em;
display: inline-block;
border-width: 3px;
border-style: solid;
}
div:hover {
border-color: red;
}
div,
div:focus-within,
div:focus-within:hover {
border: 3px solid blue;
}
<div>
<input type="text">
</div>
I don't know how you can handle it with only selector css, but you can trick it with javascript.
Your styled-component :
const Input = styled.input``
const Parent = styled.div`
border: 1px solid blue;
:hover {
border-color: ${p => p.inputFocus ? "blue" : "yellow"};
}
`
and in your render you can handle a state focus of you input.
render :
state = {
inputFocus: false
}
setFocus = () => this.setState({inputFocus: true})
unsetFocus = () => this.setState({inputFocus: false})
render() {
const { inputFocus } = this.state
return (
<Container inputFocus={inputFocus}>
<Input
onBlur={this.unsetFocus}
onFocus={this.setFocus}
/>
</Container>
)
}

How to extend(inherit) a global CSS class from within a styled-components

Is it possible to inject a global CSS class into a styled-component?
Similar to extending in LESS using &:extend or #extend in SASS.
This code doesnt apply the globalCSS styles:
const extendedComponent = styled.div`
&:extend(.globalClass) // I want this component to inherit all styles of .globalaCSS
.otherStyles {
...
}
`
The globalClass does exits and even applies styles when used inline:
extendedComponent(className="globalCSS)
you can just add the "class name" to your element,
but if you really want to inherit or extend.
Use their example as reference:
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// We're extending Button with some extra styles
const TomatoButton = Button.extend`
color: tomato;
border-color: tomato;
`;
docs link:
https://www.styled-components.com/docs/basics#extending-styles
Use attrs: https://styled-components.com/docs/api#attrs
const extendedComponent = styled.div.attrs({
className: 'globalCssClassThatIWantToExtend'
})`
.otherStyles {
/*...*/
}
`;
The attrs function can also accept a props function:
.attrs(props => ({
/*...*/
}))

Resources