How to split CSS of a single element into multiple functions/variables in styled-components? - reactjs

I have a component that has a very long list of CSS that handles various items within that element.
export const StyledTable = styled((props) => <Table {...props} />)`
padding: 20px;
background-color: white;
border-radius: 20px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
& tbody .ant-table-column-sort,
& thead th.ant-table-column-sort {
background-color: unset;
}
& .ant-select .ant-select-selector {
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
color: lightgray;
height: 50px;
font-size: 20px;
display: flex;
align-items: center;
}
& .ant-pagination {
display: flex;
justify-content: center;
align-items: center;
}
& .ant-pagination .ant-pagination-total-text {
color: rgba(102, 220, 141, 1);
}
// and another 100 rows bellow
`;
Some of the CSS is for the rows of the table, others are for the columns, another CSS is for various controls of the table (and provides only the main Table Component, so go figure).
Is there a way to somehow split that css into multiple functions/variables and then do something like:
export const StyledTable = styled((props) => <Table {...props} />)`
padding: 20px;
${rowsCss}
${columnsCss}
${controlsCss}
`
And if that is possible, how do I define rowsCss (and the rest)?

You can just use css blocks:
import { css } from 'styled-components';
const paginationCss = css`
& .ant-pagination {
display: flex;
justify-content: center;
align-items: center;
}
`
export const StyledTable = styled((props) => <Table {...props} />)`
padding: 20px;
${paginationCss}
`

Related

why this component height is not full?

This is my cart component code. I am using styled components.
import React from "react";
import styled from "styled-components";
import { useSelector, useDispatch } from "react-redux";
import { remove } from "../../features/cartSlice";
const Cart = () => {
const pizzaProducts = useSelector((state) => state.cart);
const dispatch = useDispatch();
console.log(pizzaProducts);
const handleRemove = (id) => {
dispatch(remove(id));
};
return (
<CartContainer>
<CartHeading>Your cart</CartHeading>
<CartWrapper>
{pizzaProducts.map((pizzaProduct, index) => {
return (
<CartCard key={index}>
<CartImg src={pizzaProduct.img} alt="err" />
<CartInfo>
<CartTitle>{pizzaProduct.name}</CartTitle>
<CartDescription>{pizzaProduct.desc}</CartDescription>
<CartPrice>{pizzaProduct.price}</CartPrice>
<CartButton
id="btn"
onClick={() => handleRemove(pizzaProduct.id)}
>
Remove
</CartButton>
</CartInfo>
</CartCard>
);
})}
</CartWrapper>
</CartContainer>
);
};
const CartContainer = styled.div`
height: 100vh;
width: 100%;
min-width: 100vh;
min-height: 100%;
background: #000;
#media screen and (max-width: 400px) {
width: 100%;
}
`;
const CartHeading = styled.h2`
height: 40px;
padding: 30px 0;
text-align: center;
padding-top: 5rem;
margin-bottom: 2rem;
color: white;
font-size: clamp(2rem, 2.5vw, 3rem);
letter-spacing: 4px;
text-transform: uppercase;
`;
const CartWrapper = styled.div`
display: flex;
flex-wrap: wrap;
padding: 10px 0;
justify-content: center;
`;
const CartCard = styled.div`
margin: 0 3rem;
width: 400px;
min-width: 400px;
line-height: 2;
`;
const CartImg = styled.img`
height: 400px;
min-width: 400px;
box-shadow: 8px 8px #fdc500;
`;
const CartInfo = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 1.5rem 0;
`;
const CartTitle = styled.h2`
font-weight: 400;
font-size: 1.5rem;
color: white;
word-spacing: 1px;
letter-spacing: 3px;
`;
const CartDescription = styled.p`
margin-bottom: 1rem;
color: white;
margin: 20px 0;
font-size: 20px;
text-align: center;
word-spacing: 1px;
letter-spacing: 3px;
`;
const CartPrice = styled.p`
margin-bottom: 1rem;
font-size: 2rem;
color: white;
word-spacing: 1px;
letter-spacing: 3px;
`;
const CartButton = styled.button`
font-size: 1rem;
padding: 1rem 4rem;
border: none;
background: #e31837;
color: #fff;
transition: 0.2 ease-out;
&:hover {
background: #ffc500;
transition: 0.2s ease-out;
cursor: pointer;
color: #000;
}
`;
export default Cart;
I am expecting the full height 100%.

Hover effect using Styled Components in in React don't work

Don't know why hover effect code on button in StyledComponents is not working, in React app.
Can You please look at the code ? Thanks !
export const StyledButton = styled.button`
width: 12vh;
background-color: ${colors.buttonColor};
-webkit-box-shadow: 0px 0px 35px -4px rgba(237, 38, 38, 0.51);
box-shadow: 0px 0px 35px -4px rgba(237, 38, 38, 0.51);
height: 4vh;
margin-top: 5vh;
border-radius: 5px;
padding-bottom: 5px;
display: flex;
align-items: center;
justify-content: center;
& :hover {
background-color: hotpink;
}
`;
<StyledButton>
<Link to="/main" style={{ textDecoration: "none" }}>
<StyledParagraph>Go without</StyledParagraph>
</Link>
</StyledButton>
Do you need correct selector.
In styled components, if you are styling the component itself, you don't need to write "&:hover", you can write ":hover" instead.
Both selectors are correct, use either one. If I apply styles to the styled component itself, I usually don't write the "&" sign.
Instead
& :hover {
background-color: hotpink;
}
Do you need write
:hover {
background-color: hotpink;
}
Below code with correct selector for hover.
export const StyledButton = styled.button`
width: 12vh;
background-color: ${colors.buttonColor};
box-shadow: 0px 0px 35px -4px rgba(237, 38, 38, 0.51);
height: 4vh;
margin-top: 5vh;
border-radius: 5px;
padding-bottom: 5px;
display: flex;
align-items: center;
justify-content: center;
:hover {
background-color: hotpink;
}
`;

How to center buttons with styled-components?

Can't figure out how to center 2 buttons horizontally with styled-components.
Below is my code.
Tried many ways to center, but didn't work.
import React from "react"
import styled from "styled-components"
const HomeStyles = styled.div`
h1 {
font-size: 1.5em;
text-align: center;
color: royalblue;
}
button {
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid royalblue;
border-radius: 3px;
color: royalblue;
}
`
export default function Home() {
return (
<HomeStyles>
<h1>Title</h1>
<button>Button1</button>
<button>Button2</button>
</HomeStyles>
)
}
UPDATE: I need to center buttons horizontally
Have you tried using flexbox on parent element?
const HomeStyles = styled.div`
display: flex;
flex-direction: column;
justify-items: center;
align-items: center;
....
`;
const ButtonsWrapper = styled.div`
display: flex;
justify-items: center;
align-items: center;
`;
<HomeStyles>
<h1>Title</h1>
<ButtonsWrapper>
<button>Button1</button>
<button>Button2</button>
</ButtonsWrapper>
</HomeStyles>

target child element styled components

I'm trying to change the nth-child(2) background color of the ColorBox element by targeting it as a child of ImgGrid but I just can't seem to get it to work, I have tried multiple variations with different elements and nothing seems to be working
This will change the background color if I don't try to target an nth-child element
const ImgGrid = styled.div`
display: flex;
flex-wrap: wrap;
flex-direction: row;
${ColorBox} {
background: #ff00ff;
}
`
How can I target the nth-child(2) of the ColorBox element?
import React from 'react'
import styled from 'styled-components'
// import Img from '../../atoms/Img'
import { array, bool } from 'prop-types'
const Wrap = styled.div`
padding: 20px 0;
`
const BoxWrap = styled.div`
position: relative;
border: 1px solid #000;
height: auto;
padding: 20px;
`
const Title = styled.div`
position: absolute;
display: flex;
align-items: center;
top: -20px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
height: 40px;
background: #f6f6f6;
padding: 10px;
`
const BoxInner = styled.div`
width: 100%;
height: 100%;
`
const ColorBox = styled.div`
height: 60px;
width: 100%;
background: #FFD700;
`
const ImgCell = styled.div`
flex: 0 0 25%;
padding: 5px;
`
const ImgGrid = styled.div`
display: flex;
flex-wrap: wrap;
flex-direction: row;
&:nth-child(2) ${ColorBox} {
background: #ff00ff;
}
`
const ImgCellInner = styled.div`
position: relative;
`
// const ImgText = styled.div`
// position: absolute;
// bottom: 0;
// left: 0;
// padding: 5px;
// width: 100%;
// background: rgba(0,0,0,0.7);
// color: #fff;
// `
const ImgWrap = styled.div`
width: 100%;
`
const ColorWrap = styled.div`
`
const Filter = ({ filterData, color }) => (
<Wrap>
<BoxWrap>
<Title>
For Women
</Title>
<BoxInner>
<ImgGrid>
{filterData.map(filter =>
<ImgCell>
<ImgCellInner>
<ImgWrap>
{color &&
<ColorWrap>
<ColorBox />
{filter.text}
</ColorWrap>
}
</ImgWrap>
</ImgCellInner>
</ImgCell>,
)}
</ImgGrid>
</BoxInner>
</BoxWrap>
</Wrap>
)
/* eslint-disable*/
Filter.propTypes = {
filterData: array,
color: bool,
}
Filter.defaultProps = {
filterData: array,
color: bool,
}
export default Filter
I can assume your code is not working because &:nth-child(2) means you are selecting ImgGrid which is second child itself. Try to specify ImgCell as nth-child(2):
const ImgGrid = styled.div`
display: flex;
flex-wrap: wrap;
flex-direction: row;
${ImgCell}:nth-child(2) ${ColorBox} {
background: #ff00ff;
}
`
I'm not sure about scoping, so probably you need to use & before:
const ImgGrid = styled.div`
display: flex;
flex-wrap: wrap;
flex-direction: row;
& ${ImgCell}:nth-child(2) ${ColorBox} {
background: #ff00ff;
}
`
If you stumble on this question looking for how to target all children elements, here is how;
const ParentDiv = styled.div`
>* {
background: white;
padding: 5px;
};
/* ...etc */
`;
I had the same problem. :focus-within in parent element worked for me, could solve your problem too.
Eg:
export const Parent = styled.div`
display: flex;
align-items: center;
border: 1px solid #000;
&:focus-within {
border: 1px solid #2ADCC6;
}
`;
export const Child = styled.input`
flex: 1;
border: none;
`;
Documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within

React styled-components: refer to other components

According to styled-components doc's I can refer to another component to trigger, for example, a hover effect.
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Link2 = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: steelblue;
color: white;
${Link}:hover & {
background-color: greenyellow;
color: black;
}
`;
class Hello extends React.Component{
render() {
return(
<div>
<Link>Hello World</Link>
<Link2>Hello Again</Link2>
</div>
)
}
}
Basically, hovering mouse on my <Link> should trigger a change in background-color in <Link2>.
This is not happening. Any ideas why?
I prepared a code snippet here: https://codesandbox.io/s/qv34lox494
You can refer to styled-components which are children of your styled-component, not side-by-side.
See a quote from the doc:
Here, our Icon component defines its response to its parent Link being
hovered
For your problem, you can create a wrapper for both of your links, and use the adjacent sibling selector in CSS like this:
const Wrapper = styled.div`
& ${Link}:hover + ${Link2} {
background-color: greenyellow;
color: black;
}
`;
https://codesandbox.io/s/mo7kny3lmx
The other way is to modify your selector on Link2 to use siblings (now it's nested item selector). In that case you can get rid of extra wrapper
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Link2 = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: steelblue;
color: white;
${Link}:hover + & {
background-color: greenyellow;
color: black;
}
`;
class Hello extends React.Component{
render() {
return(
<div>
<Link>Hello World</Link>
<Link2>Hello Again</Link2>
</div>
)
}
}
you can do it like this. it works for many components:
const Hi0 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;
const Hi1 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;
const Hi2 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;
const Ind = styled.div`
width:75px;
height:75px;
border-radius:50%;
display: flex;
align-items: center;
padding: 5px 10px;
background: steelblue;
color: white;
transition:0.5s;
`;
const Wrapper = styled.div`
${Hi0}:hover ~ ${Ind} {
background: blue;
};
${Hi1}:hover ~ ${Ind} {
background: red;
};
${Hi2}:hover ~ ${Ind} {
background: yellow;
};
`;
class App extends React.Component{
render() {
return(
<Wrapper>
<Hi0>Hello World</Hi0>
<Hi1>Hello World</Hi1>
<Hi2>Hello World</Hi2>
<Ind>Hello Again</Ind>
</Wrapper>
)
}
}
export default App;
sandboxexemple

Resources