I'm trying to implement a dark mode that activates according to the current time.
That's how I change the body's background color:
if (darkMode) {
document.body.style.backgroundColor = '#31403E';
} else {
document.body.style.backgroundColor = '#F2EDE4';
}
Can I change the h1 tag's color in some kind of global way? Or do I have to check for the property darkMode in every single doc and then assign the proper color.
In modern JavaScript, it could be:
const elements = document.querySelectorAll('h1')
Array.from(elements).forEach(el => el.style.color = '#31403E')
Hope this helps.
You can define a custom CSS stylesheet for dark mode:
#media (prefers-color-scheme: dark) {
color: white;
background: black
}
Where you can define your custom rules accordingly.
There's a nice trick about using filter as well that you can read a bit further over here
You can see this example over here:
https://codepen.io/rikschennink/pen/GLMLj
Where a class .dark-mode is set to the HTML document when toggling using
html.dark-mode {
filter: invert(100%);
img {
filter: invert(100%);
}
}
Docs
first of all they added dark mode preferences in css, they work like so:
#media (prefers-color-scheme: dark) {
h1 {
color: white;
}
}
but a common workaround to this back when we were developing theme switches was adding a "dark" class to the body and doing the following in css
body.dark h1 {
color: white;
}
IF YOU HAVE TO DO IT WITH JAVASCRIPT you have to loop through each and every h1's in the DOM, but it wont work on newly made h1s using javascript since it'll run on page load only as is.
let h1s = document.querySelectorAll("h1"); //gets all the h1s in the page
h1s.forEach( h1 => h1.style.color = "white");
With javascript you can do it like this:
var elements = document.getElementsByTagName("h1");
for(var i = 0; i < elements.length; i++) {
elements[i].style.color = "#000";
}
I'm trying to add new CSS class to HTML body but only after a button/link is clicked. I have included the code along with some errors information.
I have already created a function that can trigger an alert after the button/link is clicked. it's working perfectly but the ".classList.add " method/option is not taking any effects.
<html>
<head>
<style>
.addBGoverlay {background-color: gray;}
.bG {background-color: white;}
</style>
</head>
<body class="BG">
<a class="dash-menu mega-menu-link " role="button" href="#"><span class="mega-indicator"> navButtn</span></a>
<script type="text/javascript">
var X = document.getElementsByClassName('dash-menu');
var xLength = X.length;
var bg = document.getElementsByTagName('body');
function startAction() {
alert('This a popUp');
bg.classList.add("addBGoverlay");
}
for (var i = 0; i < xLength; i++) {
X[i].addEventListener('click', startAction, false);
}
</script>
</body>
</html>
when I inspect it in chrome it gives me an error "Uncaught TypeError: Cannot read property 'add' of undefined
at HTMLAnchorElement.startAction" and the below line is highlited in yellow color "bg.classList.add("addBGoverlay");"
getElementsByTagName() method will give you a collection of DOM elements. Since this collection don't have a classList property it will fail.
You can fix it by using the below code
bg[0].classList.add("addBGoverlay");
You can also use document.body instead of document.getElementsByTagName('body'). First one (document.body) give you the body object and second one will give you a collection object
For switch to previous state
Approach 1
function startAction() {
let body = document.body ;
if(body.classList.contans("addBGoverlay")){ // body.classList.contans() method will give a Boolean return value
body.classList.remove("addBGoverlay");
}else{
body.classList.add("addBGoverlay");
}
}
Approach 2
var hasBGOverlay = false;
var body = document.body ;
function startAction() {
if(hasBGOverlay){
body.classList.remove("addBGoverlay");
}else{
body.classList.add("addBGoverlay");
}
hasBGOverlay = !hasBGOverlay; // In each call state variable value will update with inverse value
}
Hope this helps
Try with Add ID attribute to body tag.
ie:
<body class="bg" id="dg_body">
js
var bg = document.getElementById('dg_body');
and update css order :
.bG {background-color: white;}
.addBGoverlay {background-color: gray;}
will work.
Change your code from :
bg.classList.add("addBGoverlay");
To:
bg.className += "addBGoverlay";
Hope it helps!
Enclosing it under window.load should solve it as it ensures that the DOM is ready before you try to fetch the elements.
window.onload(function() {
var X = document.getElementsByClassName('dash-menu');
var xLength = X.length;
var bg = document.getElementsByTagName('body');
function startAction() {
alert('This a popUp');
bg.classList.add("addBGoverlay");
}
for (var i = 0; i < xLength; i++) {
X[i].addEventListener('click', startAction, false);
}
});
.addBGoverlay {
background-color: gray;
}
.bG {
background-color: white;
}
<a class="dash-menu mega-menu-link " role="button" href="#"><span class="mega-indicator">navButtn</span></a>
Just change
var bg = document.getElementsByTagName('body')[0];
This will fix the error.
It must resolve your's problem.
you no need to get an element for the body. Document have that one. So
just concatenate the new class.
function startAction() {
alert('This a popUp');
document.body.className += "addBGoverlay";
}
I'm trying to export the whole page as PDF. During certain situation's like, if the CSS is loaded from separate file is not applied in exported PDF. So I'm trying to convert all CSS as inline using this code.
(function ($) {
var rules = document.styleSheets;
for(var rl in rules){
var rule = rules[rl].cssRules;
try{
for (var idx = 0, len = rule.length; idx < len; idx++) {
$(rule[idx].selectorText).each(function (i, elem) {
if($(elem).is(":visible"))
elem.style.cssText += rule[idx].style.cssText;
});
}
}catch(e){
console.log(e);
}
}
})(jQuery);
After I ran this code, my exported PDF is working good. But my DOM is not as before. So is there anyway where I can clone my DOM before operations, and replace the cloned DOM as before after playing with DOM. Hope my question is clear. Thanks in anticipation for the help.
In this Snippet there are 2 much more simpler ways than modifying a stylesheet:
Isolate the <iframe>,<embed>, or <object> by wrapping an element around it then apply styles referencing the wrapper element. This is demonstrated in the Snippet with div.jframe as the wrapper.
Inject a <style> block with new rulesets.
If either one is done with moderate care, you shouldn't be left with conflicting styles.
Note: The PDF in the iframe is sandboxed, so it's not there but everything still applies.
SNIPPET
function injectStyles(rule) {
document.body.insertAdjacentHTML('afterbegin',
'<style>' + rule + '</style>');
}
injectStyles('iframe:hover { border: 5px solid blue; }');
.jframe iframe {
outline: 10px solid tomato;
}
<div class='jframe'>
<iframe src='http://che.org.il/wp-content/uploads/2016/12/pdf-sample.pdf' height='400' width='400'></iframe>
</div>
Generally, when I'm not using JQuery, I use the following utility function to get properties from a stylesheet using Javascript. This works nicely to get values from CSS style sheets:
<!DOCTYPE html>
<html>
<head>
<style>
.foo {
color: red;
}
</style>
<script type = "text/javascript">
function getcss(selector, property)
{
var len = document.styleSheets.length;
for (var idx = 0; idx < len; ++idx)
{
var sheet = document.styleSheets && document.styleSheets[idx];
if (sheet)
{
var r = sheet.rules ? sheet.rules : sheet.cssRules;
if (r)
{
var i = r.length;
while (i--)
{
if (r[i].selectorText && r[i].selectorText.toLowerCase() === selector.toLowerCase())
{
return (r[i].style[property]);
}
}
}
}
}
return null;
}
function exec()
{
alert(getcss(".foo", "color"));
}
</script>
</head>
<body onload = "exec()">
</body>
</html>
The problem is that it doesn't take into account media queries. If I replace the <style> section of the above code with:
.foo {
color: red;
}
#media screen and (max-width: 600px) {
.foo {
color: green;
}
}
...it still outputs red if I shrink the window to smaller than 600px.
Is this correct WC3 behavior? Or is this a browser bug? (I'm testing with Firefox 12 on Ubuntu).
Is there anyway to correct this, so that Javascript "sees" the correct style sheet as required by the media query?
Your code is simply looking through the rules of a stylesheet, and only the first list of rules at that. The rules are a object representation of the stylesheet -- they don't change just because you've resized your browser.
In your code you're never going to see the green rul because you're only iterating over the items in the first CSSRuleList. The trick here is you need to recursively loop over any additional rules that are CSSMediaRule and contain their own CSSRuleList. For you, the sheet.rules contains both a single CSSSyleRule (which is your .foo { color:red; }) and a CSSMediaRule (which is your media query). That second rule then its own CSSRuleList, which you can traverse to find your green color.
In this case, here's where your data lies:
// Assuming sheet 0 is your stylesheet above
var sheet = document.styleSheets[0];
// First rule is ".foo { color: red; }"
console.log(sheet.cssRules[0].cssText);
// Second Rule is your "#media" and its first rule is ".foo { color: green; }"
console.log(sheet.cssRules[1].cssRules[0].cssText);
How do you add CSS rules (eg strong { color: red }) by use of Javascript?
The simple-and-direct approach is to create and add a new style node to the document.
// Your CSS as text
var styles = `
.qwebirc-qui .ircwindow div {
font-family: Georgia,Cambria,"Times New Roman",Times,serif;
margin: 26px auto 0 auto;
max-width: 650px;
}
.qwebirc-qui .lines {
font-size: 18px;
line-height: 1.58;
letter-spacing: -.004em;
}
.qwebirc-qui .nicklist a {
margin: 6px;
}
`
var styleSheet = document.createElement("style")
styleSheet.innerText = styles
document.head.appendChild(styleSheet)
You can also do this using DOM Level 2 CSS interfaces (MDN):
var sheet = window.document.styleSheets[0];
sheet.insertRule('strong { color: red; }', sheet.cssRules.length);
...on all but (naturally) IE8 and prior, which uses its own marginally-different wording:
sheet.addRule('strong', 'color: red;', -1);
There is a theoretical advantage in this compared to the createElement-set-innerHTML method, in that you don't have to worry about putting special HTML characters in the innerHTML, but in practice style elements are CDATA in legacy HTML, and ‘<’ and ‘&’ are rarely used in stylesheets anyway.
You do need a stylesheet in place before you can started appending to it like this. That can be any existing active stylesheet: external, embedded or empty, it doesn't matter. If there isn't one, the only standard way to create it at the moment is with createElement.
Shortest One Liner
// One liner function:
const addCSS = css => document.head.appendChild(document.createElement("style")).innerHTML=css;
// Usage:
addCSS("body{ background:red; }")
The solution by Ben Blank wouldn't work in IE8 for me.
However this did work in IE8
function addCss(cssCode) {
var styleElement = document.createElement("style");
styleElement.type = "text/css";
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = cssCode;
} else {
styleElement.appendChild(document.createTextNode(cssCode));
}
document.getElementsByTagName("head")[0].appendChild(styleElement);
}
Here's a slightly updated version of Chris Herring's solution, taking into account that you can use innerHTML as well instead of a creating a new text node:
function insertCss( code ) {
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
// IE
style.styleSheet.cssText = code;
} else {
// Other browsers
style.innerHTML = code;
}
document.getElementsByTagName("head")[0].appendChild( style );
}
You can add classes or style attributes on an element by element basis.
For example:
<a name="myelement" onclick="this.style.color='#FF0';">text</a>
Where you could do this.style.background, this.style.font-size, etc. You can also apply a style using this same method ala
this.className='classname';
If you want to do this in a javascript function, you can use getElementByID rather than 'this'.
This easy example of add <style> in head of html
var sheet = document.createElement('style');
sheet.innerHTML = "table th{padding-bottom: 0 !important;padding-top: 0 !important;}\n"
+ "table ul { margin-top: 0 !important; margin-bottom: 0 !important;}\n"
+ "table td{padding-bottom: 0 !important;padding-top: 0 !important;}\n"
+ ".messages.error{display:none !important;}\n"
+ ".messages.status{display:none !important;} ";
document.body.appendChild(sheet); // append in body
document.head.appendChild(sheet); // append in head
Source Dynamic style - manipulating CSS with JavaScript
This is my solution to add a css rule at the end of the last style sheet list:
var css = new function()
{
function addStyleSheet()
{
let head = document.head;
let style = document.createElement("style");
head.appendChild(style);
}
this.insert = function(rule)
{
if(document.styleSheets.length == 0) { addStyleSheet(); }
let sheet = document.styleSheets[document.styleSheets.length - 1];
let rules = sheet.rules;
sheet.insertRule(rule, rules.length);
}
}
css.insert("body { background-color: red }");
YUI just recently added a utility specifically for this. See stylesheet.js here.
In modern browsers, you can use document.adoptedStyleSheets to add CSS.
const sheet = new CSSStyleSheet();
sheet.replace("strong { color: red; }");
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
One advantage of this approach is that you do not have to wait for the <head> element to even become available, which may be a concern in browser extension code that runs very early.
if you know at least one <style> tag exist in page , use this function :
CSS=function(i){document.getElementsByTagName('style')[0].innerHTML+=i};
usage :
CSS("div{background:#00F}");
Another option is to use JQuery to store the element's in-line style property, append to it, and to then update the element's style property with the new values. As follows:
function appendCSSToElement(element, CssProperties)
{
var existingCSS = $(element).attr("style");
if(existingCSS == undefined) existingCSS = "";
$.each(CssProperties, function(key,value)
{
existingCSS += " " + key + ": " + value + ";";
});
$(element).attr("style", existingCSS);
return $(element);
}
And then execute it with the new CSS attributes as an object.
appendCSSToElement("#ElementID", { "color": "white", "background-color": "green", "font-weight": "bold" });
This may not necessarily be the most efficient method (I'm open to suggestions on how to improve this. :) ), but it definitely works.
Here's a sample template to help you get started
Requires 0 libraries and uses only javascript to inject both HTML and CSS.
The function was borrowed from the user #Husky above
Useful if you want to run a tampermonkey script and wanted to add a toggle overlay on a website (e.g. a note app for instance)
// INJECTING THE HTML
document.querySelector('body').innerHTML += '<div id="injection">Hello World</div>';
// CSS INJECTION FUNCTION
//https://stackoverflow.com/questions/707565/how-do-you-add-css-with-javascript
function insertCss( code ) {
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
// IE
style.styleSheet.cssText = code;
} else {
// Other browsers
style.innerHTML = code;
}
document.getElementsByTagName("head")[0].appendChild( style );
}
// INJECT THE CSS INTO FUNCTION
// Write the css as you normally would... but treat it as strings and concatenate for multilines
insertCss(
"#injection {color :red; font-size: 30px;}" +
"body {background-color: lightblue;}"
)
Here's my general-purpose function which parametrizes the CSS selector and rules, and optionally takes in a css filename (case-sensitive) if you wish to add to a particular sheet instead (otherwise, if you don't provide a CSS filename, it will create a new style element and append it to the existing head. It will make at most one new style element and re-use it on future function calls). Works with FF, Chrome, and IE9+ (maybe earlier too, untested).
function addCssRules(selector, rules, /*Optional*/ sheetName) {
// We want the last sheet so that rules are not overridden.
var styleSheet = document.styleSheets[document.styleSheets.length - 1];
if (sheetName) {
for (var i in document.styleSheets) {
if (document.styleSheets[i].href && document.styleSheets[i].href.indexOf(sheetName) > -1) {
styleSheet = document.styleSheets[i];
break;
}
}
}
if (typeof styleSheet === 'undefined' || styleSheet === null) {
var styleElement = document.createElement("style");
styleElement.type = "text/css";
document.head.appendChild(styleElement);
styleSheet = styleElement.sheet;
}
if (styleSheet) {
if (styleSheet.insertRule)
styleSheet.insertRule(selector + ' {' + rules + '}', styleSheet.cssRules.length);
else if (styleSheet.addRule)
styleSheet.addRule(selector, rules);
}
}
I always forget how to add a class to an HTML element and this SO comes up early in Google, but no one has added the modern way of doing this so here goes.
To add a CSS style you can select the element and call .classList.add(<className>)
for example:
document.querySelector("#main").classList.add("bg-primary");
You may also need to remove other class(es) which clash with the one you add. To do so:
document.querySelector("#main").classList.remove("bg-secondary");
That's it. Run the sample and you'll see the setInterval() method add & remove the styles every 3 seconds.
let useSecondary = false;
setInterval(changeBgColor, 3000);
function changeBgColor(){
if (useSecondary){
document.querySelector("#main").classList.remove("bg-primary");
document.querySelector("#main").classList.add("bg-secondary");
}
else{
document.querySelector("#main").classList.remove("bg-secondary");
document.querySelector("#main").classList.add("bg-primary");
}
useSecondary = !useSecondary;
}
* {
transition: all 0.5s ease-in-out;
}
.bg-primary {
background-color: green;
}
.bg-secondary{
background-color: yellow;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div >
<div id="main" >
Example text has background color changed every 3 seconds by adding / removing CSS styles.
</div>
</div>
</body>
</html>
use .css in Jquery like $('strong').css('background','red');
$('strong').css('background','red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<strong> Example
</strong>