【问题标题】:Convert css styles to inline styles with javascript keeping the style units使用 javascript 将 css 样式转换为内联样式,保持样式单元
【发布时间】:2020-06-09 22:28:17
【问题描述】:

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

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

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

我进行了研究,发现了this thread,这也将我带到了this code

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

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

这适用于 font-size:24pxma​​rgin:0 15px 等 css 属性。我遇到的问题是当我使用 px 以外的单位时。例如,如果我正在尝试制作具有 width:50% 的东西。 getComputedStyle() 将 50% 转换为 50% 当前使用的实际像素数。

notes section of the MDN web docs 我看到这是预期的行为。虽然我不太清楚最后一行是什么意思。

...布局前值和布局后值之间的示例差异包括 宽度或高度的百分比分辨率,因为它们将是 替换为仅用于已使用值的等效像素。

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

.container{width:50%;}

<div class="container">

变成这样的

<div class="container" style="width:50%">

有人知道完成这种转换的方法吗?

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

【问题讨论】:

  • 我建议将您的 CSS 内容作为 <style> 元素放入 <header>,而不是执行这种类型的 内联,因为它可能会对性能产生负面影响.
  • 我打算推荐 Yevgen Gorbunkov 推荐的东西。另外,我想确保您了解内联样式的风险:stackoverflow.com/questions/41925390/…
  • 您能否在此处包含代码的相关部分,以便可以提供帮助的人不必在其他帖子中浏览代码?另外,您的编辑器有多少访问权限? @YevgenGorbunkov 和 @ControlAltDel:我的猜测是 OP 正在使用 CMS,它限制只能编辑页面的特定区域,因此他们可能无法访问 <header> 元素和 <style> 元素甚至可能被剥离出...尤其是他们说有视觉呈现标准(在这种情况下,您希望 CMS 设置有足够的样式,但无论如何:) ...)
  • 感谢您的建议,但正如 FluffyKitten 所说,我们使用的 CMS 仅允许 RTE 编辑(并访问 html 进行编辑)。没有标题,没有 css 样式,这是一个非常有限的系统,但它是我们所拥有的。我将编辑帖子以使其更清晰。

标签: javascript html css


【解决方案1】:

找不到使用内置 getComputedStyle() 的任何方法。它还返回了太多我不感兴趣的属性。所以我想出了一个不同的方法。基本上是使用相同的函数来循环遍历一个元素(可能还有它的所有子元素),并使用Element.matches() 来获取适用于该元素的所有 css 规则并应用样式表中指定的属性。

我稍微修改了this answer 以从样式表中获取规则。

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

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;
}

【讨论】:

    猜你喜欢
    • 2014-09-25
    • 2013-06-26
    • 1970-01-01
    • 2011-05-30
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多