target first-child css styled-components - css

I am using styled-components and want to target the first child of Text, but am unable to do so.
const Text = styled.p`
font-size: 12px;
&:first-child {
margin-bottom: 20px;
}
`;
... component
return(
<div>
<p>I am just regular text</p>
<p>Me too</p>
<Text>Hello Joe</Text> // this should have the margin bottom
<Text>Goodbye</Text >
</div>
)

Finally, I got your issue. The styled component confuses with the first two native p tag (from my perspective) and that's the reason why the CSS is not applied.
I will use a workaround like this:
const Text = styled.p`
font-size: 12px;
color: blue;
&:nth-child(3) {
margin-bottom: 20px;
color: red !important;
}
`;
By doing this, you are selecting the third child (which include the first two p tag) for the CSS
OR, you can do something like this: Adding a class name for the tag and giving CSS for that class.
const Text = styled.p`
font-size: 12px;
color: blue;
&.colors {
margin-bottom: 20px;
color: red !important;
}
`;
<div>
<p>I am just regular text</p>
<p>Me too</p>
<Text className="colors">Hello Joe</Text>
<Text>Goodbye</Text>
</div>
Here is the demo
Hope it helps :)

Use like this
const Text = styled.p`
font-size: 12px;
> * {
&:first-child {
margin-bottom: 20px;
}
}
`;

There shouldn't be a space between the & and the :first-child
&:first-child {
margin-bottom: 20px;
}

it's better to use :last-of-type on certain styled component instead of using :nth-child and it works perfectly
export default styled.div`
:last-of-type {
background: red;
}`
const Text = styled.p`
font-size: 12px;
color: blue;
&:nth-child(3) {
margin-bottom: 20px;
color: red !important;
}
`;

This is possible, but probably not correct
This totally is possible, as we see with the other answers. The issue is that with first-child or nth-child solutions you tend to end up reaching down the DOM hierarchy, creating all sorts of specificity issues that can be difficult to untangle later.
The beauty of Styled Components is you typically apply styles to the element itself, meaning your styles stay tightly coupled to your components. Components become portable, and it's easy to find the line of CSS that might be causing an issue in a complex app.
for example, if I were to style the first <a> in a list item in a ul differently, I'd need to put :first-child further up the hierarchy, breaking encapsulation.
Treat your styles as a function
The simple solution to this is to recognise that the styled component is a function that can receive parameters:
<StyledListItem index={index} />
Then receive that parameter in the component:
export const StyledListItem = styled.li<{index?: number}>`
${
({index}) => {
if (index === 3) return `
color: red;
border: 2px dotted pink;
`
if (index === 0) return `
border-left: none
`
}
}
`
CSS in JS facilitates these kinds of programmatic solutions, and your life will be easier if you leverage them.

Related

Add Underline When Hover in React and CSS

How do I add a underline in text-decoration when hovering the text?
Seems this is correct but it still doesn't work
CLICK HERE
<span
style={{
color: "red",
cursor: "pointer",
"& :hover": {
textDecoration: "underline"
}
}}
>
Click this.
</span>
The style property doesn't support selectors.
You need to move your logic into a <style> element or a <link>ed stylesheet.
There are plenty of React-friendly libraries for generating them on-the-fly for you. Styled Components is a popular tool for this which supports the SCSS syntax you are (almost — you have a rogue space after the &) using.
import { styled } from 'styled-components';
const MySpan = styled.span`
color: red;
cursor: pointer;
&:hover {
text-decoration: underline;
}
`;
and then
<MySpan>Click this.</MySpan>
However, span elements are not designed to be interactive. They are not announced as clickable by screen readers and you can't tab to them if you aren't using a mouse. This is a major accessibility barrier. If you want something for the user to click on, use a link (if you are linking somewhere) or a button (otherwise).
According to here:
There has been plenty of valid points made that react inline style is not a good idea. No support for CSS selectors like “:hover”, “:active” “:focus”, “:before” and “:after”, media queries, nor for SCSS syntax, to name a few.
Just use a css file and implement it there with class:hover
try this, I Tried it and it works.
App.js:
import "./styles.css";
export default function App() {
return (
<div className="App">
<span
style={{
color: "red",
cursor: "pointer"
}}
>
Click this.
</span>
</div>
);
}
style.css:
.App {
font-family: sans-serif;
text-align: center;
}
span:hover {
text-decoration: underline !important;
color: "red";
}

Styling Material UI Button

Hi I just started using Material UI and am having a hard time styling the components. I am building a sign in page and would like my Submit button to be all the way to the bottom right. If someone can help me out that would be greatly appreciated because it seems to be inheriting styles from everywhere else but where I would like to!
I have tried adding
textAlign: 'right'
to buttonStyle and that does not work. I have also tried adding
text-align: right;
to my .form-button CSS.
The only thing that affects anything is removing the .App
Login.js
<div className='form-container'>
...
<Button
style={buttonStyle}
className='form-button'
variant='contained'>
Log-In
</Button>
</div>
...
const buttonStyle = {
backgroundColor: '#527354'
};
App.css
.App {
text-align: center;
}
.form-button {
width: 83px;
height: 36px;
box-shadow: 0px 1px 3px #00000033;
}
.MuiButton-label {
color: var(--primary-white);
font-family: 'Open Sans', sans-serif;
}
.form-container {
max-width: 400px;
margin: 2rem auto;
overflow: hidden;
padding: 0 2rem;
}
Another main goal would be to avoid inline styling because I do prefer keeping it within my style sheet. But if not possible or too overly difficult, I will inline style (as I did with the background-color).
As keikai has mentioned in the comment, you may check the Documentation in this link material-ui.com/styles/basics for overriding style.
For 'it seems to be inheriting styles from everywhere else'
I will suggest you to use styled-components instead of global css import, which mess up everywhere. Try this,
npm install --save styled-components
It creates a css class that only apply to the component.
Sample code:
import styled from 'styled-components'
const MyDiv = styled.div`// can be span, section, etc
// add your style here for the div
your div style(optional)
// your class css inside the div
.form-container {
max-width: 400px;
margin: 2rem auto;
overflow: hidden;
padding: 0 2rem;
}
// add more class if you have any
`
Then wrap your component with
// your newly created styled div
<MyDiv>
// component that needs your style
<MyComponent />
</MyDiv>
Your style will only be applied to MyDiv and MyComponent, and nothing else.
It may took awhile to get used to it, but it is extremely useful.

CSS hover modify self and other class

I know there are a ton of answers on :hover effecting other classes. What I'm trying to do is change the font color of itself (.footer_status_tex) and background-color of another class (.footer_status_gear)
Simplified CSS - Something like this:
CSS
.footer_status_tex {
cursor: pointer;
color: #fff;
}
.footer_status_gear {
width: 36px;
height: 36px;
background-color: #000;
}
.footer_status_tex: hover {
color: #81aaf3;
}
.footer_status_tex:hover .footer_status_gear {
background-color: #aba51e;
}
HTML
<div class="footer_status_tex" style="">Hello</div>
<div class="footer_status_gear"></div>
Current setup only changes font color.
Thanks
First, you need to fix the selector .footer_status_tex: hover, remove the gap after :.
Second, the selector .footer_status_tex:hover .footer_status_gear only works if the latter one is a child of the former one.
What you need is .footer_status_tex:hover + .footer_status_gear or ~ if the latter one is a sibling of the former one, also the latter one must be placed next to the former one in the DOM.
.footer_status_tex:hover {
color: #81aaf3;
}
.footer_status_tex:hover + .footer_status_gear {
background-color: #aba51e;
height: 20px;
}
<div class="footer_status_tex">Hello</div>
<div class="footer_status_gear"></div>
You can use ~ adjacent selector to target the adjacent elements
Stack Snippet
.footer_status_tex {
cursor: pointer;
color: #fff;
}
.footer_status_gear {
width: 36px;
height: 36px;
background-color: #000;
}
.footer_status_tex:hover {
color: #81aaf3;
}
.footer_status_tex:hover ~ .footer_status_gear {
background-color: #aba51e;
}
<div class="footer_status_tex" style="">Hello</div>
<div class="footer_status_gear"></div>
When posting CSS problems, please also include the associated HTML code as without it, we're can only assess half the problem.
I'm assuming this is your structure: https://codepen.io/barrymcgee/pen/vdGOra?editors=1100#
The reason why the background of .footer_status_gear doesn't change is because it's the parent element of the link. A :hover pseudo-class can only direct the children of the element to which it is applied.
If the assumption I made about your HTML structure is wrong, please provide it and I'll look again.

Apply CSS rules based on other rule - RTL specific style

Presentation
I'm trying to build a web site available in multiple cultures, with different reading direction.
To do so, I simply add the dir="rtl" attribute on my root HTML element.
My issue is that I have some CSS rules that are specific to one direction or the other (margins or paddings, most of the times).
Unsuccessful try with attribute selector
I though that I could simply use the attribute selector but the dir attribute is only set on the root element, so this wouldn't work :
selector {
&[dir="ltr"] {
// LTR specific
}
&[dir="rtl"] {
// RTL specific
}
}
For instance, on this demo, the title should have a margin of 5px on the right if the application is in rtl or on the left if it's in standard ltr.
Other idea
I've noticed that the direction is rightfully set at rtl, is there a way to use that rule within a CSS or Sass selector ?
Edit and precisions
It seems that I've forgotten an important point. I'm building the web site using Vue.js, the dir attribute is bind in the main component (App) and the RTL/LTR specific CSS rules can be in the same component or in other self-contained component.
Following your css code you could do this with SASS at-root directive DEMO. So this:
#app {
width: 300px;
height: 100px;
border: 1px solid red;
h1 {
#at-root {
[dir="rtl"]#{&} {color: green}
}
#at-root {
[dir="ltr"]#{&} {color: red}
}
}
}
It will compile to this css.
#app {
width: 300px;
height: 100px;
border: 1px solid red;
}
[dir="rtl"]#app h1 {
color: green;
}
[dir="ltr"]#app h1 {
color: red;
}
You could style everything LTR, and only adjust some elements styling for RTL. Might this work for you?
[dir="rtl"] {
&selector {
// RTL specific
}
&selectorN {
// RTL specific
}
}
Use below scss to get expected output
#app {
width: 300px;
height: 300px;
background: red;
&[dir="ltr"] h1{
margin-left: 10px;
}
&[dir="rtl"] h1 {
margin-right: 10px;
}
}
Probably you are going a little in the wrong direction.
Most of the time, you can achieve this automatically, no need for specific selectors.
Margin, for instance:
Just set it both for left and right margin. The browser will choose the correct one for you
#app {
width: 300px;
background: tomato;
margin: 10px;
}
h1 {
margin-left: 15px;
margin-right: 5px;
}
<div id="app" dir="ltr">
<h1>
margin left 15
</h1>
</div><div id="app" dir="rtl">
<h1>
margin right 5
</h1>
</div>

Styled-components: Interpolated function or component.extend?

In styled-component, how do you decide whether you should use interpolated function to modify component ( by passing props ) or extend the existing component. For example:
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;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
We could have used interpolated function also. How do you decide between the two?
It different, by passing a props we can use it in other situation but if using extends we just use it as an extra style for a new component something like inherit. Example: for nav menu, if there is an active menu, you dont need to use extends. Just use active class using props.So you dont need to do extend or make new component.

Resources