Set multiple values for one css attribute - javascript

Is it possible to set two Values for a single attribute on a CSS ID, e.g.
height: 12em; height: 12rem;
for a single id?
I know it's possible to do this with CSS, but I want to change the height via javascript, and have both values on one attribute, so that 'em' functions as a fallback for Browsers not supporting 'rem'.
Example:
function updateHeight() {
var testElem = document.getElementById("testId");
testElem.style.height = "12em";
testElem.style.height = "12rem";
//testElem.style.height = "12em; 12rem;"; doesn't work, applies "12em"
}
#testId {
height: 8em;
height: 8rem;
background-color: black;
color: white;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="utf-8" />
</head>
<body>
<div id="testId">
BlaBla
</div>
<button onclick="updateHeight()">Bla</button>
</body>
</html>

You can use a class instead
function updateHeight() {
var testElem = document.getElementById("testId");
testElem.classList.add('high');
}
#testId {
height: 8em;
height: 8rem;
background-color: black;
color: white;
}
#testId.high { /* remember that ID is more specific than class */
height: 12em;
height: 12rem;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="utf-8" />
</head>
<body>
<div id="testId">
BlaBla
</div>
<button onclick="updateHeight()">Bla</button>
</body>
</html>
Or if the value is dynamic, you'd probably have to insert a style tag to be able to support CSS cascading
function updateHeight() {
var value = 12; // or something dynamic
var styles = '#testId {height: '+value+'em; height: '+value+'rem;}';
var tag = document.createElement('style');
tag.innerHTML = styles;
document.querySelector('head').appendChild(tag);
}
#testId {
height: 8em;
height: 8rem;
background-color: black;
color: white;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="utf-8" />
</head>
<body>
<div id="testId">
BlaBla
</div>
<button onclick="updateHeight()">Bla</button>
</body>
</html>

Yes, you can. This is defined by CSS Cascade:
Each property declaration applied to an element contributes a
declared value for that property associated with the
element.
These values are then processed by the cascade to choose a single
“winning value”.
The cascaded value represents the result of the
cascade: it is the declared value that wins the cascade (is
sorted first in the output of the cascade).
Then, if you use
height: 8em;
height: 8rem;
there will be 2 declared values for the property height: 8em and 8rem. The latter will will the cascade, becoming the cascaded value.
If some browser does not support one of them, the other one will be the only declared value, so it will win the cascade.
If some browser does not support any of them, the output of the cascade will be the empty list, and there won't be any cascaded value. The specified value will be the result of the defaulting processes (the initial value in this case, because height is not an inherited property).
However, with JavaScript there is a problem. setProperty, used under the hood by camel case IDL properties in .style, uses the set a CSS declaration algorithm, which overwrites existing declarations:
If property is a case-sensitive match for a property name of a CSS declaration in declarations, let declaration be that CSS
declaration.
Otherwise, append a new CSS declaration with the property name property to declarations and let declaration be that CSS declaration.
There are some workarounds:
Use cssText instead of camel case IDL attributes:
testElem.style.cssText += "; height: 12em; height: 12rem; ";
Check the style after setting it. If you get the empty string, it means it wasn't recognized.
testElem.style.height = "12rem";
if(!testElem.style.height) testElem.style.height = "12em";
Don't set the styles in the inline style declaration. Create a new stylesheet instead, or add some class to the element to trigger some CSS from an existing stylesheet.

Related

CSS not working properly on Custom HTML Elements

I've been trying to make a custom HTML Element by extending the HTMLElement class. I try adding some style to it by linking a CSS file that is in the same directory as my other two files - index.html and custom.css.
Main folder
index.html
custom.css
custom.js
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="nofollow" type="text/css" href=''>
</head>
<body>
<script src="./custom.js"></script>
<smooth-button text="Smooth button" no-1 = 1 no-2 = 2></smooth-button>
</body>
</html>
custom.css:
smooth-button{
display: block;
color: blue;
background-color: orange;
}
custom.js:
class SmoothButton extends HTMLElement{
constructor(){
super();
this.shadow = this.attachShadow({mode: "open"})
}
connectedCallback(){
this.render();
}
render(){
this.SumOfNo1AndNo2 = null;
if(this.getAttribute("no-1")!=null && this.getAttribute("no-2")!=null){
this.SumOfNo1AndNo2 = parseInt(this.getAttribute("no-1")) +
parseInt(this.getAttribute("no-2"));
}
else{
console.log("Invalid attribute.")
}
this.shadow.innerHTML = `<button>` + this.getAttribute("text") + " " + this.SumOfNo1AndNo2
+ "</button>"
}
}
customElements.define("smooth-button", SmoothButton);
With this, I get a button as expected, with the text, but the style is applied to the element as a whole and not to the elements it's made of. How can I apply the styles separately to each of its elements (just a <button> for now) with an external CSS file? I'm using external CSS because it's somehow better as I read it here.
In addition to the answers from Brad and Emiel,
(Brad) Bluntly add a <style> element inside shadowDOM
Do read about adopted StylesSheets (Chromium only)
(Emiel) use cascading CSS properties
There are more options to style shadowDOM:
Learn about Inheritable Styles
https://lamplightdev.com/blog/2019/03/26/why-is-my-web-component-inheriting-styles/
use shadow parts
<style>
::part(smoothButton){
display: block;
color: blue;
background-color: orange;
}
</style>
<smooth-button></smooth-button>
<smooth-button></smooth-button>
<script>
customElements.define("smooth-button", class extends HTMLElement {
constructor(){
super()
.attachShadow({mode:"open"})
.innerHTML = `<button part="smoothButton">LABEL</button>`;
}
});
</script>
https://developer.mozilla.org/en-US/docs/Web/CSS/::part
https://meowni.ca/posts/part-theme-explainer/
https://css-tricks.com/styling-in-the-shadow-dom-with-css-shadow-parts/
https://dev.to/webpadawan/css-shadow-parts-are-coming-mi5
https://caniuse.com/mdn-html_global_attributes_exportparts
But...
The first question you should ask yourself:
Do I really need shadowDOM?
If you don't want its encapsulating behavior, then do not use shadowDOM
<style>
.smoothButton{
display: block;
color: blue;
background-color: orange;
}
</style>
<smooth-button></smooth-button>
<smooth-button></smooth-button>
<script>
customElements.define("smooth-button", class extends HTMLElement {
connectedCallback(){
this.innerHTML = `<button class="smoothButton">LABEL</button>`;
}
});
</script>
shadowDOM <slot>
Another alternative is to use shadowDOM <slot> elements, because they are styled by its container element
<style>
.smoothButton{
display: block;
color: blue;
background-color: orange;
}
</style>
<smooth-button><button class="smoothButton">LABEL</button></smooth-button>
<smooth-button><button class="smoothButton">LABEL</button></smooth-button>
<script>
customElements.define("smooth-button", class extends HTMLElement {
constructor(){
super()
.attachShadow({mode:"open"})
.innerHTML = `<slot></slot>`;
}
});
</script>
When you go down the <slot> rabbithole, be sure to read the (very long) post:
::slotted CSS selector for nested children in shadowDOM slot
Additionally to Brad's answer. One of the ways you can apply styles from the Light DOM to the Shadow DOM is with CSS Variables.
smooth-button{
display: block;
--button-color: blue;
--button-background-color: orange;
}
render() {
this.shadow.innerHTML = `
<style>
button {
color: var(--button-color);
background-color: var(--button-background-color);
}
</style>
<button>
${this.getAttribute("text")} ${this.SumOfNo1AndNo2}
</button>
`;
)
With this, I get a button as expected, with the text, but the style is applied to the element as a whole and not to the elements it's made of.
This is actually how the custom element is supposed to work. You can't apply styles to the shadow DOM from the outer document. If you could, you'd have a high likelihood of breaking the custom element styling through external modification.
All is not lost however! The reason the button is a different color from its background is due to the user agent stylesheet. You can actually set some CSS to tell the background to inherit the parent background color. Try adding this to your custom element:
const style = document.createElement('style');
style.textContent = `
button {
background: inherit;
}
`;
this.shadow.append(style);
JSFiddle: https://jsfiddle.net/5t2m3bku/
(Also note that it's not really a great idea to interpolate/concatenate text directly into HTML. That text gets interpreted as HTML, which can lead to invalid HTML if reserved characters are used, and even potential XSS vulnerabilities. You might modify that line where you set innerHTML to set the text, or switch to a template engine.)

Webcomponents is re-initializing every time while working with Vue js

I have created a webcomponent for a generic input boxes that i needed across multiple projects.
the design functionality remains same only i have to use switch themes on each projects.so i have decided to go on with webcomponents.One of the projects is based on Vue Js.In Vue js the DOM content is re-rendered while each update for enabling reactivity. That re-rendering of vue template is reinitializing my custom webcomponent which will result in loosing all my configurations i have assigned to the component using setters.
I know the below solutions. but i wanted to use a setter method.
pass data as Attributes
Event based passing of configurations.
Using Vue-directives.
using v-show instead of v-if
-- Above three solutions doesn't really match with what i am trying to create.
I have created a sample project in jsfiddle to display my issue.
Each time i an unchecking and checking the checkbox new instances of my component is creating. which causes loosing the theme i have selected. (please check he active boxes count)
For this particular example i want blue theme to be displayed. but it keep changing to red
JSFiddle direct Link
class InputBox extends HTMLElement {
constructor() {
super();
window.activeBoxes ? window.activeBoxes++ : window.activeBoxes = 1;
var shadow = this.attachShadow({
mode: 'open'
});
var template = `
<style>
.blue#iElem {
background: #00f !important;
color: #fff !important;
}
.green#iElem {
background: #0f0 !important;
color: #f00 !important;
}
#iElem {
background: #f00;
padding: 13px;
border-radius: 10px;
color: yellow;
border: 0;
outline: 0;
box-shadow: 0px 0px 14px -3px #000;
}
</style>
<input id="iElem" autocomplete="off" autocorrect="off" spellcheck="false" type="text" />
`;
shadow.innerHTML = template;
this._theme = 'red';
this.changeTheme = function(){
this.shadowRoot.querySelector('#iElem').className = '';
this.shadowRoot.querySelector('#iElem').classList.add(this._theme);
}
}
connectedCallback() {
this.changeTheme();
}
set theme(val){
this._theme = val;
this.changeTheme();
}
}
window.customElements.define('search-bar', InputBox);
<!DOCTYPE html>
<html>
<head>
<title>Wrapper Component</title>
<script src="https://unpkg.com/vue"></script>
<style>
html,
body {
font: 13px/18px sans-serif;
}
select {
min-width: 300px;
}
search-bar {
top: 100px;
position: absolute;
left: 300px;
}
input {
min-width: 20px;
padding: 25px;
top: 100px;
position: absolute;
}
</style>
</head>
<body>
<div id="el"></div>
<!-- using string template here to work around HTML <option> placement restriction -->
<script type="text/x-template" id="demo-template">
<div>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
</div>
</script>
<script type="text/x-template" id="select2-template">
<select>
<slot></slot>
</select>
</script>
<script>
var vm = new Vue({
el: "#el",
template: "#demo-template",
data: {
visible: true,
},
mounted(){
let self = this
setTimeout(()=>{
self.$refs.iBox.theme = 'blue';
} , 0)
}
});
</script>
</body>
</html>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
Vue's v-if will add/remove the whole DIV from the DOM
So <search-bar> is also added/removed on every checkbox click
If you want a state for <search-bar> you have to save it someplace outside the <search-bar> component:
JavaScript variable
localStorage
.getRootnode().host
CSS Properties I would go with this one, as they trickle into shadowDOM
...
...
Or change your checkbox code to not use v-if but hide the <div> with any CSS:
display: none
visibility: hidden
opacity: 0
move to off screen location
height: 0
...
and/or...
Managing multiple screen elements with Stylesheets
You can easily toggle styling using <style> elements:
<style id="SearchBox" onload="this.disabled=true">
... lots of CSS
... even more CSS
... and more CSS
</style>
The onload event makes sure the <style> is not applied on page load.
activate all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = false
remove all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = true
You do need CSS Properties for this to work in combo with shadowDOM Elements.
I prefer native over Frameworks. <style v-if='visible'/> will work.. by brutally removing/adding the stylesheet.

Buttons are not appearing in the html on click

Good day, Im creating buttons using DOM and toggle to change the paragraph in the HTML file when you click it in on in JavaScript however, the buttons are not appearing in the html and I've set it up so it sits on top of the paragraph. I have used CSS to style the buttons.
Here are the JC, HTML and CSS files:
HTML:
<!DOCTYPE html>
<head>
<link scr="stylesheet" type="text/css" href="A3 .css">
<script src="A3.js"></script>
</head>
<div id ="button_containter"></div>
<body id= target_p>
In considering any new subject, there is frequently a tendency, first, to overrate what we find to be already interesting
or remarkable; and, secondly, by a sort of natural reaction, to undervalue the blue state of the case, when we do
discover that our notions have surpassed those that were really tenable
</body>
</html>
JS:
let para = document.getElementById("target_p");
class ParagraphChanger {
constructor (p){
this.p=p;
var btnDiv = document.getElementById("button_containter");
let btnBold = this.createButton("toggle bold");
btnBold.addEventListener('click',() => this.makeBold());
btnDiv.appendChild(btnBold);
let widthBtn = this.createButton("toggle width");
widthBtn.addEventListener('click', () => this.changedWidth());
btnDiv.appendChild(widthBtn);
let clrBtn = this.createButton("togglt color");
clrBtn.addEventListener('click', () => this.changeColor());
clrBtn.appendChild(clrBtn);
let szBtn = this.createButton("toggle size");
szBtn.addEventListener('click', () => this.changeSize());
}
createButton (name){
const btn = document.createElement('button_container');
const buttonName = document.createTextNode(name);
buttonName.appendChild(buttonName);
return btn;
}
makeBold(){
// changing the size to bold, getting it from CSS s
this.p.classList.toggle("Toggle_bold");
}
changedWidth(){
this.p.classList.toggle('Toggle_width');
}
changeColor(){
this.p.classList.toggle('Toggle_width');
}
changeSize(){
this.p.classList.toggle('Toggle_size');
}
window.onload = () => {
new ParagraphChanger(document.getElementById('target_p;'));
}
};
CSS:
Toggle_bold {
font: bold;
}
.Toggle_width{
width: 50%;
}
.Toggle_width{
color: #ff2800;
}
.Toggle_size{
font-size: 100%;
}
#button_containter{
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
JS issues:
First, when you call document.createElement(), you are accidentally passing in the name of the container. Instead, you should pass in button, like so: const btn = document.createElement('button');
Next, you don't need to create a text node. btn.innerText = name will work just fine ;)
Finally, you accidentally stuck a semicolon in your new ParagraphChanger(document.getElementById('target_p;'));.
Also, you put the call to window.onload inside the class; move it outside!
CSS issues:
font: bold; won't work, you need to use font-weight: bold;
Also, you forgot a period in your Toggle_bold selector. It should be .Toggle_bold to select the class.
Here's a CodePen with your final, fixed code.
I hope this solves your problem!
Took a bit of editing as your code had a lot of issue. The container id had a typo, the button was created with button_container which is actually the ID etc. Below you can see how the button is created.
CreateElement:
In createElement we must specify the tag name not the ID itself to created new html element. Read more here.
document.createElement('button'); //p tag, h1,h2,h3 tags etc, divs
SetAttribute:
For the id we use setAttribute which Sets the value of an attribute on the specified element. If the attribute already exists, the value is updated; otherwise a new attribute is added with the specified name and value.
btn.setAttribute("id", "button_content"); //Ids,classes and data-attribute
//id="myid", class="myclass", data-myid=1
InnerText:
Finally for the value, we use innerText to set text of button and call it onLoad.
btn.innerText ="Click me";
The complete code:
<!DOCTYPE html>
<html>
<head>
<title>Website Project</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<style>
Toggle_bold {
font: bold;
}
.Toggle_width{
width: 50%;
}
.Toggle_width{
color: #ff2800;
}
.Toggle_size{
font-size: 100%;
}
#button_containter{
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
</style>
</head>
<body>
<div id ="button_container"></div>
<script>
function createButton (name){
const btn = document.createElement('button'); //Add button with create Element
btn.setAttribute("id", "button_content"); //Add Id with setAttribute method
btn.innerText ="Click me";// Add value of the button with innerText property
let container = document.getElementById("button_container"); //Fetch container div
console.log(btn);
console.log(container);
container.appendChild(btn); //Append button to it.
}
function makeBold(){
// changing the size to bold, getting it from CSS s
this.p.classList.toggle("Toggle_bold");
}
function changedWidth(){
this.p.classList.toggle('Toggle_width');
}
function changeColor(){
this.p.classList.toggle('Toggle_width');
}
function changeSize(){
this.p.classList.toggle('Toggle_size');
}
window.onload = () => {
createButton();// call button function here to create the button
}
</script>
</body>
</html>
Finally, i believe we learn by doing and so i hope this was helpfull in clearing some of the confusions as well solving your problem :).

Return value of document.querySelectorAll("[value='a']") would not change after element value being modified [duplicate]

N.B.: I should note that the proper solution to this is to just use the 'placeholder' attribute of an input, but the question still stands.
Another N.B.: Since, as Quentin explains below, the "value" attribute stores the default value, and the input.value IDL attribute stores the current value, the JavaScript I used to "fix" the problem in my below example is non-conforming, as it uses the (non-IDL) value attribute to store current, rather than default, values. Besides, it involves DOM access on every key press, so it was always just a flawed demo of the problem I was having. It's actually quite terrible code and shouldn't be used ever.
CSS selectors made me think that I could make an input with a label that acts as a preview without any JS. I absolutely position the input at 0,0 inside the label (which is displayed as an inline-block) and give it a background of "none", but only if it's got a value of "" and isn't focussed, otherwise it has a background colour, which obscures the label text.
The HTML5 spec says that input.value reflects the current value of an input, but even though input.value updates as you type into an input, CSS using the input[value=somestring] selector applies based only on what was explicitly typed into the document, or set in the DOM by the JavaScript setAttribute method (and perhaps by other DOM-altering means).
I made a jsFiddle representing this.
Just in case that is down, here is an HTML document containing the relevant code:
<!doctype html>
<head>
<meta charset="utf-8" />
<title>The CSS Attribute selector behaves all funny</title>
<style>
label {
display: inline-block;
height: 25px;
line-height: 25px;
position: relative;
text-indent: 5px;
min-width: 120px;
}
label input[value=""] {
background: none;
}
label input, label input:focus {
background: #fff;
border: 1px solid #666;
height: 23px;
left: 0px;
padding: 0px;
position: absolute;
text-indent: 5px;
width: 100%;
}
</style>
</head>
<body>
<form method="post">
<p><label>name <input required value=""></label></p>
</form>
<p><button id="js-fixThis">JS PLEASE MAKE IT BETTER</button></p>
<script>
var inputs = document.getElementsByTagName('input');
var jsFixOn = false;
for (i = 0; i < inputs.length; i++) {
if (inputs[i].parentNode.tagName == 'LABEL') { //only inputs inside a label counts as preview inputs according to my CSS
var input = inputs[i];
inputs[i].onkeyup= function () {
if (jsFixOn) input.setAttribute('value', input.value);
};
}
}
document.getElementById('js-fixThis').onclick = function () {
if (jsFixOn) {
this.innerHTML = 'JS PLEASE MAKE IT BETTER';
jsFixOn = false;
} else {
this.innerHTML = 'No, actually, break it again for a moment.';
jsFixOn = true;
}
};
</script>
</body>
</html>
I could be missing something, but I don't know what.
The value attribute sets the default value for the field.
The value property sets the current value for the field. Typing in the field also sets the current value.
Updating the current value does not change the value attribute.
Attribute selectors only match on attribute values.
There are new pseudo classes for matching a number of properties of an input element
:valid
:invalid
:in-range
:out-of-range
:required
A required element with no value set to it will match against :invalid. If you insist on using the value instead of placeholder, you could simply add a pattern or a customValidity function to force your initial value to be counted as invalid.

Accessing a CSS custom property (aka CSS variable) through JavaScript

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>

Categories