Using nested pseudo css selectors with react-emotion - reactjs

Running on a strange problem.
Following are two blocks of code. One of them works well and another just don't.
This work
const StyledButton = styled('button')`
// Some styles here
:first-child {
// Some other styles
}
:first-child:after {
content: 'F';
}
`
// After get applied succesfully to the first child
This doesn't
const StyledButton = styled('button')`
// Some styles here
:first-child {
// some other styles
:after {
content: 'F';
}
}
`
// After get applied to all nth child.
I'm using react-emotion.
Is this behavior intended or am I missing something? I want to achieve that :after should get applied to first-child only by using a similar approach to the second one.

I think there's an error in the code on the nested :after
The change that would, if I'm correct, solve your issue it to change the nested :after to &:after like so:
const StyledButton = styled('button')`
// Some styles here
&:first-child {//<====== note the & here
// some other styles
&:after { //<====== note the & here
content: 'F';
}
}
}
The & is a placeholder for the parent selector, thus the code above will compile to:
button:first-child {
// some other styles
}
button:first-child:after {
content: 'F';
}
EDIT: Sandbox with working example
Hope this helps!
`

Related

Shorter way to use SCSS #exported classNames in React (Next.js + css-modules)

I have a set of semantic color classes in SCSS, which should be applied to components based on their props. I'm using React + Next.js + css-modules.
What I Want:
The current code I wrote below works correctly, but I want a simpler approach... declaring a bunch of classNames for every component to #extend something else is overkill! I want to write the extension directly in jsx part. Is there a better (more dynamic) way to do this? maybe inline extends?
Not a valid code, but I'm looking for something like this:
export default function Component({ status }) {
return (
<div style={#extend %{status}}>
...
</div>
)
}
Code
This is the semantics file. I import it inside other scss files to extend the classes:
/* _semantics.scss */
%warning {
background: orange;
color: red;
}
%error {
background: red;
color: black;
}
...
Example Component
/* component.module.scss */
#use "semantics" as *;
.warning {
#extend %warning;
}
.error {
#extend %error;
}
.success {
#extend %success;
}
// component.jsx
import css from "./component.module.scss"
export default function Component({ status }) {
return (
<div className={css[status]}>
...
</div>
)
}
// index.jsx
<Component status="warning">...</Component>
Notes
I am looking for an alternative way, so:
Using a package is fine
Using #include (mixins) instead of #extend is fine
Using .semantic-class instead of %semantic-class is fine
you can use global css to achieve this purpose

With Styled Components and Polish how to include a function as the color?

I'm using styled-components and polished for darkening/lightening the colors.
Here's what I have now working:
colors = ['#eee', '#ccc', '#ddd'];
const calcBorderColor = ({ currentPosition }) => {
const color = colors[(currentPosition) % colors.length];
return color;
};
const Choice = styled.button`
border-color: ${calcBorderColor};
`;
Where I'm stuck is here:
&:hover {
border-color: ${darken(0.1, calcBorderColor)};
}
That hover styling is error with Passed an incorrect argument to a color function, please pass a string representation of a color.
How can I use polished darken along with the calcBorderColor function?
You are only getting the error when using the darken function because it expects a string as second argument and instead you are passing the function declaration of calcBorderColor that if you log it, you could see is this:
calcBorderColor(_ref) {
var currentPosition = _ref.currentPosition;
var color = colors[currentPosition % colors.length];
return color;
}
If you:
console.log(typeof calcBorderColor);
You will get it is of type function.
This come because polished library functions are staticly typed by using Flow. And you are not getting an error in the first border-color because Styled Components is skipping to render the function declaration, probably leaving the default border-color of the button element.
So you need to pass as argument an object with the attribute currentPosition in both calls to the calcBorderColor function in order to make it usable and avoid that error.
const Choice = styled.button`
border-color: ${calcBorderColor({currentPosition: 1})};
&:hover {
border-color: ${darken(0.1, calcBorderColor({ currentPosition: 0}))};
}
`;

Setting a value in CSS from React

Having trouble parameterizing css such that animationSpeed is taken from props.
I would want to replace the .2s below with animationSpeed
transitions.css
.Anim-appear {
animation: .2s linear pageFadeIn, .2s linear pageSlideInLeft;
}
...
component.jsx
import '../css/transitions.css';
const PageAnimator = props => {
const animationSpeed = props.animationSpeed + 's' // How to use this to set animationSpeed in CSS?
}
I am having a lot of trouble doing this and was wondering how I could get this done.
Note: this value doesn't change. After we initialize the app it is a constant value. But we have several versions of the App that all have different configurations and animation speeds.
document.documentElement.style.setProperty('--animation-speed', sec);
That's how I accomplished it. It seems to work. : )
Thanks to:
How to change CSS root variable in React?

How to interpolate styles in React?

I want to color-code words by language in my React app. I have a styles file, which contains things like:
english: {
// style here
}
french: {
// style here
}
spanish: {
// style here
}
// etc.
Each of my words (entrys) is an object that contains a language key/value pair, i.e. {language: french}.
I could create a long case/switch statement, but I'm looking for a shorter way. Here's my case/switch statement:
var color;
switch (entry.language) {
case 'english':
color = styles.english;
break;
case 'french':
color = styles.french;
break;
// etc.
<div style={color}> {entry.word} </div>
That seems unnecessarily repetitive, especially if I have a lot of languages. Instead, I want to be able to just interpolate entry.language into my div, something like:
<div style={styles.{entry.language}} {entry.word} </div>
That doesn't work. Is there a way to do it?
What you want is to access an object. The bracket notation is what you need
<div style={styles[entry.language]} >{entry.word} </div>
I stumble on this page with a similar question but ended up finding the answer
from https://medium.com/capital-one-developers/cut-the-sass-how-to-use-inline-javascript-styles-for-everything-f5ac5b77ae57
import React from 'react';
import { StyleSheet, css } from 'aphrodite';
import { brandRed } from './colors';
const styles = StyleSheet.create({
foo: {
border: `1px solid ${brandRed}`,
},
});
const UserMenu = () => (
<div className={css(style.foo)}>
This box has a nice border.
</div>
);

How can I select all children of an element except the last child?

How would I select all but the last child using CSS3 selectors?
For example, to get only the last child would be div:nth-last-child(1).
You can use the negation pseudo-class :not() against the :last-child pseudo-class. Being introduced CSS Selectors Level 3, it doesn't work in IE8 or below:
:not(:last-child) { /* styles */ }
Make it simple:
You can apply your style to all the div and re-initialize the last one with :last-child:
for example in CSS:
.yourclass{
border: 1px solid blue;
}
.yourclass:last-child{
border: 0;
}
or in SCSS:
.yourclass{
border: 1px solid rgba(255, 255, 255, 1);
&:last-child{
border: 0;
}
}
easy to read/remember
fast to execute
browser compatible (IE9+ since it's still CSS3)
Nick Craver's solution works but you can also use this:
:nth-last-child(n+2) { /* Your code here */ }
Chris Coyier of CSS Tricks made a nice :nth tester for this.
When IE9 comes, it will be easier. A lot of the time though, you can switch the problem to one requiring :first-child and style the opposite side of the element (IE7+).
Using nick craver's solution with selectivizr allows for a cross browser solution (IE6+)
There is a:not selector in css3. Use :not() with :last-child inside to select all children except last one. For example, to select all li in ul except last li, use following code.
ul li:not(:last-child){ }
If you're using it within the nesting of the parent then the easiest way is:
&:not(:last-child){
....
}
Example:
.row { //parent
...
...
...
&:not(:last-child){
....
}
}
Using a more generic selector, you can achieve this as seen below
& > *:not(:last-child) {/* styles here */}
Example
<div class="parent">
<div>Child one</div>
<div>Child two</div>
</div>
This will capture all the child DIV in the parent
to find elements from last, use
<style>
ul li:not(:last-child){ color:#a94442}
</style>
Nick Craver's solution gave me what I needed but to make it explicit for those using CSS-in-JS:
const styles = {
yourClass: {
/* Styles for all elements with this class */
'&:not(:last-child)': {
/* Styles for all EXCEPT the last element with this class */
},
},
};
.nav-menu li:not(:last-child){
// write some style here
}
this code should apply the style to all except the last child

Resources