I want to create two buttons in HTML called 'green' and 'red'. When clicking on them, the style "background-color: {COLOR-SELECTED}" should be changed dynamically.
var verde = document.getElementById('verde')
var vermelho = document.getElementById('vermelho')
var body = document.querySelector('body')
function verde() {
body.className = "verde";
}
function vermelho() {
body.className = "vermelho";
}
.verde {
background-color: darkgreen;
}
.vermelho {
background-color: darkred;
}
<body>
<button class="verde" onclick="verde ()" id="verde"></button>
<button class="vermelho" onclick="vermelho ()" id="vermelho"></button>
</body>
You should use the classList API to add or remove a class to body.
More info HERE
function verde () {
body.classList.remove('vermelho');
body.classList.add('verde');
}
Here are a few changes I've made:
Remove the space between the function name and the () in the HTML.
Removed the first two lines of the javascript – you never use these variables.
Changed querySelector to getElementsByTagName, which creates a list of elements, so that you can select the first one using [0]
The snippet below should work as expected:
var body = document.getElementsByTagName('body')[0];
function verde() {
body.className = "verde";
}
function vermelho() {
body.className = "vermelho";
}
.verde {
background-color: darkgreen;
}
.vermelho {
background-color: darkred;
}
<body class="none">
<button class="verde" onclick="verde()" id="verde"></button>
<button class="vermelho" onclick="vermelho()" id="vermelho"></button>
</body>
Related
Lots of answers on how to get/set "root" CSS variables but none that I've found on how to get/set NON root CSS variables.
NOTE: This is NOT answer: https://stackoverflow.com/a/36088890/104380 That answer only handles root variables and or variables on elements, not on classes
Also: These are not answers (from: https://www.google.com/search?q=get%2Fset+css+variables). Checked the first page of links. All of them only handle root variables. I'm trying to deal with non-root variables.
.foo {
--fg-color: red;
}
.bar {
--fg-color: blue;
}
div {
color: var(--fg-color);
}
<div class="foo">foo</div>
<div class="bar">foo</div>
How do you get someFunctionToGetCSSVariable('.foo', '--fg-color') (yes, I made that up). The point is I want to get/set the --fg-color variable on the .foo CSS rule. Whatever the solution is, getting the value it should return 'red' or '#FF0000') and how do you set it to something else?
I think what OP tries to do is not to change the all elements of that certain class, but to change the class itself, there is a difference. What you need (if I understood well) is actually cssRules change on the certain class. I've created a quick (and dirty) snippet of how to search the cssRules and change the CSS properties in it (including custom one):
<html>
<head>
<style>
.foo {
--fg-color: red;
}
</style>
</head>
<body>
<div class="foo">lorem ipsum</div>
<script>
window.onload = function() {
rules = document.styleSheets[0].cssRules
for (var r in rules) {
if (rules[r].selectorText == ".foo") {
rules[r].style.setProperty('--fg-color', 'blue');
alert('hi');
break;
}
}
};
</script>
</body>
</html>
You could make use of the fact that we have cascading style sheets.
It depends on exactly what your structure is of course, (e.g. are there style elements buried in body?).
For the simple case you could add another stylesheet onto the bottom of the head element.
<!doctype html>
<html>
<head>
<style>
.foo {
--fg-color: red;
}
.bar {
--fg-color: blue;
}
div {
color: var(--fg-color);
}
</style>
</head>
<body>
<div class="foo">foo</div>
<div class="bar">foo</div>
<button>Click me</button>
<script>
const button = document.querySelector('button');
button.addEventListener('click', function () {
const head = document.querySelector('head');
const style = document.createElement('style');
style.innerHTML = '.foo { --fg-color: lime; }';
head.appendChild(style);
button.style.display = 'none';
});
</script>
</body>
</html>
Of course, it could get messy if this happens more than once. You'd want to remember that you'd added a style sheet and get rid of it before adding another one, or alter it in situ, depending on exactly what the situation is. And if there is styling scattered in the body you'll have to add the stylesheet to the bottom of that.
Looks like I have to iterate through all the stylesheets and find the rule. Here's one try.
function getCSSRuleBySelector(selector) {
for (let s = 0; s < document.styleSheets.length; ++s) {
const rules = document.styleSheets[s].cssRules;
for (let i = 0; i < rules.length; ++i) {
const r = rules[i];
if (r.selectorText === selector) {
return r;
}
}
}
}
function setCSSVariableBySelector(selector, varName, value) {
const rule = getCSSRuleBySelector(selector);
rule.style.setProperty(varName, value);
}
function getCSSVariableBySelector(selector, varName) {
const rule = getCSSRuleBySelector(selector);
return rule.style.getPropertyValue(varName);
}
console.log('was:', getCSSVariableBySelector('.foo', '--fg-color'));
setCSSVariableBySelector('.foo', '--fg-color', 'green');
.foo {
--fg-color: red;
}
.bar {
--fg-color: blue;
}
div {
color: var(--fg-color);
}
<div class="foo">foo</div>
<div class="foo">foo</div>
<div class="foo">foo</div>
<div class="bar">bar</div>
<div class="bar">bar</div>
You can use document's styleSheets property to access the CSS rules of the linked .css file, and perform some operations on it to get the value of the custom css variable.
To set a value of custom CSS variable (of the class itself), you can create a new style element, and add a rule for it.
function getStyle(selector, prop) {
let rules = getRule(selector).cssText;
return rules.split(prop + ":")[1].replace(";", "").replace("}", "").trim();
}
function setStyle(selector, prop, val) {
let style = document.querySelector("style.customStyle");
if(style === null){
style = document.createElement("style");
style.className = "customStyle";
style.innerHTML = `${selector}{${prop}:${val}}`;
document.head.appendChild(style);
} else{
style.innerHTML += `${selector}{${prop}:${val}}`;
}
}
function getRule(selector) {
let rulesObj = document.styleSheets[0];
let classes = rulesObj.rules || rulesObj.cssRules;
classes = Object.values(classes)
let rules = classes.filter(c => c.selectorText === selector)[0];
return rules;
}
console.log(getStyle(".foo", "--fg-color"));
console.log(getStyle(".bar", "--fg-color"));
document.querySelector("button").onclick = ()=>{
setStyle(".bar", "--fg-color", "green");
}
.foo {
--fg-color: red;
}
.bar {
--fg-color: blue;
}
div {
color: var(--fg-color);
}
<div class="foo">foo</div>
<div class="bar">foo</div>
<div><button>Click</button></div>
Get
Iterate all styles
Styles can be injected via external CSS file, a <style> tag (on the page) or style attribute (irrelevant to you).
const results = [];
const SELECTOR = '.foo';
const PROP = '--bar';
[...document.styleSheets].forEach(sheet => {
[...sheet?.cssRules].forEach(rule => {
// you should probably use regex to find PROP (so it won't match `--bar-x` for example)
if( rule.cssText.includes(SELECTOR) && rule.cssText.includes(PROP) ){
results.push(rule.cssText)
}
})
});
console.log(results)
.foo { --bar: red }
Now you need to parse the result and extract the property value.
You did not specify in your question if CSS selectors' specificity should be regarded, which makes things a lot more complex.
There might also be selectors which implicitly applies style properties to elements. Examples of different specificities:
/* assuming '.foo' is a div child of <body> */
.foo { --x:1 }
body .foo { --x:2 }
body > div { --x:3 }
body * { --x:4 }
div { --x:5 }
Set
Regarding setting, you need to dynamically add a rule or a style tag:
document.head.insertAdjacentHTML("beforeend", `<style id="whatever">--fg-color: red;</style>`)
And when you want to update it, just overwrite the #whatever <style> with innerHTML.
To set the value you can use document.querySelectorAll and the setProperty method on the style of each object:
function setCssVariable(selector, variable, value) {
document.querySelectorAll(selector).forEach(function (element) {
element.style.setProperty(variable, value);
});
}
setCssVariable(".foo", "--fg-color", "black");
And to get the value, assuming all elements of the class have the same value, you can use a similar approach using document.querySelector and the getProperty method on style of the element:
function getCssVariable(selector, variable) {
const element = document.querySelector(selector);
if (element !== null) {
return element.style.getPropertyValue(variable);
}
}
getCssVariable(".foo", "--fg-color");
You can read the variable value from the getComputedStyle method of JS and set the
variable value with style attribute.
let foo = document.querySelector('.foo');
/*You can get the value of variable property from the element where you used the variable*/
//console.log(getComputedStyle(foo).getPropertyValue('--fg-color'));
/*You can set the variable value like this for every element where used the variable and want to choose at runtime with js */
//foo.style.cssText = '--fg-color:black;';
function setCSSProperty(cls, prop, val){
let els = document.querySelectorAll(cls);
if(els){
els.forEach(el => {
el.style.cssText += `${prop}:${val};`
})
}
}
function getCSSPropertyData(cls, prop){
let els = document.querySelectorAll(cls);
let data = [];
if(els){
els.forEach((el,ind) => {
let cs = getComputedStyle(el);
data[ind] = cs.getPropertyValue(prop).trim();
});
}
return data;
}
console.log(getCSSPropertyData('.foo', '--fg-color'));
setCSSProperty('.foo', '--fg-color', 'green');
.foo {
--fg-color: red;
}
.bar {
--fg-color: blue;
}
div {
color: var(--fg-color);
}
<div class="foo">foo</div>
<div class="bar">foo</div>
I'm trying to get this program to add a special character when the assigned button for the character is pressed. The problem is, I'm going to have a lot of functions. Can I somehow just make one function that I can use for all of the buttons?
//These are buttons
var aa = document.querySelector('#aa')
var oo = document.querySelector('#oo')
var uu = document.querySelector('#uu')
var khii = document.querySelector('#khii')
//This is the text box
var textBox = document.querySelector('#typeIn')
//Functions to add a character into the text box
function addAa() {
textBox.innerHTML += "ā";
}
function addOo() {
textBox.innerHTML += "ō";
}
function addUu() {
textBox.innerHTML += "ū";
}
function addKhii() {
textBox.innerHTML += "χ";
}
//Telling the buttons to call on the functions when clicked
aa.onclick = addAa
oo.onclick = addOo
uu.onclick = addUu
khii.onclick = addKhii
Additionally: why does this not work?
var aa = document.querySelector('#aa')
var textBox = document.querySelector('#text')
function addLetter(a) {
textBox.innerHTML += a
}
aa.onclick = addLetter("ā")
This just adds the character once into the text box. Clicking on the button then does nothing. Why does it do that?
Yes you can do it with only one function. Pass the character as parameter to the function. Like that:
version with addEventListener (prefered)
const btns = document.querySelectorAll('button');
const textBox = document.querySelector('#typeIn');
btns.forEach(b => {
b.addEventListener('click', e => {
textBox.innerHTML += e.target.getAttribute('data-char')
})
});
#typeIn {
margin:10px;
padding: 10px;
color: white;
min-height:40px;
background: gray;
}
<button data-char="aa">aa</button>
<button data-char="X">X</button>
<button data-char="ō">ō</button>
<button data-char="ū">ū</button>
<div id="typeIn"></div>
Generally try to avoid onclick events and use eventListener instead.
Version onclick Event
const textBox = document.querySelector('#typeIn');
function add(what) {
textBox.innerHTML += what;
}
#typeIn {
margin:10px;
padding: 10px;
color: white;
min-height:40px;
background: gray;
}
<button onclick="add('aa')">aa</button>
<button onclick="add('X')">X</button>
<button onclick="add('ō')">ō</button>
<button onclick="add('ū')">ū</button>
<div id="typeIn"></div>
You could do something like this:
Add (for example) data-value attributes to each of your buttons
<button data-value="A">A</button>
<button data-value="B">B</button>
<button data-value="C">C</button>
Grab all these buttons, and add "click" event listeners to each, like so:
document
.querySelectorAll('button') // Use appropriate class name here
.forEach(button =>
button
.addEventListener("click", (e) =>
console.log(e.target.dataset.value) // Do whatever you want here
)
)
Modify the listener function's body as per your needs
Here's a link to a JsFiddle that I've created for demo.
I have a button that triggers a script on a webpage. One instance works. When I try to add a second button/script, both buttons trigger the second script only. I know (think?) it's because the var I'm defining for the buttons are not unique to their individual scripts, but every way I attempt I break the whole thing.
button {
display: block;
cursor: pointer;
margin-left: 10px;}
button:after {
content: " (off)";
}
button.on:before {
content: "✓ ";
}
button.on:after {
content:" ";
}
.frac span {
-webkit-font-feature-settings: "frac" 1;
font-feature-settings: "frac" 1;
}
.onum span {
-webkit-font-feature-settings: "onum" 1;
font-feature-settings: "onum" 1;
}
Html:
<button name="frac" id="frac">Fractions</button>
<button name="onum" id="onum">Oldstyle Numbers</button>
This text is supposed change OT features when the buttons are pressed.
JS:
<script> var btn = document.getElementById("frac"),
body = document.getElementById("textA"),
activeClass = "frac";
btn.addEventListener("click", function(e){
e.preventDefault();
body.classList.toggle(activeClass);
btn.classList.toggle('on');
}); </script>
<!-- onum -->
<script> var btn = document.getElementById("onum"),
body = document.getElementById("textA"),
activeClass = "onum";
btn.addEventListener("click", function(f){
f.preventDefault();
body.classList.toggle(activeClass);
btn.classList.toggle('on');
}); </script>
The variance between the scripts/buttons are some of the changes from different things I've done, but I've gone mostly back to the beginning so it's simpler.
In javascript, every variable that you declare is inherently available across the entire page. So, putting them in separate tags will have no effect.
So essentially, your second variable btn is actually overwriting the first one. Rename the second variable to say, btn2.
Or, as an alternative, change the line
btn.classList.toggle('on')
to
this.classList.toggle('on')
this within the click handler will always point to the current button being clicked.
You can do it in fewer lines of code
// you create the array of buttons
let butons = Array.from(document.querySelectorAll("button")),
// you define the _body
_body = document.getElementById("textA")
// for every button in the buttons array (map is an iterator)
butons.map((btn) =>{
//you define the activeClass to be the name attribute of the button
let activeClass = btn.getAttribute("name");
// everytime you click the button
btn.addEventListener("click", (e) =>{
/*this was in your code. I don't know why you need it
e.preventDefault();*/
//you toggle the activeClass & the on class
_body.classList.toggle(activeClass);
btn.classList.toggle("on");
})
})
button {
display: block;
cursor: pointer;
margin-left: 10px;
}
button:after {
content: " (off)";
}
button.on:before {
content: "✓ ";
}
button.on:after {
content: " ";
}
/* I'm using color to visualize the change */
.frac span {
color: red;
}
.onum span {
color: green;
}
<button name="frac" id="frac">Fractions</button>
<button name="onum" id="onum">Oldstyle Numbers</button>
<p id="textA">The variance between the <span>scripts/buttons</span> are some of the changes from different things I've done, but I've gone mostly back to the beginning so it's simpler.</p>
How to use vanilla JavaScript or jQuery to toggle between two classes is a question, that has been asked and answered many times on stackoverflow and other websites.
What I haven't found though is a solution to use the onclick event to toggle between a pool of classes.
What I want to achive is this:
I have a body element with the class "yellow".
When clicking a button, I want this class removed from the body and replaced with the class "green". Clicking the button again should change the class to "red" and next time to "blue" and finally back to "yellow" and so on.
Any ideas are much appreciated.
Here's a simple answer, you can modify it so you push or pop more classes into the array and so on.
var classes = ["yellow", "green", "red"];
var button = $("#changeColor");
var count = 1;
button.on("click", function(){
$("#foo").removeClass();
$("#foo").addClass(classes[count]);
count++;
if(count > 2){
count = 0;
}
});
.yellow {
background-color: yellow;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" style="width: 200px; height: 50px;" class="yellow">
FOO
</div>
<button id="changeColor">CHANGE</button>
Have a look at below snippet. Please note, in pool all colors should be unique otherwise you have to create an extra variable to track the index of applied color.
var pool = ['yellow', 'green', 'red', 'blue']
var body = document.getElementsByTagName('body')[0];
body.style.backgroundColor = 'yellow';
function changeColor() {
var bodyColor = body.style.backgroundColor;
var appliedIndex = pool.indexOf(bodyColor);
if (appliedIndex === pool.length - 1) {
body.style.backgroundColor = pool[0];
} else {
body.style.backgroundColor = pool[appliedIndex + 1];
}
}
<button id="change" onClick="changeColor()">Change</button>
How can compare the background color of an element, when the color is set with javascript, I want a function that toggles the backgroundColor:
function toggleBgColor() {
if(document.getElementById("id").style.backgroundColor === "blue"){
document.getElementById("ide").style.backgroundColor = "red");
}else{
document.getElementById("ide").style.backgroundColor = "blue");
}
}
The problem is that the comparison is always false, so my background is always blue, but it want the color to switch from blue to red and vice versa when the function is called
Use Window.getComputedStyle() — https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle.
The backgroundColor property can get tricky with various representations of color. Consider changing classes instead:
JavaScript
function toggleBgColor() {
var el = document.getElementById("id");
var hasBlue = el.classList.contains('blue');
el.classList.toggle('blue', !hasBlue);
el.classList.toggle('red', hasBlue);
}
CSS
.blue {
background-color: blue;
}
.red {
background-color:red;
}
Or more semantically correct:
JavaScript
function toggleBgColor() {
document.getElementById("id").classList.toggle('selected');
}
CSS
#id {
background-color:red;
}
#id.selected {
background-color:blue;
}
Why not simply add a class that gets toggled?
function toggleBgClass() {
var element = document.getElementById('id');
if (element.classList.contains('blue')) {
element.classList.add('blue');
element.classList.remove('red');
}
else {
element.classList.add('red');
element.classList.remove('blue');
}
}
Now, in your CSS:
.blue {
background-color: blue;
}
.red {
background-color: red;
}
You have written the incorrect code.
The correct code is
function toggleBgColor()
{
if(document.getElementById("ptag").style.backgroundColor === "blue")
{
document.getElementById("ptag").style.backgroundColor = "red";
}
else
{
document.getElementById("ptag").style.backgroundColor = "blue";
}
};
Html File
<html>
<head>
<script type="text/javascript" src="js/backgroundtry.js"></script>
</head>
<body>
<p id="ptag" style="background-color:blue;">
Hi How are you
</p>
<a class="mybutton" onclick="toggleBgColor();">
Change Color
</a>
</body>
</html>