javascript - changing a class' style - javascript

I've been working with jQuery for a while, but now I want to write something in pure javascript and it's prooving to be challenging..
One of my biggest problems at the moment is that I haven't found a way to set/change styling for a class. This is not a problem for elements with id, but I want to change the styling for a group of elements with the same class and not just for one element with an id..
In jQuery I would just write:
$('.someClass').css('color','red')
Is there really no simple equivalence to this in pure js?

Try the following
var all = document.getElementsByClassName('someClass');
for (var i = 0; i < all.length; i++) {
all[i].style.color = 'red';
}
Note: As Cheery pointed out getElementsByClassName won't work in IE. The linked question has a nice way to work around this limitation
javascript document.getElementsByClassName compatibility with IE

I find it easier to use CSS variables. You can set the class to use a variable and then change that value in Javascript, thus changing the CSS.
If you style the class like:
:root {
--some-color: red;
}
.someClass {
color: var(--some-color);
}
Then you can change the variable's value in Javascript with
document.documentElement.style.setProperty('--some-color', '(random color)');
(random color) can then be anything that would be considered a valid CSS color (eg. blue, black, #626262, rgb(12, 93, 44))
Updating the value in JS automatically updates the page as well.
And of course, this can be done with any property, not just color. Here is an example that changes the padding of a class:
CSS
:root {
--some-padding: 12px;
}
.someClass {
padding: var(--some-padding);
}
Javascript
// Set padding to 15px
document.documentElement.style.setProperty('--some-padding', '15px');
// Set padding to 5rem
document.documentElement.style.setProperty('--some-padding', '5rem');
// Set padding to 25%
document.documentElement.style.setProperty('--some-padding', '25%');
Useful example: toggle dark / light mode:
(How to use css properties to dynamically set css properties)
// set to light mode:
document.documentElement.style.setProperty('--bg-color', getComputedStyle(document.documentElement).getPropertyValue('--bg-color-light'));
// set to dark mode:
document.documentElement.style.setProperty('--bg-color', getComputedStyle(document.documentElement).getPropertyValue('--bg-color-dark'));
With the respective css:
:root {
--bg-color: black;
--bg-color-light: white;
--bg-color-dark: black;
body {
background-color: var(--bg-color);
}
Sources
How to declare and use CSS variables: https://www.w3schools.com/css/css3_variables.asp
How to update a CSS variable in JS: https://css-tricks.com/updating-a-css-variable-with-javascript/

var sheet = document.createElement('style')
sheet.innerHTML = ".someClass {color: red;}";
document.body.appendChild(sheet);

What you want to change is the style sheet, I guess? Thats possible in Javascript, see
Quirksmode: Change CSS
Totally Pwn CSS with Javascript (in Internet Archive)
Is the only way to change a style to do it per-element in JavaScript? (possible duplicate)
I'm afraid there is no library for that, I really would like to see one...

var all = document.getElementsByClassName('someClass');
for (var i = 0; i < all.length; i++) {
all[i].className += " red";
}
For better coding style add another class to the elements with the code above and then use CSS to change the color of all elements like this:
.red {
color:red;
}

You can use selector library, for example Sizzle: http://sizzlejs.com/ but if you want pure JS that I guess you are stuck with getting all the elements, and then programatically "handpicking" the ones that have classes you are interested in using RegEx like this for example:
This is an equivalent of your JQuery oneliner:
for( i in document.all) document.all[i].className && /\bpost-text\b/g.test(document.all[i].className) && (document.all[i].style.color = "red")
:)
If you don't need it in one line you can make it faster (and much more readable):
var myClassName = "someClass";
var regexp = RegExp("\\b"+myClassName+"\\b/g");
var elements = document.all;
for( i in elements){
var this_element = elements[i];
if(regexp.test(this_element.className){
this_element.style.color = "red";
}
}
If "for( i in object)" doesn't work for you, just use classic for loop "for(var i = 0; i < elements.length; i++)".
It could be 'beautified' a bit with the use of some slightly more advanced JS concepts (array function mappings, folding and such), which JS version are you coding agains? I guess it's not ECMA Script 5, right?
Also, check out this question/answer Get All Elements in an HTML document with a specific CSS Class

Related

Why can't I retrieve a CSS style property for an element using JS? [duplicate]

This question already has answers here:
Get a CSS value with JavaScript
(8 answers)
Closed 4 years ago.
So I am trying to retrieve a CSS property from the DOM and the only thing being returned is ""...
e.g. if my CSS code is
nav {
color: red;
}
and my javascript is
var nav = document.querySelector("nav");
var navColor = nav.style.color;
console.log(navColor);
All that is returned to console is "". I am new to JS.
If I try to manually make a var and find it's property in the console, it also outputs "", until I change the value of the style property, then it successfully returns the properties value - yes I have definitely set a property I am trying to retrieve and I have checked spelling hundreds of times.
Check this link: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
const nav = document.querySelector("nav");
const { color: classStyle } = getComputedStyle(nav);
const { color: inlineStyle } = nav.style;
console.log(inlineStyle)
console.log(classStyle)
nav {
color: red;
}
<nav>this is nav</nav>
You will need to use getComputedStyle() for that:
var navColor = getComputedStyle(nav).color;
You can query the applied css rule by calling getComputedStyle(document.querySelector("nav")).color
var nav = document.querySelector("nav");
console.log(getComputedStyle(nav).color)
nav {
color: red;
}
<nav>Menu</nav>
With .style property You can't access elements css styles if the styles is not inline.
You need to use getComputedStyle function.
Usage:
var nav = document.querySelector("nav");
var navColor = getComputedStyle(nav).color;
console.log(navColor);
For more information please refer to this link
As mentioned in the comments, the style property only returns inline styles, as in:
<div style="color: red;"></div>
would return...
"color: red;"
What you're looking for is the window.getComputedStyle function, which can be used to retrieve final style values. Like so:
// HTML
<div class="some-element"></div>
// CSS
.some-element {
color: red;
}
// JS
const someElement = document.querySelector('.some-element');
console.log(window.getComputedStyle(someElement).getPropertyValue('color'));
This should log out red.
EDIT
Per comment, the output would actually be rgb(255, 0, 0), the RGB equivalent of red. As the function name suggests, it's computing styles, not retrieving their actual values. For example, if you styled with CSS a width to be 10%, getComputedStyle would calculate the pixel value of whatever the final width is rendered as. Not the best solution, but JavaScript generally doesn't need to directly interact with raw CSS files -- that should be up to the CSS and (JavaScript-controlled) classes to manage.
EDIT 2
Just an FYI, you can use .getPropertyValue('color') or just .color, I'm unaware of any preference in the dev community.

Ignore/override surrounding / inherited CSS

I have this call to add HTML/CSS to an existing page:
let div = document.createElement('div');
div.style.zIndex = 9999999;
div.innerHTML = str; // some pre-defined HTML string
document.body.insertBefore(div, document.body.firstChild);
I am creating a Chrome Extension that helps developers. What's happening is that the above HTML is inheriting the existing CSS from developer's pages. I want the styling of the above HTML to be independent from the CSS/styling on the developer's page.
Is there a way to ignore all existing CSS on page? I'd like to basically create a "CSS sandbox".
I think one way to create such a sandbox, would be an iframe, but I am looking for a simpler way to do that.
Add a class to elements which you want to reset..and then apply all:unset to that class
The all CSS shorthand property sets all of an element's properties (apart from unicode-bidi and direction) to their initial or inherited values, or to the values specified in another style sheet origin.
...all:unset
Specifies that all the element's properties should be changed to their inherited values if they inherit by default, or to their initial values if not.(It will ignore all the user agent style too.)
Stack Snippet
let p = document.createElement('p');
p.style.color = "red";
p.innerHTML = "Hello"; // some pre-defined HTML string
p.classList.add("reset");
document.body.insertBefore(p, document.body.firstChild);
p {
background: black;
}
.reset {
all: unset;
}

CSS equivalent to .attr("data-html", "true")

Following up from
line break for d3 circle title tooltipText
the code is
svgContainer.selectAll("g.node").each(function() {
var node = d3.select(this);
var tooltipText = node.attr("name");
var tooltipText = node.attr("name").replace("\\n", "<br />");
if (tooltipText) {
node.select("circle")
.attr("data-html", "true")
.attr("title", tooltipText);
}
and I'd like to replace the .attr("data-html", "true") function with CSS formatting
css, not-working-1:
# g.node circle { data-html: true;}
css, not-working-2:
# g.node circle { html: true;}
both above 2 have "Unknown property name" error.
I'm wondering, what is the CSS equivalent to .attr("data-html", "true")?
Thank you very much.
CSS is (designed for) a simple mechanism for adding style to an HTML document.
The code you referred to actually mutates the DOM (in this case, the html-node).
On a side note: If you want to 'select' based upon that state in CSS, you could do.
html {
background: red;
}
html[data-something=true] {
background: green;
}
if then the JavaScript sets $('html').attr('data-something', 'true'); your CSS would be applied (from red background to green).
It doesn't have equivalent CSS property. CSS is the look and some behavior. data-html is an HTML5 styled attribute, which is used to store a data. You can add anything with data- prefix.
So you need to use a Javascript to add an HTML5 attribute.

Create a very low specificity css property

I am trying to create a very low specificity css property using javascript. Just like !unimportant (which doesn't exists)
I don't know whether this is possible or not.
My reason to look for something like !unimportant is that I am writing a small javascript plugin. In which I want to add a default style to a element which should be later easily overriden by the user.
But if I write:
element.style.backgroundColor = "green";
The user will not be able to override the above style easily without using !important. So, I added a dynamic style tag by using the following code:
var style = document.createElement('style');
// WebKit hack :(
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
and then to the above code, I added a dynamic stylesheet using the following code:
var element = document.getElementById('main');
// To use attribute names to apply the styles
element.setAttribute('custom-el', '1');
var sheet = style.sheet;
var properties = "background-color: green;";
var elName = "[custom-el]";
if (sheet.insertRule) {
sheet.insertRule(elName + "{" + properties + "}", 0);
} else if (sheet.addRule) {
sheet.addRule(elName, properties, 0);
}
Now the background-color: green can be overriden by using the following code:
div.main {
background-color: red;
}
But as you can see in css, I used higher specificity to override background-color: green i.e div + .green.
But I want the overriden to happen even when user writes the following css:
.main{ /* Could be simple class name or id name or even tag name */
background-color: red;
}
Fiddle
This might seems to be a small issue. but it is a big problem for me. Please help.
I would simply write like this:
element.style.backgroundColor = element.style.backgroundColor || "green";
Where, if backgroundColor is undefined then it uses green as backgroundColor else it would take the backgroundColor from stylesheet.
Finally I got the answer..
document.head.insertBefore(style, document.head.children[0]);
I should just insert the dynamic stylesheet above already present stylesheets in the head tag.
Working Fiddle
Unfortunately, this is not working in any IE version. I am still looking for answer.

How to temporarily add a CSS style?

I have a div and when I mouse over it I want to change the background (and possibly other properties). I can do it by calling el.style.backcolor = "", but is there a way I can add another CSS style to it then remove it later? Like style += mouseOverStyle and then style -= mouseOverStyle. That way I could select the properties to change in the CSS instead of in the JavaScript code.
EDIT: I may want to apply the new style in other situations, not just mouseover, so #div:hover isn't really a general solution. What I'm really asking is is there something like style.add("style") and style.remove("style")?
If I understood you correctly, you're asking to change the background when you hover your div element?
This is easily done via CSS, no Javascript or other codes are necessary!
#myDiv
{
background-color: #f00;
}
#myDiv:hover
{
background-color: #00f;
}
Of course you can change other styles too, you don't need to add another class to change one or more styles.
Hope that helps :)
Just add or remove CSS classes when needed.
Adding:
yourElement.className += ' my_class';
Removing:
yourElement.className = yourElement.className.replace(/\bmy_class\b/, '');
With jQuery you can use addClass, removeClass and toggleClass methods (see the docs).
You could try using multiple :hover pseudo selectors:
div.style1:hover { background: red }
div.style2:hover { background: yellow }
Then use javascript/jquery to switch between html class attributes
I would recomendate you to use a JS library, such as jQuery. In jQuery it is simple like that:
http://api.jquery.com/addClass/ together with the mouseover event handling http://api.jquery.com/mouseover/.
function changeStyle()
{
document.getElementById("elementID").style.color="green";
}
after the .style. you should paste the css attribute you want to edit.
If you're wanting to use js, change the properties on the user event.
onmouseover : el.style.background = "blue";
onmouseout : el.style.background = "red";
If you want to add more properties as time goes along just throw it in a function
function onMouseOverFunction () {
el.style.background = "blue";
el.style.color = "blue";
el.style.font-size= "1em";
}

Categories