I want to use the components i made multiple times while rendering dynamic content
but when i try to render them they just stack up on themselves in the same position
whenever i render the component, multiple times, i dont even see the sliders and the >title stacks up on eachother
import React from "react";
import styled from "styled-components";
import ellipse from "../img/ellipse.png";
import Range from "./Range";
function RangeComp() {
const titlesArr = [
"Cybersecurity",
"Developer",
"DevOps",
"Designer",
"Project Manager",
"Product Manager",
"Marketer",
"Writer",
];
console.log(titlesArr);
return (
<Container>
<Circle />
<Heading>Score your level of interest in these job titles:</Heading>
<Divs>
<Div1>
<Range title={titlesArr[0]} />
<Range title={titlesArr[1]} />
</Div1>
<Div2></Div2>
</Divs>
</Container>
);
}
export default RangeComp;
const Container = styled.div`
position: absolute;
width: 980px;
height: 583px;
left: 650px;
top: 220px;
box-shadow: 0px 4px 29px #f0f3ff;
border-radius: 35px;
:hover {
border: 1px solid black;
}
`;
const Circle = styled.div`
position: absolute;
background-image: url(${ellipse});
width: 30px;
height: 30px;
right: 1.8%;
top: 2%;
background-repeat: no-repeat;
background-size: cover;
`;
const Heading = styled.div`
position: absolute;
width: 400px;
height: 31px;
font-family: "HelveticaNeueCyr";
font-style: normal;
font-weight: 400;
font-size: 20px;
line-height: 155.02%;
color: #30302e;
left: 8%;
top: 10%;
`;
const Divs = styled.div``;
const Div1 = styled.div``;
const Div2 = styled.div``;
Above is where i want to reuse the component but they just stack up on each other
Below is the component i want to reuse
import React, { useState } from "react";
import "./Range.css";
import styled from "styled-components";
import ReactSlider from "react-slider";
function Range(props) {
const [currentValue, setCurrentValue] = useState(0);
return (
<div className="range">
<ReactSlider
className="customSlider"
trackClassName="customSlider-track"
thumbClassName="customSlider-thumb"
marks={1}
min={0}
max={10}
defaultValue={0}
value={currentValue}
onChange={(value) => setCurrentValue(value)}
/>
<h4>{props.title}</h4>
<h1 className="range-value">{currentValue}/10</h1>
</div>
);
}
export default Range;
What's inside your Range.css?
If the position is:
position: absolute;
Then your components will always stack on top of each other because they all have the same style.
You might need to set the position to:
position: relative;
So that the components will position themselves relative to each other.
Related
I am having an issue with applying padding (and styles) to my Material UI component.
I have this component here:
import "./css/Landing.css";
import { Button } from "#mui/material";
function Landing() {
return (
<div className="Background">
<div className="centerdiv">
<div>
<Button className="Login-Button" variant="contained">
Register
</Button>
</div>
<div>
<Button variant="contained">Login</Button>
</div>
</div>
</div>
);
}
export default Landing;
This component references the following CSS file and Login Button Class:
.Background {
background-color: black;
background-repeat: no-repeat;
background-size: cover;
position: absolute;
height: 100%;
width: 100%;
}
.wrapper {
text-align: left;
background: gray;
/* so we can actually see what's happening */
padding: 20px;
position: absolute
/* Give us some breathing room */
}
.centerdiv {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
width: 100px;
height: 100px;
}
.Login-Button {
background-color: #ffffff;
padding: 10px;
}
When I attempt to reference the LoginButton class, the padding for my Material UI Button doesn't work. As well as the styles.
What is the best practice way of adding styles to my buttons?
Its probably because the styles inside Button take precedence over yours due to CSS specificity. Probably you can check this by using the dev tools to see if your styles are crossed out.
You need to use the material-ui theming solution: https://mui.com/material-ui/customization/theme-components/
You can create a styled button using 'styled' from MUI
import styled from "#mui/system/styled";
import Button from "#mui/material/Button";
export const LoginButton = styled(Button)(({ variant }) => ({
":hover": {
backgroundColor: "pink"
},
border: "solid red",
backgroundColor: "black",
width: "200px",
color: "white",
padding: "20px",
boxShadow: "3px 3px 3px pink"
}));
export default function App() {
return (
<div>
<LoginButton>LOGIN</LoginButton>
</div>
);
}
CodeSandbox : https://codesandbox.io/s/styled-button-variant-mui-sofl-forked-nwyxde?file=/src/StyledButton.js
I have a Splideslide element in react and am looking to move the description text over the image for each element. Currently the code I have is:
import {useEffect, useState} from "react";
import styled from "styled-components";
import {Splide, SplideSlide} from "#splidejs/react-splide";
import "#splidejs/splide/dist/css/splide.min.css";
function Popular() {
const [popular, setPopular] = useState([]);
useEffect(() => {
getPopular();
}, []);
const getPopular = async() => {
const api = await fetch(`https://api.spoonacular.com/recipes/random?apiKey=${process.env.REACT_APP_API_KEY}&number=9`);
const data = await api.json();
console.log(data);
setPopular(data.recipes)
console.log(data.recipes)
}
return (
<div>
<Wrapper>
<h3>Popular Picks</h3>
<Splide options = {{
perPage:4,
arrows: false,
pagination: false,
drag: 'free',
gap: "4rem",
}}>
{popular.map((recipe) =>{
return (
<SplideSlide>
<Card>
<Gradient/>
<p>{recipe.title}</p>
<img src={recipe.image} alt={recipe.title}/>
</Card>
</SplideSlide>
);
})}
</Splide>
</Wrapper>
</div>
)
}
const Wrapper = styled.div`
margin: 4rem 0rem;
postion: absolute;
`;
const Card = styled.div`
min-height: 25rem;
overflow: hidden;
postion: relative;
img {
border-radius: 2rem;
postion: absolute;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
p {
position: absolute;
z-index: 10;
left: 50%;
bottom: 0%;
transform: translate(-50%, 0%);
color: black;
width: 100%;
text-align: center;
font-weight: 600;
font-size: 1rem;
height: 40%;
display: flex;
justify-content: center;
align-items: center;
}
`;
const Gradient = styled.div`
z-index: 3
postion: absolute;
width: 100%;
height: 100%;
background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.5))
`;
export default Popular
Theoretically I believe this should be able to move the text on the image but for some reason it is not working as intended. The full project can be seen in the repository here: REPO. Feel free to comment for further information or any clarifications.
Maybe because of your multiple
postion: absolute;
instead of
position: absolute;
;)
I am new to React and did not find any solution to this simple problem.
I want to revert LangText colors when the toggle button is clicked - initially ENG is white and EST is black and every time input is clicked the colors invert.
I have separate files for returning and styling components.
I tried to change the color of a variable (located on top of the style-components file) inside the styled component tag, so with CSS - inside Input pseudo-class &:checked + span. Looked surreal and didn't work in any way.
I would be very thankful for an example of how to change two colors at the same, time in this case. There are always too few examples with components, usually, CSS is used separately, but for me this method is more readable and logical.
import React from 'react'
import { Input, InputWrapper, Slider, ToggleContainer, LangText} from './LangugageToggleElements';
const LanguageToggle = ({onChange}) => {
return(
<ToggleContainer>
<InputWrapper>
<Input type="checkbox" onChange={onChange}/>
<Slider>
<LangText>ENG</LangText>
<LangText>EST</LangText>
</Slider>
</InputWrapper>
</ToggleContainer>
)} ;
export default LanguageToggle
import styled from "styled-components";
let toggleBackground = "#000";
let textColor = "#fff";
export const ToggleContainer = styled.div`
position: absolute;
top: 10px;
right: 20px;
`
export const InputWrapper = styled.label`
position: relative;
display: flex;
justify-content: center;
text-align: center;
`
export const Input = styled.input`
position: absolute;
left: -9999px;
top: -9999px;
&:checked + span {
&:before {
left: 52px;
}
}
`
export const Slider = styled.span`
display: flex;
justify-content: center;
text-align: center;
cursor: pointer;
width: 105px;
border-radius: 100px;
position: relative;
transition: background-color 0.2s;
color: ${textColor};
&:before {
content: "";
position: absolute;
top: 15px;
left: 2px;
width: 50px;
height: 20px;
border-radius: 45px;
transition: 0.2s;
background: ${toggleBackground};
box-shadow: 0 2px 4px 0 rgba(0, 35, 11, 0.2);
}
`;
export const LangText = styled.p`
padding-right: 5px;
padding-left: 5px;
z-index: 1;
letter-spacing: 3px;
`;
I think you can simply use a useState hook to maintain checkbox and the use it for your LangText.
<ToggleContainer>
<InputWrapper>
<Input type="checkbox" onChange={()=>{
onChange();
//use state hook to maitain the checkbox value
}}/>
<Slider>
<LangText className={isChecboxValue === x ? color : invert }>ENG</LangText>
<LangText className={isChecboxValue === y ? invert: color}>EST</LangText>
</Slider>
</InputWrapper>
</ToggleContainer>
So I am sure it's something very simple but I can't get the background to cover the whole background, simple as that. I say simple, but I will provide the code I have used.
Basically only a quarter of the top of the screen is black basically if I only have something wrapped in the component.
Home.js -
import React from 'react'
import styled from "styled-components";
import Background from './images/Cryptid.png'
const Home = () => {
return (
<Container>
<InnerContainer>
<Logo />
<JoinInfo><p>test</p></JoinInfo>
</InnerContainer>
</Container>
)
}
const Container = styled.div`
display: flex;
height: 100%;
width: 100%;
background: black;
background-size: cover;
`;
const InnerContainer = styled.div`
height: 100%;
width: 100%;
`;
const Logo = styled.div`
border: 1px solid red;
margin: auto;
padding: auto;
height: 100px;
width: 400px;
background-image: url(${Background});
`
const JoinInfo = styled.section`
color: white;
`
export default Home;
You can add the background color to the html body element then it will cover the whole screen:
import { createGlobalStyle } from 'styled-components'
const GlobalStyle = createGlobalStyle`
body {
background: black;
}
`
const <Home> = () =>
<GlobalStyle />
<Navigation /> {/* example of other top-level stuff */}
</Home>
I've been trying to find the solution to my problem.
I have several Heading Tags (H1, H2 etc) each in their own file.
I would like to add some css when calling them based on a prop. Some headings have a small border-bottom and some don't. So, in order to refractor my code, I want to add some css based on a prop. I can't seem to find a way.
Here's an example of Heading H2:
import styled from 'styled-components';
import colors from '../../../../colors';
import fonts from '../../../../fonts';
import fontWeights from '../../../../fontWeights';
const HeadingH2 = styled.h2`
color: ${colors.text};
font-family: ${fonts.montSerrat};
font-size: 1.6em;
font-weight: ${fontWeights.light};
letter-spacing: 0.2em;
padding-bottom: 0.7em;
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`;
export default HeadingH2
Example of calling Heading H2:
import React from 'react';
import HeadingH2 from '../../common/headings/heading_h2';
import HeadingBaseline from '../../common/headings_baseline';
// Features
import {SectionContainer, FeaturesContainer} from './features.style';
import Feature from './feature';
import feature1 from '../../../img/features/feature1.png';
import feature2 from '../../../img/features/feature2.png';
import feature3 from '../../../img/features/feature3.png';
// Text
import Text from '../../../content';
const Features = () => {
return(
<SectionContainer id={"what"}>
<HeadingH2>
What We Do
</HeadingH2>
<HeadingBaseline>
{Text.headingBaseline}
</HeadingBaseline>
<FeaturesContainer>
<Feature
src={feature1}
headingText={Text.feature1.heading}
paragraph={Text.feature1.paragraph}
/>
<Feature
src={feature2}
headingText={Text.feature2.heading}
paragraph={Text.feature2.paragraph}
/>
<Feature
src={feature3}
headingText={Text.feature3.heading}
paragraph={Text.feature3.paragraph}
/>
</FeaturesContainer>
</SectionContainer>
)
};
export default Features;
I want to extract the following CSS properties
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
So, assuming I have the above CSS rule in a separate file, how do I add/import them using props on my styled component HeadingH2.
Thanks for the help :)
You can also use css helper from styled-components to create a SharedStyles.js file.
In the demo you can see it in action.
Just using it in a style of an inherited component is not working as expected. If I'm adding it to StyledBase then the variables are not correctly added afterwards (hover style override stops working).
That's why I copied ${borderBottom} to each styled component Heading1 / Heading2 instead of adding it to StyledBase.
I think having a level prop for the heading is a good idea but I would handle it differently by creating a HeadingBase component and add your styles to a StyledBase component (also see code in the demo).
The HeadingBase code looks like this:
const HeadingBase = ({ className, children, level = 1 }) =>
React.createElement(`h${level}`, { className }, children);
It's a component that renders h1,h2,... tags based on the prop level passed (defaults to h1). The h-tag receives className as props (needed for styled-components) and contains the children passed to the component.
SharedStyles.js
import { css } from "styled-components";
export const borderBottom = css`
&:after{
content: "";
display: block;
height: 3px;
width: 200px;
background-color: ${props => props.color || "black"};
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
`;
Then you can import it with import { borderBottom } from "./SharedStyles"; and add it to your styled-component like following:
const Heading1= styled.h1`
${borderBottom}
`;
Something like this works:
const HeadingH2 = styled.h2`
position: ${props => props.relative && 'relative'};
padding: ${props => props.paddingBottom ? '0 0 20px 0' : '0'};
}
`;
Then use like this:
<HeadingH2 relative paddingBottom />
Possible answer:
I add the following CSS rules in a separate file like so.
I create a function which returns a string of text. I can import this function and add those rules to any component I wish.
export const borderBottom = () => {
return `
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`
}
And use it like so on any heading or component that I wish:
import styled from 'styled-components';
import colors from '../../../../colors';
import fonts from '../../../../fonts';
import fontWeights from '../../../../fontWeights';
import {borderBottom} from '../../../../css';
const HeadingH5 = styled.h5`
color: ${colors.black};
font-family: ${fonts.montSerrat};
font-size: 1em;
font-weight: ${fontWeights.light};
letter-spacing: 0.1em;
padding-bottom: 0.45em;
margin-bottom: 25px;
${borderBottom}
`
;
export default HeadingH5;
This works for me. Any other suggestions are welcome.
You should definely check this: typestyle
the best way you can write dynamic css (for me). Works perfectly with react, even with ssr if you need it...
Why not just have a headingLevel prop? and then pass it into the styled component? And just have one StyledHeader styled component as I'm guessing the code is the mostly the same in all the heading styles files? Which is a big no no, you want to always try not to repeat your code.
const Features = () => {
return(
<SectionContainer id={"what"}>
<StyledHeader
headingLevel={headingLevel}
>
What We Do
</StyledHeader>
<HeadingBaseline>
{Text.headingBaseline}
</HeadingBaseline>
<FeaturesContainer>
<Feature
src={feature1}
headingText={Text.feature1.heading}
paragraph={Text.feature1.paragraph}
/>
<Feature
src={feature2}
headingText={Text.feature2.heading}
paragraph={Text.feature2.paragraph}
/>
<Feature
src={feature3}
headingText={Text.feature3.heading}
paragraph={Text.feature3.paragraph}
/>
</FeaturesContainer>
</SectionContainer>
)
};
export default Features;
And in your StyledHeader file
The below function will take your passed in heading level of h1, h2, h3 and will apply a border, if not the above 3 heading level it will be 0 value. I'd do some checks to ensure the value is lower case e.g. toLowerCase()
const getBorder = ({ headingLevel } ) => {
const headingLevelMap = {
h1: 0.7,
h2: 0.6,
h3: 0.6,
};
return headingLevelMap[headingLevel] || 0;
}
const HeadingH2 = styled.headingLevel`
color: ${colors.text};
font-family: ${fonts.montSerrat};
font-size: 1.6em;
font-weight: ${fontWeights.light};
letter-spacing: 0.2em;
padding-bottom: 0.7em;
border-bottom: ${getCorrectBorderBottom}em solid black
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`;
I'd also check that if the value of the passed in headingLevel is not any of the 6 heading levels it should have a default value of whatever you want.
The above was just quick pseudo code, but hopefully get the general idea here? Let me know it comments if not.
I'd also recommend that you split your Title component out into a separate component.