Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to store temporary live <style> styling

I'm trying to create a website builder (drag and drop page builder) and was wondering where to store the styles when someone changes the styles of an element. For example, in WordPress you can type in your own custom CSS in Customizer (image example: https://i.imgur.com/qaUiVl6.png)

In other page builders like Wix or Google Chrome Inspect Element, you can click button to enable or disable styles.

While making current/live CSS edits to the page, where and how are these styles saved? (I'm not talking about a database as the code has not been saved yet. I'm talking about while making changes onsite changes, where do these "temporary/live" CSS styles get saved?)

like image 862
pixie123 Avatar asked Dec 16 '19 01:12

pixie123


4 Answers

You can use the CSSStyleSheet APIs to generate a stylesheet in memory then use insert and delete methods to add or remove rules from the stylesheet at will. When the user is done modifying you could then pass the generated stylesheet back server side to save perm.

Ref docs can be found here: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet#Methods

Compatability is IE9+ and all other modern browsers so it has good coverage.

Quick and dirty example below.

var style = (function() {
    // Create the <style> tag
    var style = document.createElement("style");
    // Add the <style> element to the page
    document.head.appendChild(style);
    return style;
})();

function AddRule(){
 //append rule from textbox to ss here
  style.sheet.insertRule(document.getElementById("cssIn").value, 0);
  document.getElementById("appliedRules").innerHTML = '';
  var rules = style.sheet.cssRules;
  for (var r in rules) {
    if(rules[r].cssText){
     document.getElementById("appliedRules").innerHTML += '<br>' +  rules[r].cssText;
    }
  }
}
//enable this to see your special prize in the console
//console.log(style.sheet);
<div class="test"> here we go</div>
Add Rule: <input type="text" id="cssIn" value=".test {color:blue}">
<button type="button" onClick="AddRule();">Add</button>

<div id="appliedRules"></div>
like image 98
Travis Acton Avatar answered Nov 18 '22 22:11

Travis Acton


Here is a simple proof-of-concept that demonstrates how this can be done using pure javascript. Just click the save button to see the CSS in the textarea get applied to the page. The CSS is just stored as the input value of the textarea element. You can also make it more complex by using localStorage and an iframe or shadow dom so you only affect a "preview" pane. But this is just a demonstration.

function saveStyles() {
    document.querySelector('#style-container').innerHTML = document.querySelector('#style-input').value;
}
#style-input {
  width: 100%;
  box-sizing: border-box;
  display: block;
  margin-bottom: 8px;
}
<style id="style-container"></style>
<textarea id="style-input" rows="5">body{background:red;}</textarea>
<button onclick="saveStyles()">Save</button>
like image 23
Cave Johnson Avatar answered Nov 18 '22 21:11

Cave Johnson


Here's an alternative that puts the stylesheet into memory and loads it via a blob URL.

This behaves a bit more like a real stylesheet than inline styles do in some edge cases, which may be desirable in some cases. It can also work on a webpage that blocks inline styles via a Content Security Policy (provided blob URL's are allowed).

(function() {
var styles = document.getElementById('styles');
var save = document.getElementById('save');
var link = null;

function getLink() {
  if (!link) {
    link = document.createElement('link');
    link.rel = 'stylesheet';
    document.head.appendChild(link);
  }
  return link;
}

save.addEventListener('click', function() {
  var link = getLink();
  if (link.href) {
    URL.revokeObjectURL(link.href);
  }
  link.href = URL.createObjectURL(new Blob([styles.value], {type: 'text/css'}));
});
})();
#styles {
    display: block;
    width: 95%;
}
<textarea id="styles" rows="5">body {
    background: green;
}
</textarea>
<button id="save">Save</button>
like image 1
Alexander O'Mara Avatar answered Nov 18 '22 21:11

Alexander O'Mara


The answers here focus on the methods for building a stylesheet and adding css rules using common methods browsers provide as part of the DOM api. These are the underlying function calls that any UI framework on the web will use.

But when you ask, "Where is this stored?". In a sense, you are asking how is the "state" managed. If you look at original post jQuery/web app building frameworks, like Backbone.js -- its motto was, "Get your model out of the DOM". So generally the "elements" of the ui-building tools will themselves be represented as component/models.

If you look at view-centric frameworks, like React or Vue, more complex web apps will use a framework like Redux to handle "state", which is stored in single object store. This represents the current options of all the components on the page.

So ultimately, a non-toy WYSIWYG web editor will likely treat each "element" as a component that renders its styles based on an inputted state. 

This coupled with a controlled and predictable way to change state, allows for the managing of complex UI. For instance, the click method would trigger an action that acts like the name of an event handler, triggering the functions (in redux world, reducers), which ultimately changes the state, in our example, color of the element.

The low-level calls to the DOM that facilitate this in a complex web-app/web-editor would be abstracted away.

like image 1
adamrights Avatar answered Nov 18 '22 20:11

adamrights