Change CSS class by Javascript when default class is set by ID - javascript

I have a DIV that has CSS applied to it in an external stylesheet by ID, such as:
<div id="myFavoriteDIVever">Stuff</div>
#myFavoriteDIVever {
display: none;
}
Then, in a Javascript function, I set the following class to that same DIV:
document.getElementById('myFavoriteDIVever').className = 'superCoolClass';
.superCoolClass {
display: block;
}
For some reason, when I do it this way, the DIV is not set to display as block. It remains not displayed in the DOM. But if I change it so the DIV has a default CSS class applied to it that sets display: none; then I set a different CSS class to it with Javascript later that sets display: block; it works as expected and displays the DIV as a block element.
Why would the CSS class override the ID CSS? So, when I apply a new className it should override the #element settings. No?

Ascending order of specificity
The following list of selectors is by increasing specificity:
Universal
selectors Type
selectors Class
selectors Attributes
selectors Pseudo-classes
ID selectors
Inline style
You can overwrite it using inline-styling
document.getElementById('myFavoriteDIVever').style.display = 'block';
#myFavoriteDIVever {
display: none;
width: 300px;
height: 400px;
background: red
}
<div id="myFavoriteDIVever" class="myFavoriteDIVever">Stuff</div>

Ids have a higher priority so adding a class will not have any effect. Your best shot is:
<div id="myFavoriteDIVever" class="myFavoriteDIVever">Stuff</div>
.myFavoriteDIVever {
display: none;
}
document.getElementById('myFavoriteDIVever').className = 'superCoolClass';

The issue isn't with your javascript, its with the CSS. There is a concept called specificity. The idea is that each CSS entry has some specificity value (1000, 100, 10, 1). The style that will be applied is the one that is the most "specific". An ID selector = 100. A class selector = 10. The id will win. Try changing the css for the class from
.superCoolClass {
display: block;
}
to
#myFavoriteDIVever.superCoolClass {
display: block;
}

This should do fine:
HTML:
<div id="myFavoriteDIVever">Stuff</div>
CSS:
#myFavoriteDIVever {
display: none;
}
#myFavoriteDIVever.show {
display: block;
}
JS:
document.getElementById('myFavoriteDIVever').className = 'show';

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>

Change css class attribute values using 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.

CSS changing to display: flex affects how classes are applied to button

I have an unordered list whose li elements each contain a button as a child within them.
In Javascript I toggle adding a 'done' style (which crosses off the text) on the li elements when they are clicked like so
function crossOffList(e){
if (e.target.nodeName === "LI"){
e.target.classList.toggle("done");
}
}
The following is the li style:
li {
margin: 10px 0px;
**display: flex;**
justify-content: space-between;
align-items: center;
align-self: center;
}
The issue is that when I add display: flex; to the li style, the button also becomes crossed off after the li item is clicked, like so:
This is how the buttons are created and added to the li elements
function addDeleteButton(element){
element.innerHTML += " ";
var button = document.createElement("button");
button.appendChild(document.createTextNode("Delete"));
button.addEventListener("click", function(e) {
ul.removeChild(element);
})
//button.classList.add("delete-button");
element.appendChild(button);
}
// initialise all starting list elements
for (var i of document.getElementsByTagName("li")){
addDeleteButton(i);
i.addEventListener("click", crossOffList);
}
This behaviour of the button also becoming crossed off does not occur if the display is not set to flex. What is causing this behaviour and is there any way to use flex while having the button not be crossed off after click?
CSS text-decoration does not get inherited in the same way as other properties, it gets propagated. It cannot be overwritten (but it can be added to) by setting another value in a child element. There is some discussion of this at Override text-decoration on child element
However, MDN documentation states that this propagation does not apply when the child element is floating or absolute.
I have not been able to show any improvement using float but there is some improvement if we position the button absolutely when, and only when, the parent LI element has display:flex
For example putting class flex on each LI element if you want them flexed and removing it if not and changing the CSS to:
li {
position: relative;
margin: 10px 0px;
justify-content: space-between;
align-items: center;
align-self: center;
background-color:cyan;
}
li.flex {/* add .flex class to each li if you want them flexed*/
display: flex;
}
li.done {
text-decoration: line-through;
}
.flex button {
position:absolute;
right:0;
}
Some work will be needed to make sure the desired layout is achieved but at least this method does not strike out the button text in both flex and non-flex cases.

How do I bind style to onclick element using Javascript?

Whenever I click on the left arrow icon, I want the style of the menu to change. Is it possible to bind specific css style when using onclick function?
i.fas.fa-chevron-circle-left.left
#sidebar-container .menu
width: 18rem
transition: 200ms
How I want it to look after onclick function.
#sidebar-container .menu
width: 10rem
Make a class containing the styles you want and you can toggle those on and off using javascript:
document.getElementById('my-element').classList.toggle('my-class');
This will add the my-class class if the element doesnt have it, and remove the my-class class if the element does have it. You may also use classList.add and classList.remove if you'd like to set it on or off.
You can easily bind this to a button with inline javascript. It is recomended to use event listeners but this should do the trick:
<button onclick="document.getElementById('my-element').classList.toggle('my-class')">Click me to toggle the class</button>
You can change my-elemment to be the ID of the element you want to toggle the class for and my-class to the classname you'd like to use.
It is possible to bind to an element. You can use document.querySelector() to find that element.
for example:
const el = document.querySelector("i.fas.fa-chevron-circle-left.left")
el.addEventListener("click", function(){
el.style.transition = "";
});
It's almost always easier to just add an overriding class instead of editing single style properties:
el.classList.add("override");
and have that class in css somewhere.
.override {
transition: none !important;
}
You can create a secondary class for styles you want when it is clicked. You can toggle the class like this
const menu = document.querySelector("#sidebar-container .menu");
menu.addEventListener('click', function () {
// by adding class name
menu.classList.toggle("menu-clicked");
});
#sidebar-container {
width: 200px;
height: 100vh;
background: #ccc;
display: flex;
padding-top: 20px;
align-items: flex-start;
justify-content: center;
transition: all ease 200ms;
}
#sidebar-container .menu {
background: #ddd;
padding: 20px;
display: block;
width: 100%;
cursor: pointer;
}
#sidebar-container .menu.menu-clicked {
background: green;
}
<div id="sidebar-container">
<div class="menu">
Menu
</div>
</div>
Hope it helps. Cheers!

Change Element's Class Name without affecting CSS values

I have an DOM element and I want to only change the className of the element. I want to remain the css values as it. (For both external css and inline css)
For example, if I have this:
.sample{
display: block
font-size: 10px,
font-color: #fff
}
<div class="sample">...</div>
After doing some JavaScript operation I need to reach this:
.newCss{
display: block
font-size: 10px,
font-color: #fff
}
<div class="newCss">...</div>
Note: There is no strict rule for css, there can be a css selector with 100 values or with only 1 one.
Note2: There is no css selector such as .newCss, I should transform the css properties from .sample, to a new one called .newCss
You can get the computed style for the element prior to making the change:
const style = getComputedStyle(theElement);
and then apply that styling to the element directly:
theElement.style.cssText = style.cssText;
Then removing the class won't change the element's styling, because it's styled inline.
Example:
const theElement = document.querySelector(".sample");
console.log("before:", theElement.className);
setTimeout(() => {
const cssText = getComputedStyle(theElement).cssText;
theElement.className = "newCss";
theElement.style.cssText = cssText;
console.log("after: ", theElement.className);
}, 800);
.sample{
display: block;
font-size: 10px;
color: #fff;
background-color: black;
}
.newCss {
background-color: yellow;
}
<div class="sample">this is the div</div>
If the new class has styling associated with it in CSS, that might affect the styling of the element. If you need to prevent that, change the class first, then assign the CSS text:
Example:
const theElement = document.querySelector(".sample");
console.log("before:", theElement.className);
setTimeout(() => {
theElement.style.cssText = getComputedStyle(theElement).cssText;
theElement.className = "newCss";
console.log("after: ", theElement.className);
}, 800);
.sample{
display: block;
font-size: 10px;
color: #fff;
background-color: black;
}
<div class="sample">this is the div</div>
You have to use JavaScript. In order to use JavaScript, you have to assign a ID to the <div> tag. Then manipulate it by JavaScript. Example: document.getElementById("id1").className="sample";
Also make sure that you using semicolon(;) after CSS properties.
function f1()
{
document.getElementById("id1").className="sample";
}
.sample{
display: block;
font-size: 10px;
font-color: #fff;
color: red;
}
.newCss{
display: block;
font-size: 10px;
font-color: #fff;
color: green;
}
<div id='id1' class="newCss"><p>Hello</p></div>
<button onclick="f1()">Click</button>
Well, if you want to change className to a class which is identical, you can simply redefine the class in the style sheet to be equivalent, or you can use inline styles, but the purpose of CSS classes is to keep a unique set of rules, so two identically-ruled CSS classes would defeat the purpose for which they exist, to be unique definitions of CSS rules, so if you want the CSS rules exactly the same, then there wouldn't be a reason to change the className, unless you were referencing it with other JavaScript functions, or if you wanted to add additional styles while keeping the old ones, in such a case:
use classList to dynamically add or remove certain individual classes, while keeping others.

Categories