I'm making a widget that will be added to external websites, and I have made a page that generates css for them to style it (text color, background color, font size, etc). I end up with a textarea filled with css for them to copy/paste to their website.
Is there a way to add this css to the current page in order to have a live preview?
If you want to add CSS as text
var style = document.createElement('style');
style.innerHTML = 'content';
document.head.appendChild(style);
If you want to add a CSS file
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'css/my.css');
document.head.appendChild(link);
I have traditionally appended a <style> block when doing elements.
var style_rules = [];
style_rules.push("#" + myElemId + " { /* Rules */ } ");
/* ... */
var style = '<style type="text/css">' + style_rules.join("\n") + "</style>";
$("head").append(style);
An important thing to note is that because you don't know what any of the existing styles is, or what id's might conflict on the page, it's very useful to keep track of your id's inside your JavaScript application, then using those to populate the injected <style> block. I also tend to run my names through a prefix function to ensure that the generic names of wrapper, and unit do not conflict (they are turned into something like myunique_wrapper and myunique_unit.
Incorporating a basic CSS reset like #myWrapper {margin: 0; padding: 0} can be a decent starting platform for building your own custom styles.
Addressing your unique case, a live preview so to speak, I would designate a div with standard elements. Then when they click "update" read in the rules and append them to the head. If you want to negate any residual effects from past rules you can remove the last <style> element or better yet give your <style> element an id. I'm not sure if that kind of selection would work, but it should.
var element = document.createElement('style');
element.setAttribute('type', 'text/css');
if ('textContent' in element) {
element.textContent = css;
} else {
element.styleSheet.cssText = css;
}
document.getElementsByTagName('head')[0].appendChild(element);
Can you add a style tag to the DOM, with the contents of the text-area in it? You may want to give it an id so you can change it later.
I recommend you start using a decent framework for your web/JavaScript development, personally I'd go with jQuery.
http://api.jquery.com/css/
There are some code snippets here that show you how to quickly set css properties for elements.
Related
I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
However, I've encountered a different behaviour.
Here, we have legal case name: Johnson V United Care.
I want to convert all words to uppercase, except the "V", which I want to convert to lowercase.
This is what I want: JOHNSON v UNITED CARE.
However, in the below code, CSS uppercase style seems to override the Javascript code.
I've referred the CSS file in the <head> and the JS file just before the closing </body> tag.
What I am doing wrong?
Note: After I've posted the question, I've thought that the JS code only changes the innerHTML, and subsequently CSS style is applied to this new HTML. So, this does not seem like a priority issue. But I still can't figure how to apply JS code after CSS in order to get the correct result.
(function() {
let title = document.querySelector("h1.title>a");
let a = title.innerHTML;
let b = a.match(/\b[v]\b/i);
title.innerHTML = a.replace(b, b.toString().toLowerCase());
})();
h1.title>a {
text-transform: uppercase;
}
<h1 class="title">Johnson V United Care</h1>
I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
That article is very wrong.
Inline style has precedence over rule-sets. It doesn't matter how the two styles are added to the document. It just looks like JS has precedence because JS is used to add inline style.
What I am doing wrong?
CSS changes how the content is presented.
The CSS says it should be presented in uppercase.
It doesn't matter if, in the actual content, a particular character is lower-case because it was written that way in HTML or changed to be that way with JS.
You are changing the content with JS, and then CSS is presenting that content in uppercase.
I'd approach the problem by writing extra markup and styling that.
h1.title>a .name {
text-transform: uppercase;
}
<h1 class="title"><span class="name">Johnson</span> v <span class="name">United Care</a>
</h1>
Actually, it will not be possible to override the CSS property this way, because they are not working on the same property. You're setting the text-transform property in the CSS and in JS code you are just changing the HTML content of the element but not overriding the text-transform property. This way the precedence order will have not effect.
To solve the problem, you should do all text transformations in JS and remove the text-transform property in CSS.
Here is an example:
const title = document.querySelector('h1.title > a');
const polifyText = (str, char) =>
str
.split(' ')
.map(part => (part.includes(char) ? part.toLowerCase() : part.toUpperCase()))
.join(' ');
let newTitle = title.textContent;
let char = newTitle.match(/\b[v]\b/i);
title.textContent = polifyText(newTitle, char);
h1.title > a {
/* Comment this out */
// text-transform: uppercase;
}
<h1 class="title">Johnson v United Care
</h1>
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;
}
I am wanting to be able to select chunks of CSS Rules using JavaScript or jQuery and get them into a variable, basically as the preformatted text you would expect in a style-sheet.
Ideally we would carefully comment our CSS styles and have them simply in the <head> <style> tag on the html page. The JavaScript would locate the particular comment that wraps the rules within the <style> tag on the page, and copy those rules to a variable as text, for later use.
/* CSS Rules */
.example{
font-size: 1em;
color:blue;
}
/* end */
In this case the script would find the string /* CSS Rule */, then select all the lines below it until it hits a terminating comment /* end */
Any ideas? I've googled a fair bit for a solution, but guess this is a pretty unusual thing to be doing, having a hard time finding any pointers.
Welp...you could always have an id on your style tag like
<style id="css">div{ background-color:red; }</style>
And then grab the contents with jquery
var cssText = $('#css').html();
But this whole thing would make Ada Lovelace cry, maybe you can find another way to fullfil your requirements?
It's a bit hacky-ish, but here is one way to do this -
Extract the text (use regex or indexOf) - assuming you have the text block, create a data-uri out of it:
var cssURL = "data:text/css;charset=utf8," + encodeURIComponent(cssTxt);
create a link element and set rel to stylesheet (browser is able to deal with type):
var link = document.createElement("link");
link.rel= "stylesheet";
link.href = cssURL;
Add to header to load and parse:
document.getElementsByTagName("head")[0].appendChild(link);
Example
Only the green should show -
var css = ".s1 {border:1px solid red} " +
"/* start */ .s2 {border:1px solid green} /* end */ " +
".s3 {border:1px solid blue}";
// get css text and convert to data-uri
var start = css.indexOf("/* start */");
var end = css.indexOf("/* end */", start);
var cssTxt = css.substring(start, end);
var cssURL = "data:text/css;charset=utf8," + encodeURIComponent(cssTxt);
// create link element and add to header
var link = document.createElement("link");
link.rel= "stylesheet";
link.href = cssURL;
document.getElementsByTagName("head")[0].appendChild(link);
<div class="s1">Class s1 - ignored</div>
<div class="s2">Class s2 - should have green border</div>
<div class="s3">Class s3 - ignored</div>
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.
I'm trying to develop a Firefox addon/Chrome extension. How to insert a new DOM node to arbitrary place of arbitrary page without being affected by its CSS?
Take a look at this demo: http://jsfiddle.net/za5cop0e/1/. If the web page modify the style of all div under certain node in some way (display: none as example), and I inserted my div to it without knowing that display is modified, my div will not behave as I expect.
One solution I can think of is to override all standard CSS styles with default value, which is unacceptable. Is there more elegant way to do this, for example, document.createElement('div', false), where the second argument indicates to the browser that this node does not inherit any CSS style from ancestors.
You can embed your own css to the DOM element that you are appending.
So for the DOM element you can add css for just that DOM that will override any other as inline CSS preceeds others
http://jsfiddle.net/za5cop0e/4/
var s = document.createElement('style')
s.textContent = 'div { display: none }'; // problematic CSS
document.head.appendChild(s);
// expect to show a black block, but will not show due to the CSS style above
var d = document.createElement('div');
d.style.backgroundColor = 'black';
d.style.width = '100px';
d.style.height = '100px';
d.style.display = 'block'; // here
document.body.appendChild(d);