如何设置带有供应商前缀的 CSS 值(不是属性名称) |客户端

How to set vendor prefixed CSS values (NOT property names) | client-side

提问人:Axel 提问时间:9/20/2017 最后编辑:Axel 更新时间:2/3/2021 访问量:1927

问:

<edit>我实际上猜到了这会发生,但是在发布几秒钟后,我收到了一个“可能重复”的标志,这是不合适的!这个问题是关于CSS值的,而不是关于CSS属性名称的,所以它不是这个这个问题的重复!!它也不是这个的复制品,因为我要求一个通用的解决方案。
如果你仍然不相信或不确定这篇文章不是关于什么的,也许你可以看看这个问题的底部:“我不在寻找什么”和“谁没有完成工作”
</edit>

如果需要,有没有办法通过 JavaScript 在客户端设置适当的供应商前缀 CSS 值?

我在找什么

例如:background: -prefix-linear-gradient{...}

我很想得到一个关于如何通过 JavaScript 在客户端设置供应商前缀的 CSS 值的通用解决方案。除此之外,问题在于如何在客户端执行此操作,而不是作为构建过程的一部分(例如 POSTcss)。

但我也很感激任何提示

  • 完成工作的 JavaScript/jQuery 插件或
  • 其他资源可以让我自己弄清楚。

正如你所看到的,我已经自己给出了答案。但我仍在寻找更好的解决方案,因为 Autoprefixer 附带了大约 626 KB 的重负载!


使用案例场景

/*
Unprefixed version of "linear-gradient" will only work for
browsers: IE10+, FF16+, Chrome26+, Opera12+, Safari7+.
So how to generate a prefixed version on the fly if necessary?
*/

var aVal = ['linear-gradient(to bottom, #fefefe 0%,#aaaaaa 100%)', 'linear-gradient(to bottom, #aaaaaa 0%,#fefefe 100%']
    style = document.getElementsByTagName('BODY')[0].style,
    i = 0;
(function toggle () {

  if ( i++ ) { i = 0; }
  style.background = aVal[ i ];
  /* here we need something like:
  style.background = parseForPrefix( aVal[ i ] );
  */
  setTimeout(toggle, 2000)

})();
* {
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}
Unprefixed version of "linear-gradient" will only work for<br>
browsers: IE10+, FF16+, Chrome26+, Opera12+, Safari7+.<br>
So how to generate a prefixed version on the fly if nessecary?

或者想象一下这样的事情

jQuery('head').append('<style>body{background:linear-gradient(...)}</style>')

这应该是这样的

jQuery('head').append('<style>'
    + parseForPrefix('body{background:linear-gradient(...)}') +
'</style>')

相反。


我不是在寻找什么

例如:-prefix-transform: translate{...}

如何在 CSS 属性名称上使用供应商前缀这个主题已经讨论得足够多了(而不是我所追求的)。
注意:我也完全了解作为构建过程一部分使用的预处理器和后处理器。我的整个CSS工作流程都是基于“咕噜咕噜:SASS:PostCSS:Autoprefixer”的,所以没有必要给出任何建议!


谁没有完成工作

  • -prefix-free 在以供应商为前缀的 CSS 属性名称上做得很好,但不处理以供应商为前缀的 CSS 值。
  • 不幸的是,jQuery也是如此。
JavaScript HTML CSS 客户端 供应商前缀

评论

0赞 Blazemonger 9/20/2017
stackoverflow.com/a/39500379/901048
0赞 Axel 9/20/2017
亲爱的@Blazemonger请花点时间再读一遍我的问题。我的问题不是关于属性名称,而是关于值。jQuery不处理这个问题。我什至在我的问题中强调了这一点 - 所以你可能没有仔细阅读(这很正常)!
0赞 Blazemonger 9/20/2017
如果需要,Jquery 将自动设置适当的供应商前缀。它不是一个纯粹的 JavaScript 解决方案,但它是 JavaScript。.css()
1赞 Axel 9/20/2017
@Blazemonger 这不是真的!jQuery 为属性名称(如“background”、“display”等)添加前缀,但不包括“linear-gradient”、“flex”等值。你不明白吗?css_selector { property-name: value }。AGAIN: “property-name”: 将以 “jQuery” 和 “-prefix-free” 为前缀 |“value”:不会以 jQuery 或 -prefix-free 为前缀。
1赞 Ilya Streltsyn 10/2/2017
关于您的示例:已更改其语法(添加了“to”关键字和“magic angles”,更改了角度方向),因此仅将前缀添加到现代值可能无法在目标旧浏览器中工作(或者至少无法按预期工作)。解决方案是否应该考虑此类更改?linear-gradient()

答:

3赞 Ari 9/20/2017 #1

为了完成您的要求,您需要一个参考来将当前使用的浏览器与所需的前缀进行比较;像Caniuse一样。或者你可以用CSS@supports规则做一些混合,但这可能比它的价值更麻烦。

有一个现有的解决方案,autoprefixer,但它需要你使用postcss。README 包含各种构建工具插件的示例。我使用 SCSS 和 autoprefixer,我正在实现梦想。

评论

0赞 Axel 9/20/2017
Jepp sure - 我在我的“咕噜声 |SASS“构建过程,但我没有考虑过使用它”post“而不是”pre”。另外:你有没有关于如何让它快速运行的提示。
0赞 Ari 9/20/2017
老实说,我只是设置了浏览器版本,不考虑它。祝你好运。
0赞 Axel 9/20/2017
啊,好吧;我们还没有走在同一条轨道上。我的意思是如何在已经部署的站点上使用 autprefixer,而不是作为构建设置的一部分......如果你有时间,也许你可以再看看我的问题 - 请参阅我的更新“用例场景”,它应该很清楚!
1赞 Axel 10/3/2017
郑重声明:这个答案根本不是 OP 的解决方案,因为它与客户端解决方案无关。
0赞 Axel 9/25/2017 #2

如果您不确定此主题是否与您相关,请阅读“建议 |新手注意事项“首先在此答案的底部。


感谢 Ari回答,至少为我指明了正确的方向。此解决方案利用了 Autoprefixer,你们中的大多数人可能会将其与任务运行程序一起用作构建设置的一部分(对我来说也是如此)。

不幸的是,我无法获得有关如何将 Autoprefixer 用作客户端独立版本的信息。因此,我只是看了一下网站,我知道它们正在执行我也想要实现的相同任务(即 Autoprefixer |UICodePenSassmeisterJS Bin)。

这样做的最佳资源是官方的 Autoprefixer |UI 总而言之 - 实际上这没什么大不了的。因此,在这里,我们使用一个非常基本的模型,该模型能够说明......

如何使用 Autoprefixer 客户端

实际上这就是我们所需要的。autoprefixer.process( sInput ).css

但是,让我们将其引导到更真实的类似生活的用例场景中。

// Autoprefixer | ready to rumble
// http://autoprefixer.github.io/assets/code.js?v=1499371172398732683
var sInput  = document.getElementById("AutoprefixerIn").innerHTML,
    sOutput = autoprefixer.process( sInput, {}, {browsers: ["> 0%"]} ).css;

document.getElementById("AutoprefixerOut").innerHTML = sOutput;
document.getElementById("console-AutoprefixerIn").innerHTML += sInput;
document.getElementById("console-AutoprefixerOut").innerHTML += sOutput;
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Autoprefixer.js | Client-Side</title>
<!-- give snippet a better appearance -->
    <style>*{margin:0;padding:0;height:100%;width:100%;}pre{border:2px solid #fff;box-sizing:border-box;overflow:auto;width:50%;}</style>

<!-- Autoprefixer | source, input -->
<!-- IE10+, FF16+, Chrome26+, Opera12+, Safari7+ | prefix for others -->
    <style id="AutoprefixerIn">
        body {
            background: linear-gradient(to bottom, #fefefe 0%,#aaaaaa 100%);
            display: flex;
        }
    </style>
<!-- Autoprefixer | destination, output -->
    <style id="AutoprefixerOut"></style>

<!-- Autoprefixer | load library -->
<!-- view-source:http://autoprefixer.github.io/ | line: 140 -->
    <script src="https://rawgit.com/ai/autoprefixer-rails/master/vendor/autoprefixer.js" crossorigin="anonymous"></script>
    <script> // online fallback in case github is off
        window.autoprefixer || document.write('<script src="https://wzrd.in/standalone/autoprefixer@latest">\x3C/script>');
    </script>
</head>
<body>
<pre id="console-AutoprefixerIn">
    /* display unprefixed original input coming from "style#AutoprefixerIn" */
</pre>
<pre id="console-AutoprefixerOut">
    /* display dynamically generated and prefixed output coming from "style#AutoprefixerOut" */
</pre>

专业版

  • Autoprefixer 附带了 27 种特殊技巧,这可能使其成为目前可用的最无懈可击的跨浏览器解决方案。

魂斗罗

  • Autoprefixer 带有一个沉重的有效载荷,即 626 KB(缩小)。

推荐 |新手须知

  • 此解决方案仅适用于必须“即时”将 CSS 添加到网站的开发人员。即便如此,也只有当 CSS 包含必须以供应商为前缀的属性值(例如 、 等)而不是 CSS 属性名称(例如 )。对于依赖跨浏览器 CSS3 功能的插件作者来说,情况很可能就是这样。linear-gradientradial-gradientbackground
  • 另一种情况是,如果您无法通过 JavaScript 控制客户端以外的实际标记。
  • 在大多数用例中,处理以供应商为前缀的 CSS 属性名称就足够了(jQuery css 方法也可以这样做)。
  • 对于直接交付给客户端(浏览器)的任何 CSS,强烈建议在交付之前在构建设置中准备 CSS。
  • 如果您仍然不确定,很可能有更好的解决方案适合您。

PS:在仔细检查所有资源后,我意识到 https://github.com/postcss/autoprefixer#javascript 也指向了正确的方向。

评论

0赞 guest271314 9/30/2017
请注意,不需要库,请参阅 stackoverflow.com/a/37364536
0赞 Axel 9/30/2017
@guest271314感谢您的评论。如果我错了,请纠正我,但您的解决方案是关于前缀 CSS 属性名称(如、、等)——不是吗?我的问题是关于CSS值(如,等)!transformborder-radiustransitionlinear-gradientflex
0赞 guest271314 9/30/2017
“I would love to get a generic solution on how to set vendor prefixed CSS values client-side via JavaScript.” 是什么意思?
0赞 Axel 9/30/2017
这意味着该解决方案可以在任何情况下使用,并且不限于一个浏览器系列、一个浏览器时代或一些 CSS 值组(如梯度组)。如果你看一下我的答案(也许运行代码片段),你会发现这是一个非常通用的解决方案。Autoprefixer 甚至利用了 27 个特殊的技巧,试图使 CSS“尽可能跨浏览器”。实际上,我对这个解决方案非常满意 - 如果没有沉重的有效载荷。Autoprefixer 不是为在客户端运行而设计的(除非它能够运行)。
0赞 Axel 9/30/2017
所以有效载荷并不那么重要。因此,也许有人知道一个更轻量级的工具可以做类似的事情。或者也可以对 Autoprefixer 本身进行特殊构建......但是,我@guest271314对,您的解决方案对 CSS 值没有用,但对 CSS-property-names(请清除)没有用???
1赞 guest271314 10/1/2017 #3

如果属性的值与变量匹配,则可以迭代 、 get 和 属性,例如,用于在 value 前面添加前缀document.styleSheets"cssRules""style"CSSStyleDeclarationRegExp.replace()

const [values, prefix, re = new RegExp(values.join("|"))] = [
  ["linear-gradient","flex"], "-webkit-"
];

[...document.styleSheets]
.forEach(({cssRules}) => {
  const [[{style}], styles = Object.entries(style)] = [cssRules];
  if (cssRules.length && styles.some(([, prop]) => 
      re.test(prop))) {
    console.log(cssRules[0].cssText);
    styles
    .forEach(([key, prop]) => {
      if (re.test(prop)) style[key] = prop.replace(prop, prefix + prop)});
    console.log(cssRules[0].cssText);
  }
})
body {
  background: linear-gradient(to bottom, #fefefe 0%, #aaaaaa 100%);
  display: flex;
  flex-direction: row;
}

评论

0赞 Axel 10/1/2017
到目前为止看起来真的很有希望 - 也曾朝这个方向考虑过。您能否修改一下它看起来更像我回答中的片段。它不是关于外观,而是关于将原始CSS与修改后的CSS进行比较。会很棒。
0赞 guest271314 10/1/2017
@Axel 在堆栈片段中呈现结果应该无关紧要。属性值在对象处设置。您可以包括 before 和 调用以显示 before before set 值。console.log(console.log(cssRules[0].cssText)).filter().forEach()
0赞 Axel 10/1/2017
你是对的。在堆栈片段中呈现结果无关紧要。但无论如何,视觉反馈都很好。
1赞 Jess 8/20/2018 #4

也许 Modernizr 可以解决这个问题,比如

// returns: -webkit-linear-gradient(left, red, red)
Modernizr.prefixedCSSValue('background', 'linear-gradient(left, red, red)')

工作原理:

// prefixedCSSValue is a way test for prefixed css properties (e.g. display: -webkit-flex)
// @credits modernizr v3.6.0 | Build https://modernizr.com/download?-prefixedcssvalue-dontmin
Modernizr.prototype.prefixedCSSValue = function(prop, value) {
    var result = false;
    var elem = createElement('div'); // basically: document.createElement.apply(document, ['div'])
    var style = elem.style;

    if (prop in style) {
        var i = domPrefixes.length; // domPrefixes === [ "moz", "o", "ms", "webkit" ] or []

        style[prop] = value;
        result = style[prop];

        while (i-- && !result) {
            style[prop] = '-' + domPrefixes[i] + '-' + value;
            result = style[prop];
        }
    }

    if (result === '') {
        result = false;
    }

    return result;
};

评论

0赞 Axel 8/20/2018
这很有趣。就在几天前,我才知道 s 方法。只是没有足够的时间自己回答;但它实际上在我的待办事项清单上。ModernizrprefixedCSSValue
0赞 Jess 8/22/2018
@Axel我将使用 emotion 来处理客户端的动态样式转换,它会自动为一些 css 值添加前缀。和使用时不Modernizremotion
0赞 Axel 8/22/2018
感谢分享@Jess。我希望你对我的编辑感到满意,以增强你的答案。顺便说一句,你有没有看过我使用 Autprefixer 的答案?与其他解决方案相比,它具有非常强大的有效载荷,但也有一些很大的优势(例如 27 个特殊黑客)。祝你有美好的一天:)
0赞 Jess 8/23/2018
@Axel 感谢您的编辑。我已经阅读了您的答案,它做得很好。正如你所指出的,它的文件大小很大。由于我的页面是为普通的真实用户准备的,因此在这种情况下我无法使用它。它最适合内部系统autoprefixer
2赞 Michael Rafailyk 9/21/2019 #5

elem.style.background = 'linear-gradient{...}'

你可以使用elem.style.cssText = 'background:linear-gradient{...}; ...'

这种方法允许您一次向元素添加多个样式,当然是内联的。只会写入浏览器理解的属性。因此,只需采用当前的内联样式(字符串,而不是样式对象)或创建空字符串并添加自己的样式即可。elem.getAttribute('style')|| ''

let elem = document.getElementById('elem');
let styleAdd = 'background: -prefix-linear-gradient{...}; background: linear-gradient{...};';
elem.style.cssText = (elem.getAttribute('style') || '') + styleAdd;

评论

0赞 Michael Rafailyk 9/21/2019
@quicklikerabbit感谢您的建议!我评论了我的想法。