如何设置供应商前缀 CSS 值(不是 属性 名称)|客户端
How to set vendor prefixed CSS values (NOT property names) | client-side
<edit>
我实际上猜到会发生这种情况,但在 posting 几秒钟后,我得到了一个“可能重复”的标志,这是不合适的!这个问题是 关于 CSS 值 而 不是关于 CSS 属性 名称 所以它不是重复的this or this question!!! Its also not a dup of this one 因为我要的是通用解决方案。
如果您仍然不相信或不确定这个 post 不是关于什么的,也许您可以看看这个问题的底部:“我不想要什么”和“谁没有完成工作” " </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 属性 名称上使用供应商前缀的话题已经讨论得够多了(而不是我想要的)。
注意:我也完全知道预处理器和post-处理器用作构建过程的一部分。我的整个 CSS 工作流程基于“Grunt : SASS : PostCSS : Autoprefixer”,因此 无需就此提出任何建议!
谁没有完成工作
- -prefix-free 在供应商前缀 CSS 属性 名称上做得很好,但不处理供应商前缀 CSS 值。
- 不幸的是,jQuery也是如此。
为了满足您的要求,您需要一个参考来比较当前使用的浏览器与需要哪些前缀;喜欢 caniuse. Or you could make some mixins with the CSS @supports rule,但这可能比它的价值更麻烦。
有一个现有的解决方案,autoprefixer,但它需要您使用 postcss。自述文件包含各种构建工具插件的示例。我使用 SCSS 和 autoprefixer,我实现了梦想。
如果您不确定这个主题是否与您相关,请先阅读本答案底部的“推荐|新手注意事项”部分。
感谢 Ari for his that at least pointed me in the right direction. This solution makes use of Autoprefixer,你们中的大多数人可能将其与任务运行器一起用作构建设置的一部分(对我来说也是如此)。
不幸的是,我无法获得有关如何将 Autoprefixer 作为客户端独立版本使用的信息。所以我只是浏览了一些网站,我知道他们正在做我也想完成的相同任务(即 Autoprefixer | UI, CodePen, Sassmeister and JS Bin)。
这样做的最佳资源是官方 Autoprefixer | UI 总而言之 - 实际上这没什么大不了的。所以在这里我们使用一个非常基本的模型来说明...
如何在客户端使用 Autoprefixer
实际上autoprefixer.process( sInput ).css
就是我们所需要的。
但让我们bootstrap将其转化为更真实的用例场景。
// 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 special hacks 一起出现,这可能使其成为目前可用的最可靠的跨浏览器解决方案。
魂斗罗
- Autoprefixer 伴随着 626 KB (minified) 的重负载。
推荐|新手重要注意事项
- 此解决方案仅适用于必须“即时”向网站添加 CSS 的开发人员。即便如此,仅当 CSS 包含必须带有供应商前缀的 属性 值时 (例如
linear-gradient
、radial-gradient
等.) 而不是 CSS 属性 名称(例如 background
)。对于依赖跨浏览器 CSS3 功能的插件作者来说,很可能就是这种情况。
- 另一种情况是,如果您无法通过 JavaScript.
控制客户端以外的实际标记
- 在大多数情况下,注意供应商前缀的 CSS 属性 名称就足够了(jQuery css method 也这样做)。
- For any CSS that is delivered directly to the client (the browser) it is strongly recommended to prepare the CSS in your build setup BEFORE IT IS DELIVERED.
- 如果您仍然不确定,很可能有更好的解决方案。
PS:仔细检查所有资源后,我发现 https://github.com/postcss/autoprefixer#javascript 也指向正确的方向。
你可以迭代document.styleSheets
,得到CSSStyleDeclaration
的"cssRules"
和"style"
属性,如果属性的值匹配一个变量,例如 RegExp
,使用 .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;
}
也许 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;
};
不同于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;
<edit>
我实际上猜到会发生这种情况,但在 posting 几秒钟后,我得到了一个“可能重复”的标志,这是不合适的!这个问题是 关于 CSS 值 而 不是关于 CSS 属性 名称 所以它不是重复的this or this question!!! Its also not a dup of this one 因为我要的是通用解决方案。
如果您仍然不相信或不确定这个 post 不是关于什么的,也许您可以看看这个问题的底部:“我不想要什么”和“谁没有完成工作” " </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 属性 名称上使用供应商前缀的话题已经讨论得够多了(而不是我想要的)。
注意:我也完全知道预处理器和post-处理器用作构建过程的一部分。我的整个 CSS 工作流程基于“Grunt : SASS : PostCSS : Autoprefixer”,因此 无需就此提出任何建议!
谁没有完成工作
- -prefix-free 在供应商前缀 CSS 属性 名称上做得很好,但不处理供应商前缀 CSS 值。
- 不幸的是,jQuery也是如此。
为了满足您的要求,您需要一个参考来比较当前使用的浏览器与需要哪些前缀;喜欢 caniuse. Or you could make some mixins with the CSS @supports rule,但这可能比它的价值更麻烦。
有一个现有的解决方案,autoprefixer,但它需要您使用 postcss。自述文件包含各种构建工具插件的示例。我使用 SCSS 和 autoprefixer,我实现了梦想。
如果您不确定这个主题是否与您相关,请先阅读本答案底部的“推荐|新手注意事项”部分。
感谢 Ari for his
不幸的是,我无法获得有关如何将 Autoprefixer 作为客户端独立版本使用的信息。所以我只是浏览了一些网站,我知道他们正在做我也想完成的相同任务(即 Autoprefixer | UI, CodePen, Sassmeister and JS Bin)。
这样做的最佳资源是官方 Autoprefixer | UI 总而言之 - 实际上这没什么大不了的。所以在这里我们使用一个非常基本的模型来说明...
如何在客户端使用 Autoprefixer
实际上autoprefixer.process( sInput ).css
就是我们所需要的。
但让我们bootstrap将其转化为更真实的用例场景。
// 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 special hacks 一起出现,这可能使其成为目前可用的最可靠的跨浏览器解决方案。
魂斗罗
- Autoprefixer 伴随着 626 KB (minified) 的重负载。
推荐|新手重要注意事项
- 此解决方案仅适用于必须“即时”向网站添加 CSS 的开发人员。即便如此,仅当 CSS 包含必须带有供应商前缀的 属性 值时 (例如
linear-gradient
、radial-gradient
等.) 而不是 CSS 属性 名称(例如background
)。对于依赖跨浏览器 CSS3 功能的插件作者来说,很可能就是这种情况。 - 另一种情况是,如果您无法通过 JavaScript. 控制客户端以外的实际标记
- 在大多数情况下,注意供应商前缀的 CSS 属性 名称就足够了(jQuery css method 也这样做)。
- For any CSS that is delivered directly to the client (the browser) it is strongly recommended to prepare the CSS in your build setup BEFORE IT IS DELIVERED.
- 如果您仍然不确定,很可能有更好的解决方案。
PS:仔细检查所有资源后,我发现 https://github.com/postcss/autoprefixer#javascript 也指向正确的方向。
你可以迭代document.styleSheets
,得到CSSStyleDeclaration
的"cssRules"
和"style"
属性,如果属性的值匹配一个变量,例如 RegExp
,使用 .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;
}
也许 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;
};
不同于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;