Unable to change BG Color through props - javascript

I've googled for endless hours to try and understand why this doesn't work I've heard a state setting system could be a possible solution, but I want to know if this works before proceeding. This should be much simpler to resolve the problem if possible.
In my CSS file I am using the following line of code in order to grab data from the parent.
.cards__item__pic-wrap::after {
background-color: attr(data-Color);
}
I set this variable like so in the parent JS file
data-Color = {props.color}>
I am able to get the backgroundColor to change when I do something like style = {{backgroundColor: props.color}} which is a common solution for many people. BUT that directly edits the style instead of the pseudo style I need in CSS (the .cards__item__pic-wrap::after)
My current code doesn't even display any background color and I have a feeling attr() is not returning my data properly and causing this.
Full code below:
Cards.css
.cards__item__pic-wrap::after {
content: attr(data-category);
position: absolute;
bottom: 0;
margin-left: 10px;
padding: 6px 8px;
max-width: calc((100%) - 60px);
font-size: 16px;
font-weight: 700;
color: #fff;
background-color: attr(data-Color);
box-sizing: border-box;
}
Cards.js
import CardItem from './CardItem';
import "./Cards.css"
function Cards() {
return (
<div className='cards'>
<h1> Keep up with the latest information.</h1>
<div className = "cards__container">
<div className = "cards_wrapper">
<ul className= "cards__items" >
<CardItem
src='/images/test.jpg'
text = "Guild's are finally released! Which batch are you?"
label ="Guild News"
color = '#1f98f4'
alt = "test"
path = "/not in use"/>
</ul>
</div>
</div>
</div>
);
}
export default Cards;
CardItem.js
import {Link} from 'react-router-dom';
function CardItem(props) {
return (
<>
<li className = "cards__item" >
<Link className= "cards__item__link" to = {props.path}>
<figure className = "cards__item__pic-wrap" data-category = {props.label} data-Color = {props.color}>
<img src = {props.src} alt= {props.alt} className = "cards__item__img" />
</figure>
<div className = "cards__item__info">
<h5 className ='cards__item__text'>{props.text}</h5>
</div>
{props.color}
</Link>
</li>
</>
);
}
export default CardItem;

You can achieve your goal using this code !
//in your css file
.cards__item__pic-wrap {
background-color: var(--data-color);
}
// in your CardItem.js file
<figure style={{ '--data-color': props.color, }} className="cards__item__pic-wrap" data-category={props.label}>
<img src={props.src} alt={props.alt} className="cards__item__img" />
</figure>

You could do something like this in your css:
.cards__item__pic-wrap[data-Color] {
background-color: attr(data-Color)
}
you would only be modifying the pic wrappers which have that property defined. In your component check if data-Color has been set otherwise render it without data-Color on
so if prop.color is undefined render like so:
<figure className = "cards__item__pic-wrap" data-category = {props.label}>
<img src = {props.src} alt= {props.alt} className = "cards__item__img" />
</figure>
otherwise
<figure className = "cards__item__pic-wrap" data-category = {props.label} data-Color = {props.color}>
<img src = {props.src} alt= {props.alt} className = "cards__item__img" />
</figure>

Related

How to change css property in react

I want to change css width property of my element on some condition
<div className="consoleLayoutRoot-sideMenu">
<ConsoleSideMenu />
</div>
css
.consoleLayoutRoot-sideMenu .ant-menu {
padding-top: 30px;
/* background-color: #191146 !important; */
}
I am doing this way..but nothing is happening
document.getElementsByClassName("conjnjnot-sideMenjnjbhbhu.annjn ").style.width = "77px";
That's not working because you're treating a list as though it were an element. But it's also fundamentally not how you would do this in a React project.
Instead, you'd have the component re-render when the condition becomes true (perhaps by setting a state member). When rendering the div, you optionally include a style or a class name depending on whether you want the width applied:
<div className={`consoleLayoutRoot-sideMenu ${shouldHaveWidthClass ? "width-class" : ""}`}>
<ConsoleSideMenu />
</div>
...where .width-class { width: 50px; } is in your stylesheet.
Or with inline style, but inline styles are best avoided:
<div className="consoleLayoutRoot-sideMenu" style={shouldHaveWidthSetting ? { width: "50px" } : undefined}>
<ConsoleSideMenu />
</div>
Here's an example (using a class);
const {useState} = React;
const ConsoleSideMenu = () => <span>x</span>;
const Example = () => {
const [includeWidth, setIncludeWidth] = useState(false);
const toggle = ({currentTarget: { checked }}) => {
setIncludeWidth(checked);
};
return <React.Fragment>
<div className={`consoleLayoutRoot-sideMenu ${includeWidth ? "width-class" : ""}`}>
<ConsoleSideMenu />
</div>
<label>
<input type="checkbox" onChange={toggle} checked={includeWidth} />
Include width class
</label>
</React.Fragment>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
.width-class {
width: 50px;
}
.consoleLayoutRoot-sideMenu {
border: 1px solid blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

I am trying to have a second slider on the same page but its not working

I am trying to have a second slider on the same page but its not working.
The first one works fine but the second one is not working. I think there is something wrong with the parent element method but cant wrap my head around it.
var ids = ["view_0", "view_1", "view_2", "view_3"]
let current_id = 0;
function next(productnr) {
if (document.getElementById(ids[current_id]).parentElement.id == productnr) {
let last_array_position = ids.length;
document.getElementById(ids[current_id]).classList.remove("show");
current_id++;
if (current_id >= last_array_position) {
current_id = 0;
}
document.getElementById(ids[current_id]).classList.add("show");
}
}
#1 img {
display: none;
}
#1 img.show {
display: block;
}
<article id=1>
<img class="show" id="view_0"></img>
<img id="view_1"></img>
<img id="view_2"></img>
<img id="view_3"></img>
<button><</button>
<button onclick="next(1)">></button>
<article id=2>
<img class="show" id="view_0"></img>
<img id="view_1"></img>
<img id="view_2"></img>
<img id="view_3"></img>
<button><</button>
<button onclick="next(2)">></button>
The reason your code doesn't work is that you are making use of the same id for both sliders in HTML. This will always update the former but never change the latter slide by your JavaScript function. Also, your code has a few issues like the tags aren't closed properly, no src attributes. Looks like you need multiple arrays for storing ids of multiple sliders, and multiple functions to handle previous and next buttons.
Here's a common function to handle all buttons of multiple sliders on a single page without any arrays:
function next(productId, next) {
var tags = document.getElementById(productId).getElementsByTagName("img");
var index;
for (let i = 0; i < tags.length; i++) {
if (tags[i].className == "show") {
index = i;
break;
}
}
tags[index].classList.remove("show")
index = next ? (index + 1) : (index - 1);
index = index == tags.length ? 0 : index == -1 ? tags.length - 1 : index;
tags[index].classList.add("show")
}
img {
display: none;
width: 100px;
height: 100px;
object-fit: cover;
}
img.show {
display: block;
}
<div id="product1">
<img class="show" src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg" />
<img src="https://images.ctfassets.net/hrltx12pl8hq/61DiwECVps74bWazF88Cy9/2cc9411d050b8ca50530cf97b3e51c96/Image_Cover.jpg?fit=fill&w=480&h=270" />
<img src="https://images.unsplash.com/photo-1453728013993-6d66e9c9123a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8dmlld3xlbnwwfHwwfHw%3D&w=1000&q=80" />
<img src="https://www.gettyimages.com/gi-resources/images/500px/983794168.jpg" />
<button onclick="next('product1', 0)">Prev</button>
<button onclick="next('product1', 1)">Next</button>
</div>
<div id="product2">
<img class="show" src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg" />
<img src="https://images.ctfassets.net/hrltx12pl8hq/61DiwECVps74bWazF88Cy9/2cc9411d050b8ca50530cf97b3e51c96/Image_Cover.jpg?fit=fill&w=480&h=270" />
<img src="https://images.unsplash.com/photo-1453728013993-6d66e9c9123a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8dmlld3xlbnwwfHwwfHw%3D&w=1000&q=80" />
<img src="https://www.gettyimages.com/gi-resources/images/500px/983794168.jpg" />
<button onclick="next('product2', 0)">Prev</button>
<button onclick="next('product2', 1)">Next</button>
</div>
The id attribute defines an identifier (ID) which must be unique in the whole document,
In your code you are using the same ID for multiple elements,
For what you are trying to do, I would suggest to use querySelector to select the elements as this will enable us to select exactly the component with the given id under the given slider since there are multiple elements with same id (In such repetitive case, the suggested way is using class instead of id).
I am taking a counter_id as counter of image for each slider having the id as the key of the slider.
Here, I updated the slider id as a1 and a2 for better understanding.
#${productnr}>.show#${ids[current_id[productnr]]} => select the element with class .show and id #view_0 (or so on as per counter_id of the slider) under the the element with id a1 (or a2) i.e. slider element.
We perform add and remove class operation on the element.
var ids = ["view_0", "view_1", "view_2", "view_3"]
let current_id = {
a1: 0,
a2: 0
}; //image counter for each slider having the id as the key of slider
function next(productnr) {
let last_array_position = ids.length;
let pic = document.querySelector(`#${productnr}>.show#${ids[current_id[productnr]]}`);
pic.classList.remove("show");
current_id[productnr]++;
if (current_id[productnr] >= last_array_position) {
current_id[productnr] = 0;
}
document.querySelector(`#${productnr}>#${ids[current_id[productnr]]}`).classList.add("show");
}
function prev(productnr) {
let last_array_position = ids.length;
let pic = document.querySelector(`#${productnr}>.show#${ids[current_id[productnr]]}`);
pic.classList.remove("show");
current_id[productnr]--;
if (current_id[productnr] < 0) {
current_id[productnr] = last_array_position - 1;
}
document.querySelector(`#${productnr}>#${ids[current_id[productnr]]}`).classList.add("show");
}
#a1 img {
display: none;
}
#a1 img.show {
display: block;
}
<article id="a1">
<img src="https://picsum.photos/id/1/200" class="show" id="view_0"></img>
<img src="https://picsum.photos/id/2/200" id="view_1"></img>
<img src="https://picsum.photos/id/3/200" id="view_2"></img>
<img src="https://picsum.photos/id/4/200" id="view_3"></img>
<button onclick="prev(`a1`)"><</button>
<button onclick="next(`a1`)">></button>
<article id="a2">
<img src="https://picsum.photos/id/50/200" class="show" id="view_0"></img>
<img src="https://picsum.photos/id/60/200" id="view_1"></img>
<img src="https://picsum.photos/id/70/200" id="view_2"></img>
<img src="https://picsum.photos/id/80/200" id="view_3"></img>
<button onclick="prev(`a2`)"><</button>
<button onclick="next(`a2`)">></button>
</article>
</article>

How do I create an overlay in React?

I am currently trying to create an overlay on an image when hovering. I am able to get a box displayed on screen but it's not placed over the image.
featured.js
const Featured = ({ images }) => {
if (!images || !Array.isArray(images)) return null;
return (
<section className={styles.featuredWrapper} id="work">
{images.map((image) => {
return (
<div className={styles.wrap}>
<GatsbyImage
image={image.gatsbyImageData}
alt="Link to the alt text"
className={styles.featuredImg}
/>
<div className={styles.featuredOverlay}>Test</div>
</div>
);
})}
</section>
);
};
featured.module.css
.featuredImg {
width: 100%;
position: relative;
}
.featuredOverlay {
position: absolute;
background: black;
opacity: 0.5;
width: 100%;
height: 100%;
z-index: 1;
}
Every explanation I see revolves around the use of positions absolute and relative which makes me think my issue is how I am rendering my component. Am I using the position properties on the wrong elements?
import { useState } from "react";
import "./styles.css";
function Home() {
const [showOverlay, setShowOverlay] = useState(false);
return (
<div>
<div className="main-container">
<div className="main-container__grid">
<img
src="https://miro.medium.com/max/2000/1*3SjDVyFY09xZ7NYMO5kj0g.png"
className="test"
alt="Placeholder"
onHover={() => setShowOverlay(true)}
/>
{showOverlay && <div className="targeting-box" />}
</div>
</div>
</div>
);
}
export default Home;

Image Gallery: how to remove and add class when clicking an image

Beginner here.
I have a small image gallery, with two classes declared in CSS:
imagem: selected image, with border
imagem-activa: all the others, without border
How can i use JavaScript to add/remove the classes when the user clicks one image? I already know how to do it in jQuery, but want to learn also pure JS.
HTML
<div class="exercicio">
<h2 class="titulo">
Exercício 4
</h2>
<img src="img/imagem1.jpg" class="imagem imagem-activa" />
<img src="img/imagem2.jpg" class="imagem" />
<img src="img/imagem3.jpg" class="imagem" />
<img src="img/imagem4.jpg" class="imagem" />
</div>
CSS
.imagem{border:5px solid #000;opacity:0.5;cursor: pointer;}
.imagem-activa{border:5px solid #ff0066;opacity:1;}
JS
This part i can't make it work. Can someone help me?
var imagens = document.getElementsByClassName("imagem");
var imagemActual = 0;
for(var i = 0; i < imagens.length; i++) {
imagens[i].addEventListener("click", function() {
imagens[imagemActual].classList.remove("imagem-activa");
this.classList.add("imagem-activa");
imagemActual = i;
});
}
This is my working jQuery solution
$(".imagem").click(function() {
$(".imagem").removeClass("imagem-activa");
$(this).addClass("imagem-activa");
});
So, what is happening here is that anytime any of your click handlers is invoked, your variable imageActual gets set to the current value of i which will always be 4 because this is the final value of i after the for loop. For the first click, you might not run into any errors and you might get the expected result. But as soon as any of your event listeners has run, the value of imagemActual will be 4 and that will cause an error on any future invocation of your event listeners because imagens[4] will be undefined.
There are a few ways to solve this.
1) bind
You can bind the (temporary) value of i inside the loop to the event listener function:
var imagens = document.getElementsByClassName("imagem");
var imagemActual = 0;
for(var i = 0; i < imagens.length; i++) {
imagens[i].addEventListener("click", function(index) {
imagens[imagemActual].classList.remove("imagem-activa");
this.classList.add("imagem-activa");
imagemActual = index;
}.bind(imagens[i], i));
}
.imagem {
width: 20px;
height: 20px;
background-color: blue;
}
.imagem.imagem-activa {
background-color: red;
}
<div class="exercicio">
<h2 class="titulo">
Exercício 4
</h2>
<img src="" class="imagem imagem-activa" />
<img src="" class="imagem" />
<img src="" class="imagem" />
<img src="" class="imagem" />
</div>
2) let
If you can use ES6, you can use let which will make sure that your counting variable is a unique instance for every value that is applied:
const imagens = document.getElementsByClassName("imagem");
let imagemActual = 0;
for(let i = 0; i < imagens.length; i++) {
imagens[i].addEventListener("click", function() {
imagens[imagemActual].classList.remove("imagem-activa");
this.classList.add("imagem-activa");
imagemActual = i;
});
}
.imagem {
width: 20px;
height: 20px;
background-color: blue;
}
.imagem.imagem-activa {
background-color: red;
}
<div class="exercicio">
<h2 class="titulo">
Exercício 4
</h2>
<img src="" class="imagem imagem-activa" />
<img src="" class="imagem" />
<img src="" class="imagem" />
<img src="" class="imagem" />
</div>

displaying child div on hover on parent div in react js

Hello :) I am relatively new to react js, i am trying to apply animation on a div that is a child of another div, parent div " portfolio-product-item " displays featured image extracted from wp rest api, and child div " portfolio-product-item-details " has the contents of the post.
What i want to do is display the content when hovered over the featured image in parent div , my code is like this , how can i achieve it?
import React from 'react';
import Home from './Home';
require ('../../app.css');
require ('../../animate.min.css');
class Portfolio extends React.Component{
render(){
console.log(this.props.data.length);
var contents=[];
for (var i = 0; i < this.props.data.length; i++) {
contents.push(
<div className="col-xs-12 col-md-4">
<div id="portfolio-product-item" >
<img src={this.props.data[i].featured_image} />
<div ref= "productDetails" id ="portfolio-product-item-details" dangerouslySetInnerHTML={{__html: this.props.data[i].content.rendered}} />
</div>
</div>
);
}
return(
<div className = "container">
<div className="row">
<section className="portfolio">
<h1>Our Latest Work</h1>
<p id="below-header">These are some of the works that has been keeping us busy over the years. See for yourself what we can do.</p>
<div className="col-xs-12 ">
{contents}
</div>
</section>
</div>
</div>
)
}
}
export default Portfolio;
React allows to add / remove elements from the virtual DOM. Use the onMouseEnter and onMouseLeave to set show / hide state.
<img
onMouseEnter={() => this.setState({ show: true })}
onMouseLeave={() => this.setState({ show: false })}
/>
Then show / hide details based on the state:
{this.state.show ?
<div ref= "productDetails" id ="portfolio-product-item-details"
dangerouslySetInnerHTML={{__html: this.props.data[i].content.rendered}}
/>
: null}
My solution was something like this
import React from 'react';
import Home from './Home';
require ('../../app.css');
require ('../../animate.min.css');
class Portfolio extends React.Component{
render(){
var contents=[];
for (var i = 0; i < this.props.data.length; i++) {
var productImage ={
backgroundImage:'url('+ this.props.data[i].featured_image + ')',
backgroundSize: '100% 100%'
}
contents.push(
<div className="col-xs-12 col-md-6 col-lg-4">
<div id="portfolio-product-item" style ={productImage} >
<div ref= "productDetails" id ="portfolio-product-item-details" dangerouslySetInnerHTML={{__html: this.props.data[i].content.rendered}} />
</div>
</div>
);
}
return(
<div className = "container">
<div className="row">
<section className="portfolio">
<h1>Our Latest Work</h1>
<p id="below-header">These are some of the works that has been keeping us busy over the years. See for yourself what we can do.</p>
<div className="col-xs-12 ">
{contents}
</div>
</section>
</div>
</div>
)
}
}
export default Portfolio;
and css rules were like this
section.portfolio div#portfolio-product-item{
height:370px;
width:100%;
background: #f0f0f0;
margin:15px;
position:relative;
transform: rotate(4deg) ;
box-shadow: 5px 5px 5px #909090;
-webkit-font-smoothing: antialiased;
}
section.portfolio div#portfolio-product-item-details{
height:100%;
width:100%;
padding:10px;
text-align: center;
color:#ffffff;
position: absolute;
top:0;
background-color: #000000;
opacity:0;
}
section.portfolio div#portfolio-product-item-details:hover{
cursor:pointer;
opacity:0.9;
transition: all .5s ease-in-out;
}

Categories