Change css class attribute values using javascript - javascript

I want to change the value of one of the attributes of css class dynamically
Here's my scenario:
I've many elements using one class, instead of getting them all and looping them over and applying style, I want to change the value of one of the attributes of class, which is alredy applied on them. for example
.prodName {
max-width: 270px;
display: block;
}
above class is being used by many elements, and I want to alter one of the attributes of that class like
.prodName {
max-width: 350px <---
display: block;
}
is there any simple method for this in javascript.
Before I post this question, I already searched but didn't find anything easy and useful.
thanks in advance to helping hands.

You can use CSS variables for this case.
const root = document.querySelector(':root');
function play() {
root.style.setProperty('--size', '300px');
}
:root {
--size: 100px;
}
.container {
background-color: red;
width: var(--size);
height: var(--size);
cursor: pointer;
}
<div class="container" onclick="play()"></div>
The only problem with the above approach is support in older browsers. If you have to support IE, and older browsers where CSS variable support is not present, you can handle this problem by adding a class to the body/parent container.
function play() {
document.body.classList.add('large')
}
.container {
background-color: red;
width: 100px;
height: 100px;
cursor: pointer;
}
.large .container {
width: 300px;
height: 300px;
}
<div class="container" onclick="play()"></div>

Add new class to CSS:
.mw350 {
max-width: 350px;
}
Then add new class to the element in JS:
document.querySelector('.prodName').className += ' mw350'; // <-- better to select using unique IDs, like '#prodNameElement'

If you are going to control the css class/attribute change from ts, maybe with a function or var change, you might want to use ngClass: https://www.freecodecamp.org/news/angular-ngclass-example/ and have all the logic where you want it, easily accessible.

Related

How to change a css value in javascript?

So I want to change a css value in javascript, without having an element in html, I'll explain like:
<style>
.box{
width: 10%;
}
</style>
<script>
// I want to change the width value of (.box) to something like "90%"
</script>
So what I mean to say is that I want to change the (.box) width value between the two style tags, I know my question sounds weird, but am just new coding and I really need it, any help appreciated!
Use media queries.
I don't remember the exact way to do this, but something like:
.box { width: 90%; }
#media screen and (min-width: 1000px) {
.box { width: 40%; }
}
You can change the properties (e.g. width) of a CSSStyleDeclaration with its setProperty() method.
You can get a CSSStyleSheet of a specific <style> element with its sheet property.
In our case, the stylesheet's first CSSStyleRule (sheet.cssRules[0]) is for the CSS class .box. You get the CSSStyleDeclaration object of a CSSStyleRule with its style property.
Example:
const iClass = document.getElementById("i-class");
const classRule = document.getElementById("my-style").sheet.cssRules[0];
// Set input.value to initial width-value (10%)
iClass.value = classRule.style.getPropertyValue("width");
// Update width-value on each input
iClass.addEventListener("input", () => {
classRule.style.setProperty("width", iClass.value);
});
/* Ignore; presentational styling */
.box {
margin-bottom: .5rem;
aspect-ratio: 1/1;
background-color: coral;
text-align: center;
}
<style id="my-style">
.box{
width: 10%;
}
</style>
<div>
<label for="i-class">Class width:</label> <input id="i-class">
</div>
<div class="box">class</div>
Unlike adding a new CSS rule, this changes the existing rule.
Here's one option, adding a <style> tag dynamically. This will add a style which overrides previous, obviously. See other answers for other options of changing existing rules.
var inline_style = `
.box {
width: 90%;
background: pink;
}`;
// from https://stackoverflow.com/a/28662118/3807365
document.head.insertAdjacentHTML("beforeend", '<style>' + inline_style + '</style>')
.box {
width: 10%;
background: blue;
}
<div class="box">i'm a box</div>

CSS varibale in own style [duplicate]

This question already has an answer here:
How to set left and right CSS properties without setting top and bottom
(1 answer)
Closed 1 year ago.
I'am not profficient in html and css, so i dont even know how to search for a post here in StackOverflow I excuse my selfe beforehand if this is an duplicate.
i want to do something like this:
margin-horizontal
{
margin-left: var;
margin-right: var;
}
<div style="margin-horizontal: 50px">
Is there a way to accomplish this behavior?
CSS variables are possibly what you are looking for. Your example would look as follows.
CSS:
:root {
--space: 50px;
}
.margin-horizontal
{
margin-left: var(--space);
margin-right: var(--space);
}
HTML:
<div class="margin-horizontal">...</div>
To add to Chris05's answer: you can also programmatically set the CSS variables from JavaScript.
document.documentElement.style.setProperty('--space', '150px');
document.documentElement.style.setProperty('--space2', '20px');
:root {
--space: 50px;
--space2: 50px;
}
div {
color: white;
text-align: center;
background-color: #454545;
margin-top: 10px;
}
.margin-horizontal {
margin-left: var(--space);
margin-right: var(--space);
}
.margin-horizontal2 {
margin-left: var(--space2);
margin-right: var(--space2);
}
<div class="margin-horizontal">150px margins</div>
<div class="margin-horizontal2">20px margins</div>
Expanding on the answer by #chris05, if you want to have different values of margins for different divs, you can add a class that sets the CSS variable to a different value, for instance:
.m-25 {
--space: 25px;
}
.m-75 {
--space: 75px;
}
Then your default will be 50px, and if you want a different one you just add a modifier class:
<div class="margin-horizontal">Foo</div>
<div class="m-25 margin-horizontal">Bar</div>
and you'll see:
What exactly are you hoping to get?
If you want to use your css class in your html you want to give the div a class with the name 'margin-horizontal'. like this: div class="margin-horizontal"

CSS pseudo class disappears after variable value update via JS

I would like to be able to update a CSS variable via JS, but when I make the variable update the CSS pseudo element get's destroyed (i.e. just disappears).
Here's the SCSS code:
:root {
--test-thing: "";
}
.folder-1-open span::after {
width: 90%;
height: 85%;
bottom: 0;
left: 5%;
background-color: #fff;
z-index: 3;
content: var(--test-thing);
}
I'm trying to manipulate the variable thusly:
const root = document.documentElement
root.style.setProperty('--test-thing', "Hello World")
The CSS above works perfectly fine on the element (a label) that it's applied to, basically just a white square, but as soon as I try and update the CSS variable --test-thing to add a string via the content prop, the whole thing just disappears.
Is it not possible to do this with a pseudo element or class?
From researching related posts on SO, my understanding was that this was possible using CSS variables.
For context, I’m working off this example of a pure CSS interactive folder (when it’s open is when I’d like to update content proper dynamically).
Ok, I figured out why this is happening, sort of. Still not 100% sure why, but it has something to do with the fact that the new value isn't in quotes. Just put the value in quotes and it works fine.
const root = document.documentElement
root.style.setProperty('--test', "'Hello World'") // <-- this needs to be in quotes
:root {
--test: "";
}
#test {
height: 100px;
width: 100px;
background: #ccc;
}
#test:after {
content: var(--test);
min-width: 100px;
background: #000;
min-height: 30px;
color: #fff;
}
<div id="test">
</div>

JS Hover Over One Item to Make Another Move

I've got a simple text button with an image of an arrow next to it. I'm wanting the arrow image to move when someone hovers over the button.
I currently have this working in one instance with JS 'document.getElementById...', but I have several buttons across my site that I'd like to have the same behavior. My first thought would be to use a class instead of an id, and use the same functions.
For whatever reason, document.getElementsByClassName doesn't work - even in one instance.
Here's a simpler version to demonstrate - View on Codepen: https://codepen.io/sdorr/pen/JxYNpg
HTML
<HTML>
hover over me
<div id="block"></div>
hover over me
<div class="block"></div>
CSS
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
#block {
width: 30px;
height: 30px;
background-color: red;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
JS
function move() {
document.getElementById("block").style.marginLeft = "35px";
}
function moveBack() {
document.getElementById("block").style.marginLeft = "0px";
}
function moveAlt() {
document.getElementsByClassName("block").style.marginLeft =
"35px";
}
function moveBackAlt() {
document.getElementsByClassName("block").style.marginLeft =
"0px";
}
First off, why isn't the behavior with a class working but an id works fine?
Secondly, would a class solve this issue and be scalable across all buttons with the same two functions (onmouseover / onmouseout)?
If not, any ideas on a solution? I currently have a solution I found using jQuery that does work, but when hovering over one button, all arrow images move across the site. I don't necessarily mind this behavior because only one button is really in view at a time - but I'm trying to learn JS and solve problems with my own solutions!
I greatly appreciate your desire to learn on your own and not rely on premade solutions. Keep that spirit and you will go places!
When it comes to getElementsById, we know this should work for one element, since the function returns a single Element.
However, what does getElementsByClassName return?
(see: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName)
It returns an HTMLCollection which you can iterate over to change an single element's style.
So, to get this to work with JavaScript you need to write a function that will be able to identify the particular div.block you want to move. But, this puts you back to where you started, needing some particular identifier, like an id or a dataset value to pass to the function.
Alternately, based on the HTML structure you provide, you could look for nextElementSibling on the a that get's clicked. But I would set up an eventListener rather than adding a JS function as a value to the onmouseenter property.
const btns = document.getElementsByTagName('a');
/*** UPDATE forEach is a NodeList method, and will fail on HTMLCollection ***/
/* this fails -> Sorry! ~~btns.forEach(button=>{~~
/* the following will work
/**********/
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('mouseenter', function(e) {
//we pass e to the function to get the event and to be able to access this
const block = this.nextElementSibling;
block.style.marginLeft = "35px";
})
btns[i].addEventListener('mouseleave', function(e) {
const block = this.nextElementSibling;
block.style.marginLeft = "0";
})
}
But with siblings, there is a CSS-only solution.
We can use the Adjacent Sibling Selector combined with the :hover state selector and no JavaScript is needed, if we are just moving back and forth.
.button:hover+.block {
margin-left: 35px;
}
See the Snipped Below
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
.button:hover+.block {
margin-left: 35px;
}
hover over me
<div class="block"></div>
hover over me
<div class="block"></div>
As Vecta mentioned, getElementsByClassName returns an array-like. You'll need to do something like this to get the first element:
function moveAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "35px";
}
function moveBackAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "0px";
}
However a better solution might be to use document.querySelector, which operates similarly to jQuery's $() syntax:
function moveAlt() {
document.querySelector(".block").style.marginLeft = "35px";
}
function moveBackAlt() {
document.querySelector(".block").style.marginLeft = "0px";
}

Using addClass to show an interval

I'm attempting to show an interval within a bar. Initially I was using the jQuery plugin for range, but it did not work like I wanted.
I have several different bulleted pointed within my bar. Whenever someone clicks within or near the point (in the class sliderInterval) I want the class rangeSection to be added to that area, basically showing that certain interval active. However, the rangeSection doesn't even show up, nor I am certain I am doing this correctly.
In addition, since I am doing this with intervals. I want to be able to give those intervals values, so that when one is selected I can display that value.
This is what I am trying to get it to look like:
I added a snippet to show what I have done so far. Any advise?
$(function interval() {
$(".slideInterval").click(function() {
$(this).addClass(".rangeSection");
});
});
#sliderBar {
border-radius: 15px;
width: 90%;
height: auto;
margin: 25px 10%;
background: blue;
}
.rangeSection {
width: 100px;
height: 100%;
color: purple;
position: absolute;
z-index: 1;
}
.intervalCircle {
border-radius: 50%;
height: 15px;
width: 15px;
background: red;
z-index: 1;
position: absolute;
}
.sliderInterval {
display: inline-block;
padding: 10px 8%;
}
.sliderInterval:first-child {
padding-left: 0;
}
.intervalCircle:first-child {
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="sliderBar">
<div class="rangeSection"></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
</div>
try this one.
You can use the .ready(); function of the jQuery library and set the .click() listener on all the .sliderInterval elements. I added the active class as well.
try it here:
https://jsfiddle.net/8cxLLts1/
$(document).ready(function(){
$(".sliderInterval").click(function() {
$(this).addClass("active");
});
});
EDIT: actually, if you use toggleClass() instead of addClass(), you'll be able to turn on and off a specific section
Using onclick in your html attribute and then binding a click event also in js could be considered redundant and unnecessary. Try removing the onclick attribute from your html and then adjust your js like so:
$(document).ready(function(){
})
.on('click', '.sliderInterval', function(){
$(this).addClass(".rangeSection");
});
Bind it to the document itself and this will help with your event delegation naturally. Also, take care to double check your class names - your js is missing the 'r' in '.sliderInterval'.

Categories