使用javascript将css样式转换为内联样式,并保留样式单位

使用javascript将css样式转换为内联样式,并保留样式单位,javascript,html,css,Javascript,Html,Css,我们有一个公司内容管理系统,允许富文本编辑/html标记,但不允许以任何方式上载、附加或使用标题元素或样式表。它提供了一些富文本编辑控件,还提供了对源html的访问,但只针对html片段——没有头,没有体。我们也无法访问在页面上显示这些标记的整个系统。设置内容样式的唯一方法是通过元素上的内联样式属性。这是最好的,也不漂亮,但这就是我们所拥有的,我正努力在糟糕的情况下做到最好 我们也有高标准的视觉表现,并希望能够快速生产和修改/更新内容,并保持它好看。使用系统很难正确应用格式。对于任何试图用RTE

我们有一个公司内容管理系统,允许富文本编辑/html标记,但不允许以任何方式上载、附加或使用标题元素或样式表。它提供了一些富文本编辑控件,还提供了对源html的访问,但只针对html片段——没有头,没有体。我们也无法访问在页面上显示这些标记的整个系统。设置内容样式的唯一方法是通过元素上的内联样式属性。这是最好的,也不漂亮,但这就是我们所拥有的,我正努力在糟糕的情况下做到最好

我们也有高标准的视觉表现,并希望能够快速生产和修改/更新内容,并保持它好看。使用系统很难正确应用格式。对于任何试图用RTE标记一段或两段以上内容的人,你可能知道我的意思。看起来我们应该有一个不同的系统,但是以前有人在大公司工作过吗?只是说说而已

我们确实可以访问另一个位置,在那里我们可以“编写”和“存储”实际样式的内容,然后将其“编译”到另一个系统中。换句话说,我们可以使用css和最佳实践进行创作/设计,然后运行一些代码,将这些元素、类和id格式转换为内联样式

我做了研究,发现了这一点,也让我找到了答案

这两种方法都非常有助于探索解决方案,但我遇到了一个问题。这些解决方案使用javascriptgetComputedStyle()方法。对于属性,还有一些其他选项,可以只查看其他属性,也可以对元素提供的子元素进行递归,但基本上可以归结为这一点。(由于getComputeStyle返回的是一个对象而不是数组,因此还有一个prototype/polyfill,允许使用forEach对对象进行迭代,但这些都不是我面临的问题的一部分。)

const computedStyle=getComputedStyle(元素); computedStyle.forEach(属性=>{ element.style[property]=computedStyle.getPropertyValue(属性); });

这适用于css属性,如字体大小:24px边距:0 15px。我遇到的问题是当我使用px以外的设备时。例如,如果我试图制作宽度为50%的东西。getComputedStyle()将50%转换为50%当前使用的实际像素数

在我看来,这是预期的行为。虽然我不太清楚最后一行是什么意思

…布局前和布局后值之间的示例差异包括 宽度或高度百分比的分辨率,如下所示 替换为仅用于已用值的等效像素

所以我要做的是转换成这样的东西

.container{宽度:50%;}

像这样的事情

有人知道如何完成这种类型的转换吗


PS:如果重要的话,我们将在css中使用更基本的属性——没有转换、网格、前缀等。如果这告诉你什么的话,我们仍然需要支持IE11。我们不需要考虑每种边缘情况或浏览器。只是一些基本的东西,使我们所有的H1看起来都一样。

无法使用内置的getComputedStyle()实现这一点。它还返回了太多我不感兴趣的属性。所以我想出了一个不同的方法。基本上是使用同一个函数来循环一个元素(可能还有它的所有子元素),以及获取应用于该元素的所有css规则并应用样式表中指定的属性

为了从样式表中获取规则,我做了一些修改

还有一个额外的好处,我们可以从所有文档样式表中提取,也可以从准备代码进入内容管理系统的富文本编辑器所需的特定样式表中提取

function applyInline(element, recursive = true) {

  if (!element) {
    throw new Error("No element specified.");
  }

  const matches = matchRules(element);

  // we need to preserve any pre-existing inline styles.
  var srcRules = document.createElement(element.tagName).style;
  srcRules.cssText = element.style.cssText;

  matches.forEach(rule => {
    for (var prop of rule.style) {

      let val = srcRules.getPropertyValue(prop) || rule.style.getPropertyValue(prop);
      let priority = rule.style.getPropertyPriority(prop);

      element.style.setProperty(prop,val,priority);
    }
  });

  if (recursive) {
    element.children.forEach(child => {
      applyInline(child, recursive);
    });
  }
}

function matchRules(el, sheets) {
  sheets = sheets || document.styleSheets;
  var ret = [];

  for (var i in sheets) {
    if (sheets.hasOwnProperty(i)) {
      var rules = sheets[i].rules || sheets[i].cssRules;
      for (var r in rules) {
        if (el.matches(rules[r].selectorText)) {
          ret.push(rules[r]);
        }
      }
    }
  }
  return ret;
}

我建议您将CSS内容作为
元素放入
中,而不是进行这种类型的内联,因为它可能会对性能产生负面影响。另外,我想确保您知道内联样式的风险:您能在这里包含代码的相关部分吗?这样ppl就不必在其他帖子中搜索代码了?另外,您在编辑器中有多少访问权限@YevgenGorbunkov&@ControlAltDel:我猜OP使用的是CMS,它限制了对页面特定区域的编辑权限,因此他们可能无法访问
元素,
元素甚至可能被剥离。。。特别是当他们说有视觉表现的标准时(在这种情况下,你希望CMS设置有足够的样式,但无论如何:)…)谢谢你的建议,但正如FluffyKitten所说,我们使用的CMS只允许RTE编辑(以及访问html进行编辑)。没有标题,没有css样式,这是一个非常有限的系统,但它是我们所拥有的。我会编辑这篇文章,让它更清楚一点。