Change Element's Class Name without affecting CSS values - javascript

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.

Related

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!

Is it possible to assign a class to :root?

As I am thinking about solutions to another problem of mine, I am trying to understand to which extend CSS elements can inherit from other elements. Specifically, having the following definition
.dark {
background-color: black;
}
.light {
background-color: white
}
is it possible to programmatically assign (with JS, probably) one of these classes to the :root element?
It can be done easily with JS.
Select the element:
const root = document.querySelector(':root')
Assign the class to it:
root.classList.add('light')
All together:
const root = document.querySelector(':root')
root.classList.add('light')
Or, instead of having two classes, it might be better to have a :not() selector:
:root:not(.dark){
background-color: white;
}
:root.dark{
background-color: black;
}
I would use (and have used) CSS variables for this.
:root {
--background-color: black;
}
.background {
background-color: var(--background-color);
}
Then change the CSS variable with javascript.
In HTML, :root is equivalent to <html> (doc):
In HTML, :root represents the element and is identical to the
selector html, except that its specificity is higher.
A possible solution would be to apply the class to <html>:
document.getElementsByTagName("html")[0].classList.add('dark')
.dark {
background-color: red;
}
<html>
hello
</html>

getComputedStyle('background-color') returns transparent, does not inherit ancestor's [duplicate]

This question already has answers here:
How to get computed background color style inherited from parent element
(3 answers)
Closed 4 years ago.
getComputedStyle is supposed to return the final computed CSS property value. But for background-color, all browsers return transparent (or rgba(x,x,x,0)) instead of computing in inherited value from ancestors.
The only time the method works is if the element has a background color specified directly (even if through its class, but not through parent's definifions). But that makes getComputedStyle useless, it should take in account all ancestor's definitions.
The method works fine for other things like color as shown in the fiddle.
How can i get the effective background color of an element in JS instead of every element telling me it is transparent?
let para = document.querySelector('p');
let compStyles = window.getComputedStyle(para);
para.textContent = 'Incorrect background-color: ' + compStyles.getPropertyValue('background-color') + ', but font color is correct: ' + compStyles.getPropertyValue('color');
/* no colors are specified for p */
p {
width: 400px;
margin: 0 auto;
padding: 20px;
line-height: 2;
font-size: 2rem;
font-family: sans-serif;
text-align: center;
}
/* this is the important part, only color gets inherited, not background-color */
div {
background-color: purple;
color: lightblue;
}
<!-- Original example taken from MDN: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle -->
<div>
<p>Hello</p>
</div>
If it helps, the X question is How do i compute color luminosity difference between font color and background for each element in a page in an userscript ;)
That getComputedStyle does not work makes it not doable imho. But this question should be interesting on its own.
It's because background-color property is not inherited by the children elements (unlike the color property).
You can read more at: https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance
This is the correct result, because background color is not inherited. From MDN:
Initial value transparent
Applies to all elements. It also applies to ::first-letter and ::first-line.
Inherited no
Media visual
Computed value computed color
Animation type a color
Canonical order the unique non-ambiguous order defined by the formal grammar
To piggyback on other answers. Here's a working example using inherited css.
/* no colors are specified for p */
p {
width: 400px;
margin: 0 auto;
padding: 20px;
line-height: 2;
font-size: 2rem;
font-family: sans-serif;
text-align: center;
background-color: inherit; /* I added this */
}
/* this is the important part, only color gets inherited, not background-color */
div {
background-color: purple;
color: lightblue;
}
https://jsfiddle.net/meq6x5ay/

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

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';

Using class name in CSS value

I am currently doing some styling and have thought up an interesting way to do something. I want to create a piece of text that stands out among every other bit of text on the page. Below you can see the way I've done this.
var el = document.querySelectorAll('span[class^=impact]')[0],
col = el.className.split('-')[1];
el.style.textShadow = '2px 2px 0 #' + col;
html, body {
width: 100%;
height: 100%;
margin: 0;
background-image: url('http://i.imgur.com/UxB7TDq.jpg');
}
[class^=impact] {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-family: Impact, sans-serif;
font-size: 72pt;
font-weight: 800;
text-transform: uppercase;
}
<span class="impact-008080">impact</span>
As you can see I'm basically getting the first half of the class and applying styles to it and grabbing the second half of the class in JavaScript and applying the shadow then. What I want to do is omit the JavaScript completely and keep it all in CSS.
I do not have a list of colours. Any and all hex colours are supported obviously. I would prefer to keep this format.
CSS attr
Theoretically, this type of thing is what the CSS attr property could be used for when browser support exists. Note that this won't work now, but when browser support does exist, it might look something like this:
HTML
<span class="impact" data-shadow="#008080">Impact</span>
CSS
.impact {
/* you text and positioning styles here */
text-shadow: 2px 2px attr(data-shadow);
}
You can read more about the attr property here:
https://developer.mozilla.org/en-US/docs/Web/CSS/attr
But for now...
Your best bet is probably to continue to use JavaScript, but instead of appending the hex code to the class name, store the hex value in a data attribute of the element, allowing you to keep the class name consistent for all instances of that element.
HTML
<span class="impact" data-shadow="#fff">Impact</span>
CSS
.impact {
/* your text and position styles here */
}
JS
var el = document.querySelector(".impact"),
shadow = el.dataset.shadow;
el.style.textShadow = '2px 2px ' + shadow;
Here's a JSFiddle for reference: http://jsfiddle.net/galengidman/xx6r1n2o/

Categories