Reputation: 1418
I've recently come to prefer resuable UI modules in the form of single .js files, which manipulate the dom using div.innerText
and so forth. I'm developing a UI framework of sorts (a new and better one I swear) and I plan on allowing other devs to write their own modules to extend my framework.
To ensure that two devs' work doesn't interfere with each other, I'm making my modules self-contained. Then,because they are self-contained, I can rapidly and even recursively deploy them in any div on a page; e.g. call uiElement.deploy(element)
sets up the reusable uiElement
with the element as a parent, through code like the following:
uiElement.deploy=function(root){
uiElement.div=document.createElement("div");
uiElement.div.innerHTML=`
<style>
button{
background:red;
}
</style>
<button>Hey!</button>`;
root.appendChild(uiElement.div);
}
It all works pretty well, but when it comes to styling, I'm a bit wary of declaring <style>
elements in the innerHTML, because they might adversely impact the styling of my other reusable modules.
So, I'm wondering, why hasn't the HTML standard decided that if you put a <style>
element in a container other than <head>
, it only operates on the container's children (i.e. ithe style
tag's siblings) and their decendants? It feels like a good idea to promote code reusability.
And by the way, how might I avoid the problem I've stated above? My current thought is to give the div a unique ID and then edit the css in my <style>
tag, by parsing the innerHTML with regex.
Upvotes: 3
Views: 654
Reputation: 1418
I've revisited the problem and would have recommended to my past self: Shadow DOM!
Shadow DOM can give CSS elements scope. The disadvantage is that you cannot access elements from the document using document.getElementById
, which sadly locks you out of a number of libraries e.g. svg.js.
Here's how to use a shadow root, if you have some DOM element:
let el=document.createElement("div");
el.attachShadow({mode:'open'})
let st=document.createElement("style");
st.innerHTML=`
div{
background:blue;
}
`
el.appendChild(st);
Upvotes: 0
Reputation: 13304
CSS stands for Cascading Style Sheets. The cascading suggests that it is poured down over every element starting at the root node: document
. The specification states that any style
-element always applies to the whole document
.
My solution to your question of applying a own style to the element. However this solution is not elegant and can be solved better, since it will clutter the document with style-elements whenever an element is added.
uiElement.deploy=function(element, className){
uiElement.div=document.createElement("div");
uiElement.div.innerHTML=`
<style>
button.${className}{
background:red;
}
</style>
<button class="${className}">Hey!</button>`;
element.appendChild(uiElement.div);
}
Better would be to add a link
-element which points to a css-file that has style information about your code.
uiElement.deploy=function(element, className){
uiElement.div=document.createElement("div");
//link element - if not present in document: add.
if (!document.querySelector(`link[href='location/${element}.css']`))
{
const link = document.createElement("link");
link.href = `location/${element}.css'`;
document.head.appendChild(link);
}
uiElement.div.innerHTML=`
<button class="${className}">Hey!</button>`;
element.appendChild(uiElement.div);
}
A stylesheet file (.css
) also provides easier and more flexible management of your code, not needing to change the js-file if you just want to change the visual appearance.
Even in the situation above I would highly suggest to set a unique ID or class name to your created elements to differ in your CSS-rules, because CSS-rules are valid for the whole document.
Upvotes: 1
Reputation: 623
Give your outer element an ID
if it doesn't already have one, (or possibly a class
),
then you can write your CSS snippet to only apply to the children of that element:
#thisID button { ... }
Upvotes: 1