最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Where to store temporary live <style> styling - Stack Overflow

programmeradmin0浏览0评论

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: .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?)

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.sstatic/osKEF.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?)

Share Improve this question edited Dec 20, 2019 at 20:33 pixie123 asked Dec 16, 2019 at 1:37 pixie123pixie123 9793 gold badges15 silver badges28 bronze badges 5
  • I am not sure I understand the question, but if you are looking to modify the text in a style tag with javascript consider this: stackoverflow./questions/13357515/… – Steve0 Commented Dec 20, 2019 at 20:41
  • Are you asking how something like live editing CSS styles and how it applies to the page right away as you edit it as well as where do they get save to? If what I'm interpreting is correct, then there are several front-end web frameworks that do this, where DOM element bind to data correspond to these styles and as they change the DOM element/style changes. As for storing, they can just be store temporary in memory or localstorage if you don't want to mit to save them on the backend database. – noobius Commented Dec 20, 2019 at 20:53
  • @noobius Yes that is correct but how are they stored? For example, I have a paragraph element and I want to change the font size dynamically. After changing it, I can add #paragraph-1 { font-size: 18px; }; to <style> but what if I want to change the font size to again to the same element and also add padding. Or what if I delete the element, it should delete that style too. Are there better ways to do this? – pixie123 Commented Dec 20, 2019 at 21:24
  • @pixie123 Have you heard of Angular, Vue.js etc...? Take a look at this link and see if its description sounds like what you're trying to do. angular.io/api/mon/NgStyle While these framework make it easier to do this, you can certainly do them with pure javascript and DOM manipulation. Also how these things work is call data binding, as when the data changes (in this case your styles) it trigger the DOM to update the element. – noobius Commented Dec 20, 2019 at 21:32
  • @noobius Yes, while that could work, I already have most of the stuff built in jquery. Any solutions using jquery or pure js? – pixie123 Commented Dec 20, 2019 at 21:39
Add a ment  | 

6 Answers 6

Reset to default 6 +25

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/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>

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 plex 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>

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>

The answers here focus on the methods for building a stylesheet and adding css rules using mon 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 ponent/models.

If you look at view-centric frameworks, like React or Vue, more plex 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 ponents on the page.

So ultimately, a non-toy WYSIWYG web editor will likely treat each "element" as a ponent 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 plex 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 plex web-app/web-editor would be abstracted away.

Based on the discussion, I can suggest to use separate styles for each element id. Here is a sketch.

  <script>

  function setStyle(id, style_text) 
  {
    var style_id = "style_"  + id;
    var style_forId = "#" + id + " " + style_text;

    var styleDom = document.getElementById(style_id);

    if(!styleDom)
    {
        styleDom = document.createElement('style');
        styleDom.type = 'text/css';
        styleDom.id = style_id;
        styleDom.innerHTML = style_forId; 
        document.getElementsByTagName("head")[0].appendChild(styleDom);
    }
    else
    {
        styleDom.innerHTML = style_forId; 
    }
  }

  </script>

  <button id="myButton1" type="button" >My Button 1</button>
  <button id="myButton2" type="button" >My Button 2</button>
  <br>
  <button onclick="setStyle('myButton1', '{color:red}'); "> Set Red color for myButton1 </button>
  <br>
  <button onclick="setStyle('myButton2', '{color:red}'); "> Set Red color for myButton2 </button>
  <br>
  <button onclick="setStyle('myButton1', '{color:green}'); "> Set Green color for myButton1 </button>
  <br>
  <button onclick="setStyle('myButton2', '{color:green}'); "> Set Green color for myButton2 </button>
  <br>

Great Answers already just putting a different viewpoint out there.

Simple Version

Using CSSStyleSheet

const style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(`
  header {
    background: 'black'
  }
`, 0);

Real World

I would take this simple idea and control it through a data structure like this.

// A JS Object to control and modify CSS styles on.
const css = {
    header: {
        background: 'black',
        border: '2px green solid',
        'font-size': '12px'
    }
}

// Converts JS Object to CSS Text (This is not battle tested)
function objToCss(style) {
    return Object.entries(style).reduce((styleString, [propName, propValue]) => {
        propName = propName.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
        if (typeof propValue === 'object') {
            return `${styleString}${propName}{${objToCss(propValue)}}`;
        } else {
            return `${styleString}${propName}:${propValue};`;
        }
    }, '')
}

// Setup
const style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(objToCss(css), 0);

// Updates
css.header.border = '1px blue solid';
style.sheet.replace(objToCss(css), 0);
发布评论

评论列表(0)

  1. 暂无评论