我想在运行时动态生成css
。
最初我使用过sass
并定义了一些变量并使用了这些变量。但是必须首先从scss
生成css。 Sass让我可以灵活地使用变量和函数,但我仍然无法通过javascript
在运行时更改它们。
一种方法是通过javascript
更改内联样式,但这种方法并不完全灵活。
document.getElementById("myDiv").style.color = "red";
我不想在上面做,也不想通过javascript附加任何<style>
属性。
我想使用javascript但不能用于修改每个样式属性。我希望使用css和javascript实现scss效果,但在运行时即动态。
E.g。假设我从 ajax调用获得了color
信息,现在我想根据立即收到的color
更改网站的整个主题,而无需重新启动或重新部署我的应用程序。
e.g
在scss中完成
.myClass {
background:$color;
// Update color value dynamically at run-time
}
甚至是可能还是我在错误的方向思考!
答案 0 :(得分:1)
扩展链接的&#34;可能的副本中提供的信息&#34;问题,您可以轻松设置&#34;默认&#34;页面CSS文件中的样式集,然后根据AJAX调用的响应创建包含任何覆盖的内联<style>
元素。只要元素/ class / id定义在两个位置(即CSS文件和内联样式部分)中相同,特异性将导致内联定义覆盖CSS。
因此,使用您的示例,您的静态CSS文件将包含:
.myClass {
background: #FFFFFF;
}
。 。 。如果AJAX调用失败,则存在默认值,然后动态创建的<style>
部分将包含:
.myClass {
background: THE_AJAX_RESPONSE_VALUE;
}
。 。 。这将覆盖默认值。
根据您的示例JSON,这将非常简单。 。 。你将遍历JSON的每个顶级属性并创建它:
KEY_NAME {
. . .
}
然后,在该块中,循环遍历该属性中的每个属性,并添加键和值以创建样式定义:
KEY_NAME {
key1: value1,
key2: value2,
. . .
keyN: valueN
}
您还可以使用StyleSheet和CSSStyleSheet接口来访问现有样式表中的规则,但是,假设它使用类似于数组的结构,则意味着循环遍历所有CSS定义以找到您想要的并改变它。如何做到这一点的一个例子可以在另一个SO问题的答案中找到:Is it possible to alter a CSS stylesheet using JavaScript? (NOT the style of an object, but the stylesheet itself)
在这两种方法之间,创建一个重要的<style>
部分似乎更容易。
答案 1 :(得分:1)
由于JSON同时具有元素名称和相关样式,因此刷新页面样式表(vs内联元素样式)可能是最快的,因为它使用innerHTML
并且只需要单个DOM查找。
您需要循环使用JSON来创建CSS兼容字符串,然后将其转储到onpage样式元素中。您可以通过将现有innerHTML
与新CSS字符串连接来附加CSS。为简单起见,我在样式表中添加了一个ID,但您也可以在需要时生成样式元素。
var StringifiedAjaxStyleObject = "h1 {background-color: #ecc; color: #633}";
var styleSheet = document.getElementById("style-update");
// some additional fake test style returns...
var testStyle1 = "h1 {background-color: #ccc; color: #333}";
var testStyle2 = "h1 {background-color: #667; color: #bbc}";
var testStyle3 = "h1 {background-color: #fee; color: #b00}";
// some fake ajax returns...
window.setTimeout(function() {
styleSheet.innerHTML = StringifiedAjaxStyleObject;
}, 1000);
window.setTimeout(function() {
styleSheet.innerHTML = testStyle1;
}, 2000);
window.setTimeout(function() {
styleSheet.innerHTML = testStyle2;
}, 3000);
window.setTimeout(function() {
styleSheet.innerHTML = testStyle3;
}, 4000);
&#13;
/* base styles ... */
h1 {
padding: 5px;
background-color: #eef;
color: #007
}
&#13;
<!-- empty stylesheet -->
<style id="style-update" type="text/css" rel="stylesheet"></style>
<h1>Hi, mom</h1>
<button>Update Styles<button>
&#13;
修改强>
这是一个基于评论中JSON对象的更真实的版本。通过按钮触发它。
var styleSheet = document.getElementById("style-update");
var btn = document.querySelector('button');
btn.addEventListener("click", updateStyles);
function updateStyles() {
var StringifiedAjaxStyleObject
, newCSS
, ajaxReturn
;
// ...your ajax method to get the new styles...
// on success...
ajaxReturn = {
".base": {
"background-color": "#b83605",
"border-color": "#543927",
"color": "gray",
"text-shadow": "0 -1px 0 rgba(0, 0, 0, 0.15)"
},
".overlay": {
"background": "rgba(76, 65, 80, 0.2)",
"color" : "#ddd"
}
};
// Convert the object to a string
newCSS = cssStringFromJson(ajaxReturn);
// Update the stylesheet
styleSheet.innerHTML = newCSS;
}
function cssStringFromJson(cssJSON) {
var styleStr = "",
i, j;
for (i in cssJSON) {
styleStr += i + " {\n"
for (j in cssJSON[i]) {
styleStr += "\t" + j + ": " + cssJSON[i][j] + ";\n"
}
styleStr += "}\n"
}
return styleStr;
}
&#13;
/* base styles ... */
.base {
border: 1px solid #ccf;
background-color: #eef;
color: #000;
padding: 15px;
}
.overlay {
padding: 5px 15px;
background: rgba(96, 95, 180, 0.2);
}
body {
font-family: sans-serif;
}
button {
margin-top: 1em;
font-size: 1em;
}
&#13;
<!-- empty stylesheet -->
<style id="style-update" type="text/css" rel="stylesheet"></style>
<div class="base">
<p>.base</p>
<div class="overlay">
<p>.overlay</p>
</div>
</div>
<button>Update Styles</button>
&#13;
答案 2 :(得分:1)
玩弄这个和CSS变量。我正在添加第二个答案,因为它与我的第一个答案的方法非常不同,它更符合你原来的问题(用JS更新CSS变量)。
但是......不要这样做。 :) IE中的浏览器支持&lt;边缘不存在,它几乎肯定比更新页面上的<style>
元素要慢,尽管我还没有测试过它。这个jsperf测试各种样式更新方法。它不包含innerHTML
单个style
元素(可能是最快的),但您可以看到以下CSS DOM方法比其他方法慢。
// get the stylesheet
// array position depends on how many style sheets you're loading.
// adjust as needed.
var sheet = document.styleSheets[0];
// simplest method: insertRule()
// setTimeout only for demo so you can see the change
window.setTimeout(function(){
// @media all {} is a trick to insert more than one
// selector and/or properties at once. Otherwise it's:
// sheet.insertRule(":root", "--header-color: green"); ...repeat...
sheet.insertRule("@media all { :root { --header-color: green; --main-color: orange; } }", 1);
}, 1200);
// SAFER method via addCSSRule.
// button and getAjaxStyles are just placeholders, obviously
var btn = document.querySelector('button');
btn.addEventListener("click", getAjaxStyles);
function getAjaxStyles() {
// success callback... break apart the json and update the CSS variables
addCSSRule(sheet, ":root", "--header-color: orange");
addCSSRule(sheet, ":root", "--main-color: blue");
addCSSRule(sheet, ":root", "--alt-color: red");
addCSSRule(sheet, ":root", "--borderColorA: lavender");
// or go with a single big string. definitely faster:
// addCSSRule(sheet, ":root", "--alt-color: red; --borderColorA: #0ff; ")
}
// Credit for addCSSRule() goes to Diego Flórez in a comment on
// https://davidwalsh.name/add-rules-stylesheets
var addCSSRule = function(sheet, selector, rules) {
//Backward searching of the selector matching cssRules
var index = sheet.cssRules.length - 1;
for (var i = index; i > 0; i--) {
var current_style = sheet.cssRules[i];
if (current_style.selectorText === selector) {
//Append the new rules to the current content of the cssRule;
rules = current_style.style.cssText + rules;
sheet.deleteRule(i);
index = i;
}
}
if (sheet.insertRule) {
sheet.insertRule(selector + "{" + rules + "}", index);
} else {
sheet.addRule(selector, rules, index);
}
return sheet.cssRules[index].cssText;
}
/* Set initial CSS variables */
:root {
--header-color: #333;
--main-color: #888;
--alt-color: #bbb;
--borderColorA: #ccc;
}
h1 {
color: var(--header-color);
}
p {
border-bottom: 1px solid var(--borderColorA);
color: var(--main-color);
}
p+p {
color: var(--alt-color);
}
<h1>header</h1>
<p>paragraph 1</p>
<p>paragraph 2</p>
<button>Update CSS Variables</button>
答案 3 :(得分:0)
您可以尝试角度模板。 它会打破你以前的sass,但它会在以后解决。