How do you get and set CSS custom properties (those accessed with var(…) in the stylesheet) using JavaScript (plain or jQuery)?
Here is my unsuccessful try: clicking on the buttons changes the usual font-weight property, but not the custom --mycolor property:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<style>
body {
--mycolor: yellow;
background-color: var(--mycolor);
}
</style>
</head>
<body>
<p>Let's try to make this text bold and the background red.</p>
<button onclick="plain_js()">Plain JS</button>
<button onclick="jQuery_()">jQuery</button>
<script>
function plain_js() {
document.body.style['font-weight'] = 'bold';
document.body.style['--mycolor'] = 'red';
};
function jQuery_() {
$('body').css('font-weight', 'bold');
$('body').css('--mycolor', 'red');
}
</script>
</body>
</html>
You can use document.body.style.setProperty('--name', value);:
var bodyStyles = window.getComputedStyle(document.body);
var fooBar = bodyStyles.getPropertyValue('--foo-bar'); //get
document.body.style.setProperty('--foo-bar', newValue);//set
The native solution
The standard methods to get/set CSS3 variables are .setProperty() and .getPropertyValue().
If your Variables are Globals (declared in :root), you can use the following, for getting and setting their values.
// setter
document.documentElement.style.setProperty('--myVariable', 'blue');
// getter
document.documentElement.style.getPropertyValue('--myVariable');
However the getter will only return the value of a var, if has been set, using .setProperty().
If has been set through CSS declaration, will return undefined. Check it in this example:
let c = document.documentElement.style.getPropertyValue('--myVariable');
alert('The value of --myVariable is : ' + (c?c:'undefined'));
:root{ --myVariable : red; }
div{ background-color: var(--myVariable); }
<div>Red background set by --myVariable</div>
To avoid that unexpected behavior you have to make use of the getComputedStyle()method , before calling .getPropertyValue().
The getter will then, look like this:
getComputedStyle(document.documentElement,null).getPropertyValue('--myVariable');
In my opinion, accessing CSS variables should be more simple, fast, intuitive and natural...
My personal approach
I've implemented CSSGlobalVariablesa tiny (<3kb) javascript helper which automatically detects and packs into an Object all the active CSS global variables in a document, for easier access & manipulation.
// get the document CSS global vars
let cssVar = new CSSGlobalVariables();
// set a new value to --myVariable
cssVar.myVariable = 'red';
// get the value of --myVariable
console.log( cssVar.myVariable );
Any change applied to the Object properties, is translated automatically to the CSS variables.
Available in : https://github.com/colxi/css-global-variables
The following example illustrates how one may change the background using either JavaScript or jQuery, taking advantage of custom CSS properties known also as CSS variables (read more here). Bonus: the code also indicates how one may use a CSS variable to change the font color.
function plain_js() {
// need DOM to set --mycolor to a different color
d.body.style.setProperty('--mycolor', 'red');
// get the CSS variable ...
bodyStyles = window.getComputedStyle(document.body);
fontcolor = bodyStyles.getPropertyValue('--font-color'); //get
// ... reset body element to custom property's new value
d.body.style.color = fontcolor;
d.g("para").style["font-weight"] = "bold";
this.style.display="none";
};
function jQuery_() {
$("body").get(0).style.setProperty('--mycolor','#f3f');
$("body").css("color",fontcolor);
$("#para").css("fontWeight","bold");
$(this).css("display","none");
}
var bodyStyles = null;
var fontcolor = "";
var d = document;
d.g = d.getElementById;
d.g("red").addEventListener("click",plain_js);
d.g("pink").addEventListener("click",jQuery_);
:root {
--font-color:white;
--mycolor:yellow;
}
body {
background-color: var(--mycolor);
color:#090;
}
#para {
font: 90% Arial,Helvetica;
font-weight:normal;
}
#red {
background:red;
}
#pink {
background:#f3f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<p id="para">Let's try to make the background red or pink and change the text to white and bold.</p>
<button id="red">Red</button>
<button id="pink">Pink</button>
Note that with jQuery, in order to set the custom property to a differnt value, this response actually holds the answer. It uses the body element's get() method which allows access to the underlying DOM structure and returns the body element, thereby facilitating the code setting the custom property --mycolor to a new value.
You can use getComputedStyle function to get css variables,Here is a example.
const colors = document.querySelectorAll(".color");
const result = document.getElementById("result");
colors.forEach((color) => color.addEventListener("click", changeColor));
function changeColor(event) {
const target = event.target;
// get color
const color = getComputedStyle(target).getPropertyValue("--clr");
document.body.style.backgroundColor = color;
// active color
colors.forEach((color) => color.classList.remove("active"));
target.classList.add("active");
result.textContent = getComputedStyle(target).getPropertyValue("--clr")
}
result.textContent = "#1dd1a1";
body{
background-color: #1dd1a1;
}
.colors{
position: absolute;
padding: 2rem;
display: flex;
gap: 1rem;
}
.color{
display: inline-block;
width: 2rem;
height: 2rem;
background-color: var(--clr);
border-radius: 50%;
cursor: pointer;
transition: $time-unit;
}
.color.active{
border: .2rem solid #333;
transform: scale(1.25);
}
<h1>Click to change Background</h1>
<section class="colors">
<span class="color active" style="--clr: #1dd1a1"></span>
<span class="color" style="--clr: #ff6b6b"></span>
<span class="color" style="--clr: #2e86de"></span>
<span class="color" style="--clr: #f368e0"></span>
<span class="color" style="--clr: #ff9f43"></span>
</section>
Current Color: <span id="result"></span>
Related
i'm trying to change each of my div's background color to black when my mouse enters the div using an eventlistener. it currently is only switching the first div to black but not any other div. why is my eventlistener only applying to the first 'contentDivs' div?
example:
this is my html code:
<body>
<div id="mainContainer"></div>
<script src="index.js"></script>
</body>
this is my javascript code:
for(x=0; x<64; x++) {
const contentDivs = document.createElement('div');
contentDivs.id = 'contentDivs';
document.getElementById('mainContainer').appendChild(contentDivs);
}
document.getElementById('contentDivs').addEventListener('mouseenter', () => {
document.getElementById('contentDivs').style.background = 'black';
})
this is what shows up when inspecting the elements in google chrome:
If you want to select many elements you can use querySelectorAll. If you want to select one please use querySelector.
I've used minimal changes for your example. Ideally you should take advice of comments and change the identifying method to be class rather than id.
Lastly, I've added another effect using css alone, so you can compare how to make style changes using :hover class.
for (x = 0; x < 64; x++) {
const contentDivs = document.createElement('div');
contentDivs.id = 'contentDivs';
document.getElementById('mainContainer').appendChild(contentDivs);
}
document.querySelectorAll('#contentDivs').forEach(function(elem) {
elem.addEventListener('mouseenter', () => {
elem.style.background = 'black';
})
})
#contentDivs {
width: 20px;
height: 20px;
background: pink;
float: left;
margin: 10px;
transition: 500ms all;
}
#contentDivs:hover {
transform: scale(1.5);
}
<body>
<div id="mainContainer"></div>
</body>
How do I remove the inline style which is added by JavaScript?
For example: if people click the button, the marginTop of div#test will be 30px, but what if I want to remove the inline style instead of resetting it to another value like 0?
I do not want to add a class to that element and remove it because it's not suitable in my use case.
const elm = document.querySelector('#test')
function change() {
elm.style.marginTop = '30px';
}
#test {
width: 150px;
height: 60px;
background-color: blue;
}
<div id="test"></div>
<button onclick="change()">Change</button>
either set as empty string
elm.style.marginTop = '';
or to remove the complete attribute use
removeAttribute
elem.removeAttribute('style');
I am building a simple chat bot.On each new message received from the server, a new HTML element is created and pushed to the browser. So, for example, message 1 will be:
<div class="message-computer"><p>Hi, how are you?</p></div>
Then you (the user) types/sends a message, which shows up as:
<div class="message-user"><p>I am good, thanks!</p></div>
and so on and so forth. I created a slider to change the size of the text being sent to/from the chat bot. It now works, but it only edits EXISTING HTML elements. New messages sent to/from the server are still in the original size.
$('input').on('change', function() {
var v = $(this).val();
$('.message-computer p').css('font-size', v + 'em')
$('.message-user p').css('font-size', v + 'em')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="range" value="1" min="1" max="1.6" step=".1" id="slider" ondrag="changeSize()" />
How can I make the change in font size apply to all new elements sent to the browser?
Thanks
Not sure I understand well your problem, your code snippet doesn't contain any text.
But when using jQuery to update style, CSS statment is added individualy into each element style attribute (look at your browser inspector).
So newly added elements wont have their style attribute modified until you rechange the input value, and so will inherit from global CSS rules.
I suggest to apply the font style to the parents .message-computer & .message-user.
If you can't, wrap p elements into a dedicated div and apply the style to the div.
If you really need to apply it individually to each element, run $('input').trigger('change'); just after inserting new elements into the DOM.
What you want to do is add a class to a parent tag of your HTML, and to then have a CSS rule which applies to all of the like-elements on the page.
Then, no matter how many .message element you add to your .parent element, a CSS rule applies to them equally.
For instance, something like this would work. You could make this approach more efficient, but this illustrates the idea.
$('input').on('change', function() {
var v = $(this).val();
$('.parent').removeClass('font-1');
$('.parent').removeClass('font-2');
$('.parent').removeClass('font-3');
$('.parent').removeClass('font-4');
$('.parent').removeClass('font-5');
$('.parent').addClass('font-' + v);
});
.parent.font-1 .message {
font-size: 1em;
}
.parent.font-2 .message {
font-size: 2em;
}
.parent.font-3 .message {
font-size: 3em;
}
.parent.font-4 .message {
font-size: 4em;
}
.parent.font-5 .message {
font-size: 5em;
}
.message-computer {
color: red;
}
.message-user {
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="range" value="1" min="1" max="5" step="1" id="slider" ondrag="changeSize()" />
<div class="parent font-1">
<div class="message-computer message"><p>I AM ROBOT</p></div>
<div class="message-user message"><p>Only human.</p></div>
</div>
You're only modifying existing node.
If you want that new node take those rules simply build a javascript function that add or update dynamically a css node
function changeSize(v)
{
var css = [
".message-computer p, .message-user p {font-size: "+v+"em;}"
].join("");
var head = document.head || document.getElementsByTagName('head')[0];
var style = null;
if(!document.getElementById("customTextSize"))
{
style = document.createElement('style');
style.id = "customTextSize";
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
}
else
{
style = document.getElementById("customTextSize");
style.removeChild(style.firstChild);
style.appendChild(document.createTextNode(css));
}
}
On your on change simply call the function :
changeSize(v)
i have a question about to get the X id by
document.getElementById("X").style.backgroundColor
this is my HTML:
<div id ="X" class="main-sidebar text-white ">
</div>
CSS like:
.main-sidebar{
background-color: #343a40;
width:10%;
height:100%;
display:block;
position: absolute;
left:0px;
/*top:0px;*/
}
But when I use document.getElementById("X").style.backgroundColor in js i get NULL value...
That's because style refers to the inline style attribute in your HTML. If you want to get the style that's set via CSS only, you will need to use computedStyles.
const elem = document.getElementsByTagName('p')[0]; // get element
const styles = window.getComputedStyle(elem); // get computed style of element
console.log(styles.getPropertyValue('background-color')); // get specific attribute
p {
background-color: red;
}
<p>Hi!</p>
Try using computed styles:
window.getComputedStyle(document.getElementById("X")).backgroundColor
.style Will get or set the inline style of an element.
In your case, the style for .main-sidebar is in a .css file.
What you can do is use getComputedStyle():
getComputedStyle(document.getElementById("X")).backgroundColor // #343a40
I want on ajax call change the values loaded from CSS file, it means not only for one element like:
document.getElementById("something").style.backgroundColor="<?php echo "red"; ?>";
but similar script which is change the css value generally, not only for element by ID, idealy like background color for CSS CLASS divforchangecolor:
CSS:
.divforchangecolor{
display: block;
margin: 20px 0px 0px 0px;
padding: 0px;
background-color: blue;
}
HTML:
<div class="divforchangecolor"><ul><li>something i want to style</li><ul></div>
<div class="divforchangecolor">not important</div>
<div class="divforchangecolor"><ul><li>something i want to style</li><ul></div>
<div class="divforchangecolor">not improtant</div>
Ideal solution for me:
onclick="--change CSS value divforchangecolor.backgroundColor=red--"
but i need to change CSS to reach .divforchangecolor ul li and .divforchangecolor ul li:hover
If you can't just apply the classname to these elements. You could add a new selector to your page. The following vanilla JS would be able to do that (jsFiddle).
function applyDynamicStyle(css) {
var styleTag = document.createElement('style');
var dynamicStyleCss = document.createTextNode(css);
styleTag.appendChild(dynamicStyleCss);
var header = document.getElementsByTagName('head')[0];
header.appendChild(styleTag);
};
applyDynamicStyle('.divforchangecolor { color: pink; }');
Just adapt the thought behind this and make it bullet proof.
var elements=document.getElementsByClassName("divforchangecolor");
for(var i=0;i<elements.length;i++){
elements[i].style.backgroundColor="red";
}
var e = document.getElementsByClassName('divforchangecolor');
for (var i = 0; i < e.length; i++) e[i].style.backgroundColor = 'red';
Use getElementByClassName() and iterate over the array returned to achieve this
You can select elements by class with document.getElementsByClassName or by css selector (includes class) with document.querySelectorAll().
Here are two approaches, for example: Live demo here (click).
Markup:
<div class="divforchangecolor"></div>
<div class="divforchangecolor"></div>
<div class="divforchangecolor"></div>
<div class="divforchangecolor"></div>
<div class="some-container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
JavaScript:
var toChange = document.getElementsByClassName('divforchangecolor');
for (var i=0; i<toChange.length; ++i) {
toChange[i].style.backgroundColor = 'green';
}
var toChange2 = document.querySelectorAll('.some-container > div');
for (var i=0; i<toChange.length; ++i) {
toChange2[i].style.backgroundColor = 'red';
}
I recommend the second solution if it is possible in your case, as the markup is much cleaner. You don't need to specifically wrap the elements in a parent - elements already have a parent (the body, for example).
Another option is to have the background color you want to change to in a css class, then you can change the class on your elements (and therefore the style changes), rather than changing the css directly. That is also good practice, as it lets you keep your styles all in css files, while js is just manipulating which one is used.
On the whole document your approach can be a bit different:
ajax call
call a function when done
conditionally set a class on the body like <body class='mycondition'></body>
CSS will take care of the rest .mycondition .someclass: color: red;
This approach will be more performant than using JavaScript to change CSS on a bunch of elements.
You can leverage CSS selectors for that:
.forchangecolor {
display: block;
margin: 20px 0px 0px 0px;
padding: 0px;
background-color: blue;
}
.red-divs .forchangecolor {
background-color: red;
}
Then, with javascript, add the red-divs class to a parent element (could be the <body>, for example), when one of the divs is clicked:
document.addEventListener("click", function(event) {
var target = event.target;
var isDiv = target.className.indexOf("forchangecolor") >= 0;
if(isDiv) {
document.body.classList.add("red-divs");
}
});
Working example: http://jsbin.com/oMIjASI/1/edit