80

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?

John Smith
  • 861
  • 1
  • 8
  • 5

5 Answers5

173

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);
Zanon
  • 29,231
  • 20
  • 113
  • 126
vogdb
  • 4,669
  • 3
  • 27
  • 29
  • 30
    JavaScript allows not to put `;` at the end, but it can lead to unexpected behaviour and is considered bad practice. – Daniel W. Oct 16 '13 at 09:42
  • Is there any npm package / js library to do this where I can just pass a CSS JSON object? – gerrytan Apr 13 '17 at 02:48
  • Unfortunately I don't know a library like that. – vogdb Apr 20 '17 at 16:25
  • Does this still work even if the css is loaded right after page load? – Jovanni G Oct 04 '17 at 04:40
  • It worked for me in my environment but it is always better to try in your particular case. – vogdb Oct 05 '17 at 08:34
  • 1
    I had to use `innerText` instead of `innerHTML` to get this to work in Chrome. – Nic Jul 31 '18 at 06:18
  • 4
    you can just do `document.head` instead of `document.getElementsByTagName('head')[0]` – Pontiacks Feb 16 '20 at 10:42
  • With modern linters... `;` have been deprecated in modern dev workflows/tooling, depending on your environment – Ray Foss Sep 10 '20 at 17:38
  • 1
    That's wonderful. I didn't use them in my answer but those Crockford followers had been attacking this post for several years every week, demanding semicolons. Finally they made while I wasn't online to for some time. Anyway, I am happy that common sense prevailed. – vogdb Sep 13 '20 at 07:22
  • @RayFoss what do you mean by modern? for example in Google Earth Engine Editor it demands it – Flash Thunder Apr 24 '21 at 00:47
  • 1
    @FlashThunder The best guage of guidelines are the ESLint rule sets in use... the biggest ones like AirBnB, Standard and most Typescript ones dropped the `;`. The reasoning is you need to know when you "need" one even if you use them, so why use them. There is a good slide show on it from the maker of Vue, Evan You. http://slides.com/evanyou/semicolons – Ray Foss Apr 26 '21 at 14:03
18

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.

Josh K
  • 28,364
  • 20
  • 86
  • 132
  • 7
    I would recommend you adjust your answer to exclude the use of jQuery as the OP did not mention the use of it, nor did they tag the question with jquery – jondavidjohn Jan 31 '11 at 03:46
  • @Jondavid: I make one call with jQuery, which is actually just as easily done with pure JavaScript. Simple DOM manipulation. My answer uses jQuery, if the OP would like to not use jQuery then he can of course modify that one small portion of my example code. – Josh K Jan 31 '11 at 04:05
  • 3
    Then why wouldn't you just adjust your answer to conform to the OP's specifications? – jondavidjohn Jan 31 '11 at 04:06
  • 2
    @jondavid: The OP has neglected to give any specifications. – Josh K Jan 31 '11 at 05:09
  • jquery is super common, and its not the responsibility of answers to try to guess at the tools at an OP's disposal. When in doubt, recommend what you would do. I certainly wouldn't recommend using pure dom manipulation.. – B T Jul 05 '13 at 20:39
7
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);
Konstantin Tarkus
  • 37,618
  • 14
  • 135
  • 121
0

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.

Antoine Latter
  • 1,545
  • 10
  • 13
-13

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.

RichardTheKiwi
  • 105,798
  • 26
  • 196
  • 262
  • I do not consider jQuery a framework, neither do jQuery considers itself a framework, according to jQuery, "jQuery is a fast, small, and feature-rich JavaScript library." – Aaron C Dec 01 '20 at 22:25
  • @AaronC while true, that seems like pedantry in context - the substance of the statement is "I recomment using a [mature and well-maintained reusable code which solves a lot of these common problems], so that you can focus on expressing the big picture semantics of your logic and not the implementation details" - words like "framework" have general abstract composable meanings too, not just their more specific/distinct and thingified/reified meanings that we use in software, and precision of meaning is a value that is relative to the context of what you are actually saying. – mtraceur May 29 '22 at 20:56
  • Now I'm sure some of the downvotes here are not because the answer uses "framework" instead of a word which is more appropriate if you project a specific rigid context onto it. But when I see framework in this answer I can immediately tell precisely because "framework" is wrong in that rigid interpretation - that the answerer's meaning is *more abstract and flexible* - the shape of this answer's recommendation applies regardless of whether the reusable code you use is a "library" or "framework" or whatever. And I hope most people downvoting are doing it for other reasons than that wording nit. – mtraceur May 29 '22 at 21:00
  • Now having said that, the critique I have for this answer is that when someone asks "how do I do [x]", the answer "use something that already does [x]" is only sometimes appropriate, and in particular is not appropriate if the asker wants to understand the underlying workings, or if the asker has good reason to not reuse the things that already do [x]. (But to be fair to the answer, when people ask or search for "how do I do [x]" it is actually ambiguous - do you want any practical get-it-done answer or the from-the-foundation answer? could be either.) – mtraceur May 29 '22 at 21:08
  • @mtraceur I disagree. – Aaron C Jun 02 '22 at 13:51