将 CSS 对象转换为样式标签
Posted
技术标签:
【中文标题】将 CSS 对象转换为样式标签【英文标题】:Convert CSS-Object to Style Tag 【发布时间】:2017-05-09 06:18:02 【问题描述】:有时我不得不以编程方式将 CSS 样式添加到 DOM(如果你需要一个理由:想象一下编写一个带有自己的样式但应该只包含一个 *.js 文件的小型 ui 小部件以便更轻松处理)。在这种情况下,我更喜欢在我的脚本代码中使用对象表示法定义样式,而不是一个混合规则、属性和标记的大字符串。
var thumbHoverStyle =
"background-color": "rgba(211, 211, 211, 0.5)",
"cursor": "pointer"
;
对
var thumbHoverStyle = "<style> .thumb:hover background-color: rgba(211, 211, 211, 0.5); cursor: pointer; </style>";
这样的 css 对象可以很容易地与 JQuery's .css() function 一起使用,但是一旦我想设置 css pseudo-class 的样式(在我的示例中为:hover),麻烦就开始了。在这种情况下,我不能使用 JQuery .css()
函数,我只能在我的 DOM 中插入相应的样式标签。
var thumbHoverStyleTag = toStyleTag( ".thumb:hover": thumbHoverStyle );
_root.append(thumbHoverStyleTag);
我用谷歌搜索和 ***ed,但找不到将我的 css 对象转换为样式标签的实用程序函数。 最后我写了自己的函数(我可能会提供它作为这个问题的答案),但我仍然想知道是否有一个库函数。 实现此目的最优雅的方法是什么?
编辑
我在 TypeScript 中的实现:
function appendPxIfNumber(value: any): string
return (typeof value === "number") ? "" + value + "px" : value;
function toStyleTag(rulesObj: any)
var combinedRules: string = "";
for (var selector in rulesObj)
var cssObject = rulesObj[selector];
var combinedProperties = "";
for (var prop in cssObject)
var value = cssObject[prop];
combinedProperties += `$prop: $appendPxIfNumber(value);` + "\n";
combinedRules += ` $selector $combinedProperties` + "\n";
return $(`<style>$combinedRules</style>`);
使用示例:
var styleTag = toStyleTag( ".thumb": thumbStyle, ".thumb:hover": thumbHoverStyle );
【问题讨论】:
【参考方案1】:我想再试一次,因为这是一个有趣的问题。
这是我整理的原生 javascript 解决方案:
var thumbStyle =
"width" : "100px",
"height" : "100px",
"text-align" : "center",
"line-height" : "100px",
"background-color": "rgb(211, 211, 211)"
;
var thumbHoverStyle =
"color" : "rgb(255,255,255)",
"background-color": "rgb(255, 0, 0)",
"cursor": "pointer"
;
var dynamicStyle = document.createElement('style');
document.head.appendChild(dynamicStyle);
var dynamicStyleSheet = dynamicStyle.sheet;
function addStyles(selector, cssStyleObject)
var properties = Object.keys(cssStyleObject);
properties.forEach(function(property)
var value = cssStyleObject[property];
var dynamicRule = selector + ' ' + property + ': ' + value + ';';
dynamicStyleSheet.insertRule(dynamicRule, dynamicStyleSheet.cssRules.length);
);
// Add styles dynamically by stating a selector and the name of a CSS Style Object
addStyles('div', thumbStyle);
addStyles('div:hover', thumbHoverStyle);
<div>Hover Me</div>
【讨论】:
不确定它是否真的很重要,但这样您将为样式中的每个属性生成并添加一个新规则,而不是一个具有 n 个属性的规则。 我不确定我是否遵循 - 请您再次解释一下吗?谢谢。 据我了解,您生成的 css 看起来像:.foo color: red; .foo background-color: white; .foo margin-left: 2px; .foo margin-right: 4px;
而不是 .foo color: red; background-color: white; margin-left: 2px; margin-right: 4px;
啊,是的,我明白了——我明白你的意思。不过修复起来相当简单。您可以将var dynamicRule = selector + ' '
的声明移到forEach
循环上方,然后循环通过dynamicRule += property + ': ' + value + '; '
【参考方案2】:
我很想:
在mouseover()
上添加thumbHoverStyle
CSS 对象;和
在mouseout()
上用thumbDefaultStyle
CSS 对象替换它
var thumbStyle =
"width" : "100px",
"height" : "100px",
"text-align" : "center",
"line-height" : "100px",
"background-color": "rgb(211, 211, 211)"
;
var thumbHoverStyle =
"color" : "rgb(255,255,255)",
"background-color": "rgb(255, 0, 0)",
"cursor": "pointer"
;
var thumbDefaultStyle =
"color" : "rgb(0,0,0)",
"background-color": "rgb(211, 211, 211)",
"cursor": "default"
;
$(document).ready(function()
$('div').css(thumbStyle);
$('input[type="checkbox"]').change(function()
if ($('input[type="checkbox"]').prop('checked'))
$('div').mouseover(function()
$(this).css(thumbHoverStyle);
);
$('div').mouseout(function()
$(this).css(thumbDefaultStyle);
);
else
$('div').mouseover(function()
$(this).css(thumbDefaultStyle);
);
$('div').mouseout(function()
$(this).css(thumbDefaultStyle);
);
);
);
div, button
display: inline-block;
margin-right: 24px;
vertical-align: top;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Hover Me</div>
<input type="checkbox" />Activate New Hover Behaviour
【讨论】:
感谢您提出的解决方案。但是我还有其他理由要找到我的问题中描述的转换器功能。 :hover 类只是一个例子。我宁愿让浏览器的渲染引擎处理元素的悬停视觉状态,也不愿编写 mouseIn/mouseOut 处理程序代码来模拟 css :hover.【参考方案3】:我的函数 toStyleTag()
背后的方法是它首先使用 for...in statement 迭代 styleTag
并检查 styleTag
hasOwnProperty() 是否是 selector
。然后我reduce() 通过在对象上执行Object.keys() 返回的数组styleTag[selector]
,我通过加入currentValue
(属性)和styleTag[selector][currentValue]]
(规则)来concat()accumulator
将:
分开。这样做可以让styles
成为property: rule
形式的字符串数组。现在这是我们需要使用insertRule() 的格式,我们使用它来将新的CSS 规则插入到当前样式表中。请注意,我正在抓取 cssRules
的长度以找到索引 + 1,以便我们可以在样式表的最后插入这条新规则,以确保它不会被覆盖。
var styleSheet = document.styleSheets[0];
function toStyleTag(styleTag)
for(var selector in styleTag)
if(styleTag.hasOwnProperty(selector))
let styles = Object.keys(styleTag[selector]).reduce(function(accumulator, currentValue)
return accumulator.concat([currentValue, styleTag[selector][currentValue]].join(':'));
, []);
styleSheet.insertRule(selector + '' + styles.join(';') + '', styleSheet.cssRules.length);
var thumbHoverStyle =
'background-color': 'rgba(211, 211, 211, 0.5)',
'cursor': 'pointer'
;
toStyleTag( '.thumb:hover': thumbHoverStyle );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="thumb">
<img src="http://placehold.it/350x350">
</div>
【讨论】:
不错。我的toStyleTag()
函数也类似,使用for..in
循环遍历输入,并将各个部分一一连接。【参考方案4】:
这是一个适用于原始样式对象的工作示例:
我会将JSON
转换为CSS
。并定义一个应该设置样式的目标请记住,没有应该设置样式的选择器......所以我添加了一个targetSelector
。
var targetSelector='.thumb:hover',
styleObj =
"background-color": "rgba(211, 211, 211, 0.5)",
"cursor": "pointer"
,
// Convert the JSON into CSS
styleTagContent = JSON.stringify(styleObj,null,'\t')
.replace(/"/g,'')
.replace(/,\n/g,';')
.replace(/\/g, ';')
$('<style>'+targetSelector+styleTagContent+'</style>').appendTo('head');
这是一个有效的Plunk,看看它是如何工作的。
【讨论】:
哦,太好了,我还没有想过使用JSON stringify
将我的css-object 转换为css 字符串。
你的方法会去掉a:beforecontent: '123'
的引用
单引号不是有效的 JSON,我猜它可能被解析为数字。但实际上不确定。以上是关于将 CSS 对象转换为样式标签的主要内容,如果未能解决你的问题,请参考以下文章
将外部 CSS 转换为内联 CSS 用于 Rails 中的邮件
CSS标签显示模式 ③ ( 标签显示模式转换 | 行内元素转换为块级元素 | 块级元素转换为行内元素 | 块级元素行内元素转换为行内块元素 )