React set dynamic style in a component - reactjs

This has been asked several times but in my use case it's not working. I'm sure I'm missing something.
In a functional component I do:
const headerImg = {
backgroundImage: `http://localhost:1337${data.service.main_image.url}`
};
Then in a div I do the following:
<div className="bread-cumbs-area" style={headerImg}>
I'm attempting to use headerImg.backgroundImage as the background image but it's not displaying in my div. Any idea what I'm doing wrong?

Since you're setting the background image in CSS, you need to use the url() CSS function:
const headerImg = {
backgroundImage: `url('http://localhost:1337${data.service.main_image.url}')`
};

Related

How can i dynamically change images as Background in TailwindCSS?

I want to make a carousel, where the background is changing, i don't want to use the <img/> tag! I set the value as described in the documentation: https://tailwindcss.com/docs/background-image#arbitrary-values
My Code:
import React from 'react';
type CarouselProps = {
img: string;
};
const Carousel = ({ img }: CarouselProps) => {
return (
<div
className={`col-span-full bg-[url(${img})] bg-cover grid grid-cols-12 gap-6`}
> ...
</div>
);
};
When i set the String i pass to the Component hardcoded it works but when i use curly Braces and $ it doesn't. In addition i don't want to define my Background-Images in the tailwind.conf.js
The Error:
ERROR in ./src/index.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5]
.use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!
./node_modules/source-map-loader/dist/cjs.js!./src/index.css) 9:36-70
i don't want to define my Background-Images in the tailwind.conf.js
Well you have to. What you're trying to do isn't supported.
The way Tailwind scans your source code for classes is intentionally
very simple — we don’t actually parse or execute any of your code in
the language it’s written in, we just use regular expressions to
extract every string that could possibly be a class name.
so tailwind has no idea what your React code actually means. So it's simply not going to work.
Tailwind does not support dynamic class names:
Don't construct class names dynamically
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
you should customise your theme to include the image url:
You can add your own background images by editing the
theme.backgroundImage section of your tailwind.config.js file:
tailwind.config.js
module.exports = {
theme: {
extend: {
backgroundImage: {
'hero-pattern': "url('/img/hero-pattern.svg')",
'footer-texture': "url('/img/footer-texture.png')",
}
}
}
}
The solution is to use the style attribute. Thanks for helping :)
<div
className="col-span-full bg- bg-cover grid grid-cols-12 gap-6"
style={{
backgroundImage: `url(${img})`,
}}
>

Fade in and out between two images

I have two images. When I click the image container, a state is changed, and another image is revealed, while the other one disappears - like this:
const Image= ({image1, image2}) => {
const [image, setImageState] = useState(true);
return (
<div className="image-container" onClick={ () => setImageState(!image)}>
<img src={image ? "/images/" + image1 : "/images/" + image2} alt="" />
</div>
)
}
So this works as intended. When I click, the state changes, and so does the image. However, I would like there to be a fade in/out effect when the state changes. How is this achieved ?
I'm not sure if it's possible to animate via CSS the src attribute of an image element (I personally prefer to do it via CSS if possible). However you can animate its opacity property. And you'll need two elements for that - one for the fade-out effect and one for the fade-in. Here's a sandbox. The situation is very similar to this question, there you can see how to put images on top of each other (the one hidden).
Some things to note:
I've pre-set the two images' src attributes and don't set them to
nulls or some falsy values so that we don't see broken image icon while animating (could
occur if you have your state separated among multiple useState
hooks). In my case I batch changes at once to have only a single render and avoid any flashes of broken image icon.
Browser will do the animation upon class change and of course if the
property in this class can be animated. opacity is a CSS property which can be
animated.
For your case you'll probably need to set the src dynamically in your
handler so I'd recommend you make sure you don't cause multiple
renders/paints to avoid visual inconsistencies, so I think you should batch your state updates at once.
In my case the images are next to each other, but if you want to first fade-out the first image and then fade-in the second, you'll need to synchronize animation with transition-delay property.
You could some Animation library like GSAP and accomplish this, as this is difficult to accomplish by css alone.
https://codepen.io/rohinikumar4073/pen/mdVYbrm?editors=1111
function toggleImage() {
let tween = TweenLite.to(".img", 2, {
opacity: 0,
onComplete: function() {
let image = document.querySelector(".img")
if (image.src === "https://via.placeholder.com/350") {
image.src = "https://via.placeholder.com/150";
} else {
image.src = "https://via.placeholder.com/350";
}
let tween2 = TweenLite.to(".img", 2, {
opacity: 2
});
}
});
}
<script src=https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<div onclick="toggleImage()">
<img class="img" id="img1" src="https://via.placeholder.com/150" />
</div>

Adding a background image using reactjs

import Background from './img/steamledges.jpg';
const myStyles = {
backgroungImage: `url( ${Background} )`,
height: '50vh',
backgroungSize: 'cover',
}
i tried using this code and it didn't work.
What I understand from your problem, is you want to add an image using the inline-style backgroundImage right ?
What about this ? Instead of using your image as a component because it won't works. Only SVG can be used as component when you import them.
Check it out :
`backgroundImage: require('./path/to/your/img.extension)`
Tell me if you've solved the problem

what does this syntax in styled-components actually mean?

I've just started using styled-components and saw that they call what i presume is a function like so:
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`
I've never seem that syntax before and wanted to know if someone could point me to some docs about what it actually is.
It's called tagged template literals. The "tag" is the function before the template literal, which is called with its parameters being the template and template's variables. The parameters are as follow:
An array with all the string parts between the ${variables}.
First ${variable} of the template.
Second ${variable} of the template.
etc...
For example, I have written a function named tag that does the same as the function template literals use to process when you don't specify any tag function (a.k.a its default function):
function tag(stringParts, ...values){
return stringParts.reduce((accum, part, index) => accum + values[index-1] + part);
}
Calling it this way
tag`Hello, ${name}! I found ${count} results.`
yields the same result as
`Hello, ${name}! I found ${count} results.`
and the params fed to the tag function are ['Hello, ', '! I found ', ' results.'], name and count.
That's how you set the CSS rules for the <button> element.
So then you can use it as such:
<Button>Hello world</Button>
and all the styles you wrote above would get applied to all <Button> elements
Styled-components is a library used for styling react components.
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`;
`` <-- these are template literals which was introduced in ES6.
styled is an object here and when you say styled.button it means that we are styling html tags. So you can style a div, container, h1 etc. You want to use standard css to style these html tags and styled-components create a random classname for the same.
let's say you want to style a div. You name it a Wrapper. The naming covention is first letter always capital.
const Wrapper = styled.div`
background: #c0c0aa; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #1cefff, #c0c0aa); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #1cefff, #c0c0aa); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
height: 100%;
width: 100%;
`;
now you can wrap your content in render () of react.
<Wrapper>
//Your code in render of react class goes here
//thus instead of <div className = 'Wrapper'>
//you use the above code
//styled-components automatically generates random classnames solving major problems
</ Wrapper>
for more information see Max Stoiber's keynote at React Amsterdam.
https://www.styled-components.com/docs/basics#motivation

Is it possible to combine 'px' and 'vh' into the height of 1 component in react js

I have a few components and some of them are sized with px. The others I want to be variable size. However, the ones that are variable size are not a constant percentage of the page because of the components with a fixed px height. So I want a component to be about 80% of the screen height('80vh') minus the height of the other component. I was hoping to use something like
style={{height:'80vh-40px'}}
but that does not work.
I found this page which gets close but that my program does not recognize that calc function. Do I need to require it from some library maybe?
Any ideas on how to make this work?
Thanks!
I use syntax like this in my React.js components:
<div style={{height: 'calc(100vh - 400px)'}}></div>
it works for me.
Inside CSS code with LESS preprocessor I use the same syntax, but not equal:
.right_col {
height: calc(~"100vh - 400px");
}
In my experiments, I found that symbol "~" doesn't work in React.js components.
A way to solve it is by using style={} in your component.
const styles = {targetDiv: { height: 'calc(100vh - Xpx)'}}
then...
<div style={styles.targetDiv}>
...
</div>
Note - you can get the window.innerHeight (see http://ryanve.com/lab/dimensions/ for height and width options in javascript) and just calculate this yourself in react and set the width or height in pixels.
If you do this with height, you'd need to recalculate if it changes
state = {
windowHeight: window.innerHeight
}
componentWillMount () {
window.addEventListener('resize', this.handleResize)
}
componentWillUnmount () {
window.removeEventListener('resize', this.handleResize)
}
handleResize = () => {
this.setState({ windowHeight: window.innerHeight })
}
in your div
<div style={{height: this.state.windowHeight}} > ... </div>
You wouldn't want to do this everywhere, but it's very handy for some situations. For example - setting 100% height on Android mobile web, where 100vh does not work and device buttons cover up part of the screen.

Resources