I wrote a calculator App in React and generally, it's ok, but...
If I hold it longer I notice that the click is confirmed if click-down had been on the button and click-up have been on the button
I know that margin is not clickable, but in this App I can't use, for example, position
The point is that the button is animated and when click-up, cursor is not over the button. And I have a question that is there a way to prevent the whole problem in any way, so that it works the way it should?
Here's the link to the repo: https://github.com/FloweDewolf/calculator
Here's the link to the calculator: https://flowedewolf.github.io/calculator
And thanks for every help!
One solution here would be to use a pseudo-element for the styling. This way the actual button bounds (red border) will stay in place. It also prevents writing additional logic to solve a styling issue.
let count = 0;
function handleClick() {
document.getElementById('counter').innerHTML = ++count;
}
button {
position: relative;
background: transparent;
width: 5rem;
height: 5rem;
border: 1px solid red;
z-index: 1;
}
button::before {
position: absolute;
content: ' ';
left: 0;
top: 0;
height: 4rem;
width: 4rem;
background: #ff9999;
z-index: -1;
}
button:active::before {
left: 1rem;
top: 1rem;
}
<button type="button" onclick="handleClick()">Add 1</button>
<p>current count: <span id="counter">0</span></p>
I'm getting a background-color from an API, variable name settings.brand_color.
I want to use that variable in html element. I cant use style attribute becuase I'm using :before selector in my app.
I want to pass that API variable in my css file and use it in my :before pseudo selector.
JSX
<>
<input
type="radio"
name="language-select"
className="focus:ring-0 mr-5 my-18p default-style radio__input"
/>
<div className="radio__radio"></div>
</>;
CSS
.radio__radio {
width: 24px;
height: 24px;
background-color: #d8d8d8;
border-radius: 50%;
box-sizing: border-box;
padding: 6px;
margin-right: 20px;
z-index: 1;
}
.radio__radio::after {
content: "";
width: 100%;
height: 100%;
display: block;
background: #f28b46;
border-radius: 50%;
transform: scale(0);
z-index: 9;
}
Update
Another solution for this issue is to just use before & after from tailwinds
Pseudo-elements
While you cannot directly set the styling of a pseudo element in JS you can set a CSS variable and this can be picked up by the class setting for the pseudo element.
.radio__radio {
width: 24px;
height: 24px;
background-color: #d8d8d8;
border-radius: 50%;
box-sizing: border-box;
padding: 6px;
margin-right: 20px;
z-index: 1;
--bg: #f28b46; /* ADDED for initial condition */
}
.radio__radio::after {
content: "";
width: 100%;
height: 100%;
display: block;
background: var(--bg);
border-radius: 50%;
transform: scale(0);
z-index: 9;
}
Then in your Javascript when you get a new background color:
document.querySelector('.radio__radio').style.setProperty('--bg', newvalue);
or of course select all such radio buttons and change for each one if that is what is required.
You can use CSS Custom Properties as variables for the colors, using the :root class:
:root {
--brand-color: #f28b46;
}
.radio__radio {
width: 24px;
height: 24px;
background-color: #d8d8d8;
border-radius: 50%;
box-sizing: border-box;
padding: 6px;
margin-right: 20px;
z-index: 1;
}
.radio__radio::after {
content: "";
width: 100%;
height: 100%;
display: block;
background: var(--brand-color);
border-radius: 50%;
// transform: scale(0);
z-index: 9;
}
<div class="radio__radio"></div>
And when fetching the brand color from the API, create a style tag and update the :root brand color.
Note: the last :root variable will override any previous :root variable, so you need to make sure you create the <style> with the brand color after your initial CSS file.
:root {
--brand-color: yellow; // will be overridden
}
:root {
--brand-color: red; // that's the color that will show
}
I got the idea that you're using react, so you can do this like this:
const [brandColor, setBrandColor] = useState();
useEffect( () => {
fetchBrandColorFromAPI().then(brandColor => setBrandColor(brandColor));
}, [])
And then in the renderer:
{brandColor && <style dangerouslySetInnerHTML={{ __html: ` :root {
--brand-color: ${brandColor}
}`}} /> }
The best & easiest possible way is to add style in JSX code.
<input
id={languageLabel}
type="radio"
name="language-select"
value={languageLabel}
// defaultChecked={index === 0}
onChange={() => {
onLanguageChange(language, languageLabel);
}}
className="focus:ring-0 mr-5 my-18p default-style radio__input"
/>
Just add this part to your JSX File
<style>
{`
.radio__radio::before {
background-color: ${settings.brand_color}
}
`}
</style>
The issue is that you can't manipulate pseudo-elements in javascript; however, there are still a couple of options to manipulate them by knock-on effect.
Option 1: As A Haworth suggested, use a CSS variable.
Option 2: If you know there's only going to be a few different colours; then you could just toggle a class indicating which colour it should be. For instance, if you set the CSS up in a similar structure to this:
.radio__radio {
width: 24px;
height: 24px;
background-color: #d8d8d8;
border-radius: 50%;
box-sizing: border-box;
padding: 6px;
margin-right: 20px;
z-index: 1;
}
.radio__radio::after {
content: "";
width: 100%;
height: 100%;
display: block;
border-radius: 50%;
transform: scale(0);
z-index: 9;
}
.radio__radio.green::after{
background-color: #000066 /* Silly colour as an example */
}
.radio__radio.blue::after{
background-color: #006600 /* Silly colour as an example */
}
.radio__radio.red::after{
background-color: #660000 /* Silly colour as an example */
}
Then your javascript
var d = document.getElementsByClassName("radio__radio"); /* This way supports older browsers */
d.className += " otherclass";
Or if usimg jQuery
$('.radio__radio').addClass('green').removeClass('red').removeClass('blue');
There is no way I know of for you to directly inject a runtime variable from your API without using the javascript as a middle-man - there may be a way to do it with Blazor, but I haven't yet come across it.
<!DOCTYPE html>
<html>
<head>
<title>
How to define colors as variables in CSS?
</title>
<style>
:root {
--primary-color: rgb(15, 157, 88);
--secondary-color: rgb(255, 255, 255);
}
.first {
width: 50%;
padding: 40px 0px;
margin: 10px 0px;
text-align: center;
/* Apply color using CSS var */
background-color: var(--primary-color);
color: var(--secondary-color);
}
.second {
width: 50%;
padding: 40px 0px;
text-align: center;
/* Apply color using CSS var */
background-color: var(--primary-color);
color: var(--secondary-color);
}
</style>
</head>
<body>
<div class="first">
<h1>Stackoverflow</h1>
</div>
<div class="second">
<h1>gyan-js</h1>
</div>
</body>
</html>
I'm new to React so, I'll provide the answer with Vannila JS.
The color change can be done in the following steps:
Set a root css variable :root{ --myColor: #545454; }
Set the DOM element's color to the css variable declared in the root like color: var(--myColor);
Since, you mentioned that the element is not loaded yet so there is not point in what color this myColor has because it has not effect except the variable itself because we will use it in JS to change it.
In JS, Get the Color from the API response and store it in a variable
Use document.documentElement to set the color of the css variable myColor with the color we get from the API
All the elements with the color of the CSS variable will also change.
The Element which gets loaded will have the color by then.
// I couldn't find a fake API response giving a Color, so this function mocks the API which gives the color string after 2 seconds.
let getColorFromAPI = new Promise((resolve) => {
setTimeout(function() {
resolve('#FFFFFF')
}, 2000)
});
async function main() {
console.log("The Existing Color is: ", getComputedStyle(document.documentElement).getPropertyValue('--mainColor'))
console.log('Getting the Color from the API... ')
let newColor = await getColorFromAPI // Get the color from API
console.log('The New Color is: ', newColor)
document.documentElement.style.setProperty('--mainColor', newColor) // Changing the color of the CSS variable
}
main()
:root {
--mainColor: #545454;
}
.buttonElement {
background-color: var(--mainColor);
}
<button class="buttonElement">See the Color of this button</button>
To Wrap things up:
The function gets the color from the API and we set the color using document.documentElement.style.setProperty
You can also create a dummy class with just the background-color and append it to the element since, Browser computes the style with the latest CSS style declaration.
Hope this helps.
I had a similar problem one time that I actually solved by using another div element instead of the pseudo element. I apologize if that doesn't work for your specific use case, since you said you wanted to use the pseudo element. However, since it seems like you have access to the JS, JSX, and CSS, it might be something you could consider.
The before and after pseudo elements are almost equivalent to div elements placed as the first or last child of the parent element so adding another div like this
<div className="radio__radio">
<div
className="radio__radio__after"
style={{ backgroundColor: apiColor || '#f28b46' }}
></div>
</div>
and changing your second CSS selector like this
.radio__radio__after {
content: "";
width: 100%;
height: 100%;
display: block;
border-radius: 50%;
transform: scale(0);
z-index: 9;
}
to allow the background color to be controlled by the style prop should work - although you might need to make some slight adjustments to the CSS or JSX.
Let's say I have a function that changes the Align Self css property via JS.
HTML
<img id= "arrow" src="/images/leftarrow.svg">
CSS
.container {
background-color: $white;
box-shadow: 2px 0px 4px 1px black;
width: 400px;
height: 100vh;
display: flex;
flex-direction: column;
visibility: visible;
position: relative;
z-index: 2;
}
#arrow {
height: 25px;
width: 25px;
position: absolute;
align-self: flex-end;
top: 50vh;
cursor: pointer;
background-color: $white;
border-radius: 50%;
}
JS
function reverseIcon () {
arrow.style.alignSelf = "flex-start";
}
arrow.addEventListener("click", reverseIcon);
Javascript doesn't seem to change the align self property straight away. When I click, it does not change. I jumped into devTools to see what was wrong and it was applied when there was a change in the screen(?). I have no media queries. I tried this on 3 different browsers but AlignSelf doesn't seem to show up on the screen right away. It only actually changes as soon as I jump into devtools or like change the size of the screen. Anyone know why?
**Nevermind, Seems like only Chrome isn't responding to it. Still don't understand what part of this code isn't compatible with Chrome then
Are you sure the alignSelf property gets applied when you change your screen size?
Or is it just the default bahavior? In Dev-Tools, if you inspect, do you see the style-attribute at your image element? If yes, than it could be that your #arrow selector overrides it. If that's the case, I would try to toggle between a class where you can use the !important rule to override the property. Like so:
.flex-start{
align-self: flex-start !important;
}
I am using dynamic content in my react app. The content is loading fine. I am trying to change the style of the paragraph tag on the basis of a dynamic value. The style also changes on click event of the paragraph tag. When I click the paragraph the text is changing but the previous selected styles remains in effect and does not change with the dynamic value. Code which is changing the style is
if(ans){
return ans.map((a, index) => {
return(
<div className="options-container" key={index}>
<p onClick={this.handleOptionClick} className={a.IsChecked ? 'option-selected' : 'option'}>{a.Awnser}</p>
</div>
)}
);
}
the style for this is
.options-container {
display: inline-block;
width: 30%;
}
.option {
background-color: $blue;
border-radius: $button-radius;
color: $white;
cursor: pointer;
margin: $md auto;
padding: $normal;
transition: 0.3s linear all;
text-align: center;
width: 90%;
}
.option-selected {
background-color: $green;
border-radius: $button-radius;
color: $white;
cursor: pointer;
margin: $md auto;
padding: $normal;
transition: 0.3s linear all;
text-align: center;
width: 90%;
}
Problem seems to be with a.IsChecked, rest of the code looks correct. Confirm whether its value is updating in the component.
here what I did. I think you are missing something. please take a look if you find some idea.
handleOptionClick = () => {
this.setState({ answer: "here is your new value", IsChecked: true });
};
render() {
return (
<div>
<p
onClick={this.handleOptionClick}
className={this.state.IsChecked ? "option-selected" : "option"}
>
{this.state.answer}
</p>
</div>
);
}
This question already has answers here:
Get/Set CSS property values via Javascript: questions
(3 answers)
How can I programmatically copy all of the style attributes from one DOM element to another
(3 answers)
Closed 3 years ago.
I am trying to set the visibility of a div element to visible or hidden depending on the previous state. i.e, I am trying to set the visibility to hidden when the element was previously visible and vice versa with an on click event.
html:
<div id="cartwin"></div>
css:
#cartwin {
position: fixed;
z-index: 9999;
right: 0%;
top: 7%;
background-color: black;
border: 1px solid white;
border-radius: 5px;
height: 40%;
width: 25%;
visibility: hidden;
}
js:
cart.onclick = function togglecart() {
const cart = document.getElementById('cartwin').style.visibility;
if (cart == 'visible') {
cart = 'hidden';
}
else if (cart == 'hidden') {
cart = 'visible';
}
}
This code has no effect at all, and I am inclined to believe it has to do with my if tests after a bit of looking around, but i could not find anything out.
You will have to use window.getComputedStyle
See comment inside the code and check the console when clicking
var cart = document.querySelector('.cart');
var cartwin = document.getElementById('cartwin')
cart.onclick = function togglecart() {
var style = window.getComputedStyle(cartwin);
console.log(style.visibility);
// use style.visibility
// this is an option now you can handle
// what you have started with in your question
// and move on from here with rest of your code
// BUT before you do so, see the next snippet
// on how much simpler you could achieve what I believe you are trying
}
#cartwin {
position: fixed;
z-index: 9999;
right: 0%;
top: 7%;
background-color: black;
border: 1px solid white;
border-radius: 5px;
height: 40%;
width: 25%;
visibility: hidden;
}
<div class="cart">click on cart here</div>
<div id="cartwin">
<h4>lots of products in my cart</h4>
</div>
Above example is to fix the problem your were facing and showing a possible solution to it, but ...
Consider this snippet as a better solution
Here you will not handle the styles with javascript but just add/remove a class via javascript.
var cart = document.querySelector('.cart');
var cartwin = document.getElementById('cartwin')
cart.onclick = function togglecart() {
// handle the logic here in javascript
// but keep the styles where they belong => CSS
// all you need to do here is "toggle" a class name
cartwin.classList.toggle('active');
}
#cartwin {
position: fixed;
z-index: 9999;
right: 0%;
top: 7%;
background-color: black;
border: 1px solid white;
border-radius: 5px;
height: 40%;
width: 25%;
visibility: hidden;
}
#cartwin.active {
visibility: visible;
}
<div class="cart">click on cart here</div>
<div id="cartwin">
<h4>lots of products in my cart</h4>
</div>