React Styled Components generating excessive css - reactjs

Take the following example:
import * as React from 'react';
import styled from 'styled-components';
const Ball = styled.div`
width: 100px;
height: 100px;
border: 1px solid black;
border-radius: 50%;
background: radial-gradient(peachpuff 0% 8%, rgb(243, 169, 105) 10% 55%, rgb(192, 125, 66) 57% 100%) no-repeat;
background-size: 150% 150%;
background-position: center;
background-position-x: 87%;
background-position-y: 87%;
`;
const SmallBall = styled(Ball)`
width: 50px;
height: 50px;
`;
export default () => (
<>
<Ball name="Ball"></Ball>
<SmallBall name="SmallBall"></SmallBall>
</>
)
Here's the markup that's being generated:
If I were to write out the CSS I'd expect to be generated, it'd probably look something like this:
.sc-cHGsZl {
width: 100px;
height: 100px;
border: 1px solid black;
border-radius: 50%;
background: radial-gradient(peachpuff 0% 8%, rgb(243, 169, 105) 10% 55%, rgb(192, 125, 66) 57% 100%) no-repeat;
background-size: 150% 150%;
background-position: center;
background-position-x: 87%;
background-position-y: 87%;
}
.sc-cHGsZl.bmZbgS {
width: 50px;
height: 50px;
}
Instead what's generated is:
and
How can I get styled-components to output more concise CSS where common properties are grouped and not unnecessarily repeated?

You can add classNames in styled-component.
import * as React from 'react';
import styled from 'styled-components';
const Ball = styled.div.attrs({ className: "ball" })`
width: 100px;
height: 100px;
border: 1px solid black;
border-radius: 50%;
background: radial-gradient(peachpuff 0% 8%, rgb(243, 169, 105) 10% 55%, rgb(192, 125, 66) 57% 100%) no-repeat;
background-size: 150% 150%;
background-position: center;
background-position-x: 87%;
background-position-y: 87%;
`;
const SmallBall = styled(Ball).attrs({ className: "small-ball" })`
width: 50px;
height: 50px;
`;
export default () => (
<>
<Ball name="Ball"></Ball>
<SmallBall name="SmallBall"></SmallBall>
</>
)

I think a simpler approach would be to make a reusable and flexible component that you can change via passing in properties OR by using style overrides (also, it appears like this issue was reported back in 2018). While it doesn't solve the duplicate class issue, it at least mitigates it.
Working example:
components/Ball/index.js
import styled from "styled-components";
export default styled.div`
width: ${({ width }) => width || "100px"};
height: ${({ height }) => height || "100px"};
border: 1px solid black;
border-radius: 50%;
background: radial-gradient(
peachpuff 0% 8%,
rgb(243, 169, 105) 10% 55%,
rgb(192, 125, 66) 57% 100%
)
no-repeat;
background-size: 150% 150%;
background-position: center;
background-position-x: 87%;
background-position-y: 87%;
`;
index.js
import React from "react";
import { render } from "react-dom";
import { Ball, Container } from "./components";
const App = () => (
<Container>
<Ball height="50px" width="50px" />
<Ball />
<Ball style={{ height: 200, width: 200 }} />
</Container>
);
render(<App />, document.getElementById("root"));
Ball # 1
Ball # 2
Ball # 3

Related

Best practice to embed Vimeo video in Nextjs or Reactjs

I'm making a website with Next.js and wanting to embed vimeo videos and wondering what is the most common practice to do it.
I've tried regular iframe, react-player, #u-wave/react-vimeo.
I realized #u-wave/react-vimeo gives me 410 error sometimes when I leave the page open long and react-player when it loads it flickers a bit (small first and then it gets bigger to its size) :(
410 error I get on #u-wave/react-vimeo:
Thank you
This is how I have implemented Vimeo player:
import React, { useRef, useState} from "react";
import styled from "styled-components";
import { Play } from "phosphor-react";
import ReactPlayer from "react-player/lazy";
import styles from "./styles.module.scss";
export default function VideoPlayer() {
const playerRef = useRef()
return (
<div className={styles.playerWrapper}>
<ReactPlayer
id="MyId"
className={styles.reactPlayer}
width="100%"
height="100%"
controls
playing
light="img/main-page/image.webp"
playIcon={
<Btn
className={styles.btnSmall}
bgColor="var(--ifm-btn-primary)"
textColor="var(--ifm-text-black)"
borderRadius={40}
fontSize={20}
px={25}
py={25}
style={{
maxWidth: 361,
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: 10
}}
>
<Play weight="fill" color="--ifm-text-black" size={24} />
</Btn>
}
url="https://vimeo.com/yourid"
></ReactPlayer>
</div>
);
}
//styles.module.css
.playerWrapper {
position: relative;
padding-top: 56.25%;
/* Player ratio: 100 / (1280 / 720) */
box-shadow: 0px 0px 50px 0px rgba(0, 0, 0, 0.7);
border-radius: 20px;
margin-top: 92px;
margin-bottom: 21px;
}
.reactPlayer {
position: absolute;
top: 0;
left: 0;
border-radius: 20px;
overflow: hidden;
}
.btnSs {
max-width: 361px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
gap: 10;
}
#media(max-width: 768px) {
.btnSmall {
width: 150px !important;
font-size: 13px !important;
padding: 4px 10px !important;
gap: 0px !important;
}
}
#media(max-width: 451px){
.playerWrapper {
margin-bottom: 0px;
}
}

React Styled components with keyframes not working?

I tried initially working with makestyles but that didn't work with Keyframes and now I wrote the below code that compiles properly but for some reason doesnt show anything on screen??
Is there anything I'm not writing correctly or formatting correctly? Thanks
import styled, { keyframes } from 'styled-components';
export default function Confirmed() {
return (
<Wrap>
<Container>
<Box />
</Container>
</Wrap>
);
}
const animation = keyframes`
0% {
width: 60px;
height: 60px;
background:#f0f0f0;
}
25%{
width: 60px;
height: 60px;
background: #f8f8f8;
}
50% {
width: 60px;
height: 240px;
background: #f8f8f8;
}
100% {
width: 480px;
height: 240px;
background: #fafafa;
}`;
const Container = styled.div`
background: #f0f0f0;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
`;
const Wrap = styled.div`
margin: 0;
padding: 0;`;
const Box = styled.div`
border-radius: 20px;
width: 60px;
height: 60px;
background: #f0f0f0;
animation-name: ${animation};
animation-duration: 8s;
animation-iteration-count: infinite;
`;

Why is my styled Component hover effect not working

This is my first time using styledComponent.
Can someone tell me why my hover effect on SubmitBtn not working.
I just want to add hover effect on the submit button.
import styled from 'styled-components';
const SubmitBtn = styled.button`
width: 50%;
padding: 14px 20px;
margin: 8px 0;
display: inline-block;
border: none;
borderRadius: 4px;
cursor: pointer;
background: green;
color: white;
&:hover {
background: darkgreen;
color: grey;
}
`
<SubmitBtn>Submit Book</SubmitBtn>
I have taken the SubmitBtn out of component, and now it works.
You have to return/render the component.
import styled from 'styled-components';
const SubmitBtn = styled.button`
width: 50%;
padding: 14px 20px;
margin: 8px 0;
display: inline-block;
border: none;
borderRadius: 4px;
cursor: pointer;
background: green;
color: white;
&:hover {
background: darkgreen;
color: grey;
}
`
export const App = () => <SubmitBtn>Submit Book</SubmitBtn>

Styled components not applying styles

I have this 2 styled components
export const Icon = styled.svg`
width: 8px;
height: 8px;
background: black;
`
export const Dots = styled.div`
border: 2px solid green !imporant;
height: 30px;
background: white;
width: 16px;
height: 16px;
border: solid 1px #d2d2d2;
border-radius: 20px;
top: 25px;
position: relative;
${Icon}: hover {
background:black;
}
}
`
I want to display Icon on the hover of this div but i dont understand why it is not working,
Any suggestions please?
There is no problem with your code except on hover you don't change the color from its default value black
const Icon = styled.div`
width: 100px;
height: 100px;
background: black;
`;
export const Dots = styled.div`
${Icon}:hover {
background: red;
}
`;
export default function App() {
return (
<Dots>
<Icon />
</Dots>
);
}
https://codesandbox.io/s/styled-react-template-forked-nzwm8
You should place the hover styles inside the icon
export const Icon = styled.svg`
width: 8px;
height: 8px;
background: black;
&:hover {
background: black;
}

how to change the icons dynamically into a styled-component

I am new to styled-component and I am getting an error stating :
Property 'icon' does not exist on type 'ThemeProps'.
I want to give an icon in props. For one icon it works. I don't know how to do it so that I can change it many times.
export const GenericInput = styled.input`
background-color: #f4f4f4;
width: 220px;
height: 47px;
border: none;
border-radius: 50px;
font-weight: 600;
font-size: 16px;
cursor: pointer;
letter-spacing: 1px;
padding: 15px 30px;
-moz-outline-radius: 50px;
outline: none;
${(Icon) =>
Icon && css`
background-image: url(${({ icon }) => icon});
background-size: 20px;
background-position: 10px 50%;
background-repeat: no-repeat;
color: #c7c7c7;
`
}
::placeholder {
color: #c7c7c7;
}
`;

Resources